# HG changeset patch # User zmajo # Date 1458555668 -3600 # Node ID 74e9f4b900060089e4fcd9aa49667f92cb9659db # Parent 0dc62e7c6a2976bff06ec074f08ef17bd941d0cd# Parent 2eb91276c00e3468884b7e7eb432cbb00cffec2b Merge diff -r 0dc62e7c6a29 -r 74e9f4b90006 .hgtags --- a/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -351,3 +351,4 @@ 6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108 +c870cb782aca71093d2584376f27f0cfbfec0e3a jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 .hgtags-top-repo --- a/.hgtags-top-repo Mon Mar 21 08:42:00 2016 +0100 +++ b/.hgtags-top-repo Mon Mar 21 11:21:08 2016 +0100 @@ -351,3 +351,4 @@ 54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106 4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107 c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108 +1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Mon Mar 21 08:42:00 2016 +0100 +++ b/common/autoconf/generated-configure.sh Mon Mar 21 11:21:08 2016 +0100 @@ -4005,7 +4005,7 @@ devkit) PKGHANDLER_COMMAND="sudo apt-get install build-essential" ;; openjdk) - PKGHANDLER_COMMAND="sudo apt-get install openjdk-7-jdk" ;; + PKGHANDLER_COMMAND="sudo apt-get install openjdk-8-jdk" ;; alsa) PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) @@ -4026,7 +4026,7 @@ devkit) PKGHANDLER_COMMAND="sudo yum groupinstall \"Development Tools\"" ;; openjdk) - PKGHANDLER_COMMAND="sudo yum install java-1.7.0-openjdk" ;; + PKGHANDLER_COMMAND="sudo yum install java-1.8.0-openjdk-devel" ;; alsa) PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) @@ -4862,7 +4862,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1456136781 +DATE_WHEN_GENERATED=1457684806 ############################################################################### # @@ -15118,6 +15118,10 @@ REQUIRED_OS_NAME=Darwin REQUIRED_OS_VERSION=11.2 fi + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + REQUIRED_OS_NAME=AIX + REQUIRED_OS_VERSION=7.1 + fi diff -r 0dc62e7c6a29 -r 74e9f4b90006 common/autoconf/help.m4 --- a/common/autoconf/help.m4 Mon Mar 21 08:42:00 2016 +0100 +++ b/common/autoconf/help.m4 Mon Mar 21 11:21:08 2016 +0100 @@ -106,7 +106,7 @@ devkit) PKGHANDLER_COMMAND="sudo apt-get install build-essential" ;; openjdk) - PKGHANDLER_COMMAND="sudo apt-get install openjdk-7-jdk" ;; + PKGHANDLER_COMMAND="sudo apt-get install openjdk-8-jdk" ;; alsa) PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) @@ -127,7 +127,7 @@ devkit) PKGHANDLER_COMMAND="sudo yum groupinstall \"Development Tools\"" ;; openjdk) - PKGHANDLER_COMMAND="sudo yum install java-1.7.0-openjdk" ;; + PKGHANDLER_COMMAND="sudo yum install java-1.8.0-openjdk-devel" ;; alsa) PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) diff -r 0dc62e7c6a29 -r 74e9f4b90006 common/autoconf/platform.m4 --- a/common/autoconf/platform.m4 Mon Mar 21 08:42:00 2016 +0100 +++ b/common/autoconf/platform.m4 Mon Mar 21 11:21:08 2016 +0100 @@ -406,6 +406,10 @@ REQUIRED_OS_NAME=Darwin REQUIRED_OS_VERSION=11.2 fi + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + REQUIRED_OS_NAME=AIX + REQUIRED_OS_VERSION=7.1 + fi AC_SUBST(REQUIRED_OS_NAME) AC_SUBST(REQUIRED_OS_VERSION) diff -r 0dc62e7c6a29 -r 74e9f4b90006 common/bin/compare_exceptions.sh.incl --- a/common/bin/compare_exceptions.sh.incl Mon Mar 21 08:42:00 2016 +0100 +++ b/common/bin/compare_exceptions.sh.incl Mon Mar 21 11:21:08 2016 +0100 @@ -185,7 +185,6 @@ ./lib/amd64/libjava.so ./lib/amd64/libjawt.so ./lib/amd64/libjdwp.so - ./lib/amd64/libjfr.so ./lib/amd64/libjpeg.so ./lib/amd64/libjsdt.so ./lib/amd64/libjsound.so @@ -321,7 +320,6 @@ ./lib/sparcv9/libjava.so ./lib/sparcv9/libjawt.so ./lib/sparcv9/libjdwp.so - ./lib/sparcv9/libjfr.so ./lib/sparcv9/libjpeg.so ./lib/sparcv9/libjsdt.so ./lib/sparcv9/libjsound.so diff -r 0dc62e7c6a29 -r 74e9f4b90006 common/bin/unshuffle_list.txt --- a/common/bin/unshuffle_list.txt Mon Mar 21 08:42:00 2016 +0100 +++ b/common/bin/unshuffle_list.txt Mon Mar 21 11:21:08 2016 +0100 @@ -1293,12 +1293,8 @@ jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.h jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h -jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html : jdk/src/macosx/classes/com/apple/concurrent/package.html -jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent : jdk/src/macosx/classes/com/apple/concurrent -jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m : jdk/src/macosx/native/com/apple/concurrent/Dispatch.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/JavaAppLauncher.m : jdk/src/macosx/native/apple/launcher/JavaAppLauncher.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m +jdk/src/java.desktop/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m +jdk/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof : jdk/src/share/classes/com/sun/demo/jvmti/hprof jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver : jdk/src/share/classes/com/sun/net/httpserver jdk/src/jdk.httpserver/share/classes/sun/net/httpserver : jdk/src/share/classes/sun/net/httpserver diff -r 0dc62e7c6a29 -r 74e9f4b90006 corba/.hgtags --- a/corba/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/corba/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -351,3 +351,4 @@ 8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106 49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107 84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108 +b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/.hgtags --- a/hotspot/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -511,3 +511,4 @@ 7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106 c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107 934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108 +7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/aix/makefiles/trace.make --- a/hotspot/make/aix/makefiles/trace.make Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/aix/makefiles/trace.make Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,6 @@ TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -100,9 +95,6 @@ $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/bsd/makefiles/trace.make --- a/hotspot/make/bsd/makefiles/trace.make Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/bsd/makefiles/trace.make Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,6 @@ TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif @@ -101,9 +96,6 @@ $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/linux/makefiles/trace.make --- a/hotspot/make/linux/makefiles/trace.make Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/linux/makefiles/trace.make Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,6 @@ TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -100,9 +95,6 @@ $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/solaris/makefiles/amd64.make --- a/hotspot/make/solaris/makefiles/amd64.make Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/solaris/makefiles/amd64.make Mon Mar 21 11:21:08 2016 +0100 @@ -39,7 +39,7 @@ # of OPT_CFLAGS. Restore it here. ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) OPT_CFLAGS/generateOptoStub.o += -g0 -xs - OPT_CFLAGS/LinearScan.o += -g0 -xs + OPT_CFLAGS/c1_LinearScan.o += -g0 -xs endif else diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/solaris/makefiles/trace.make --- a/hotspot/make/solaris/makefiles/trace.make Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/solaris/makefiles/trace.make Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -56,8 +56,7 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ - traceEventControl.hpp \ - traceProducer.cpp + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -96,9 +95,6 @@ $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/test/JtregNative.gmk --- a/hotspot/make/test/JtregNative.gmk Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/test/JtregNative.gmk Mon Mar 21 11:21:08 2016 +0100 @@ -48,6 +48,7 @@ $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ + $(HOTSPOT_TOPDIR)/test/compiler/native \ # # Add conditional directories here when needed. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/make/windows/makefiles/trace.make --- a/hotspot/make/windows/makefiles/trace.make Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/make/windows/makefiles/trace.make Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,7 @@ !if EXISTS($(TraceAltSrcDir)) TraceGeneratedNames = $(TraceGeneratedNames) \ traceRequestables.hpp \ - traceEventControl.hpp \ - traceProducer.cpp + traceEventControl.hpp !endif @@ -58,8 +57,7 @@ !if EXISTS($(TraceAltSrcDir)) TraceGeneratedFiles = $(TraceGeneratedFiles) \ $(TraceOutDir)/traceRequestables.hpp \ - $(TraceOutDir)/traceEventControl.hpp \ - $(TraceOutDir)/traceProducer.cpp + $(TraceOutDir)/traceEventControl.hpp !endif XSLT = $(QUIETLY) $(REMOTE) $(RUN_JAVA) -classpath $(JvmtiOutDir) jvmtiGen @@ -98,10 +96,6 @@ @echo Generating AltSrc $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - @echo Generating AltSrc $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceProducer.xsl -OUT $(TraceOutDir)/traceProducer.cpp - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) @echo Generating AltSrc $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceRequestables.xsl -OUT $(TraceOutDir)/traceRequestables.hpp diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/aarch64/vm/aarch64.ad --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Mar 21 11:21:08 2016 +0100 @@ -1041,10 +1041,8 @@ bool is_card_mark_membar(const MemBarNode *barrier); bool is_CAS(int opcode); - MemBarNode *leading_to_normal(MemBarNode *leading); - MemBarNode *normal_to_leading(const MemBarNode *barrier); - MemBarNode *card_mark_to_trailing(const MemBarNode *barrier); - MemBarNode *trailing_to_card_mark(const MemBarNode *trailing); + MemBarNode *leading_to_trailing(MemBarNode *leading); + MemBarNode *card_mark_to_leading(const MemBarNode *barrier); MemBarNode *trailing_to_leading(const MemBarNode *trailing); // predicates controlling emit of ldr/ldar and associated dmb @@ -1418,23 +1416,28 @@ // leading MemBarRelease and a trailing MemBarVolatile as follows // // MemBarRelease - // { || } -- optional + // { || } -- optional // {MemBarCPUOrder} - // || \\ - // || StoreX[mo_release] - // | \ / - // | MergeMem - // | / + // || \\ + // || StoreX[mo_release] + // | \ Bot / ??? + // | MergeMem + // | / // MemBarVolatile // // where // || and \\ represent Ctl and Mem feeds via Proj nodes // | \ and / indicate further routing of the Ctl and Mem feeds // - // this is the graph we see for non-object stores. however, for a - // volatile Object store (StoreN/P) we may see other nodes below the - // leading membar because of the need for a GC pre- or post-write - // barrier. + // Note that the memory feed from the CPUOrder membar to the + // MergeMem node is an AliasIdxBot slice while the feed from the + // StoreX is for a slice determined by the type of value being + // written. + // + // the diagram above shows the graph we see for non-object stores. + // for a volatile Object store (StoreN/P) we may see other nodes + // below the leading membar because of the need for a GC pre- or + // post-write barrier. // // with most GC configurations we with see this simple variant which // includes a post-write barrier card mark. @@ -1442,7 +1445,7 @@ // MemBarRelease______________________________ // || \\ Ctl \ \\ // || StoreN/P[mo_release] CastP2X StoreB/CM - // | \ / . . . / + // | \ Bot / oop . . . / // | MergeMem // | / // || / @@ -1452,152 +1455,142 @@ // the object address to an int used to compute the card offset) and // Ctl+Mem to a StoreB node (which does the actual card mark). // - // n.b. a StoreCM node will only appear in this configuration when - // using CMS. StoreCM differs from a normal card mark write (StoreB) - // because it implies a requirement to order visibility of the card - // mark (StoreCM) relative to the object put (StoreP/N) using a - // StoreStore memory barrier (arguably this ought to be represented - // explicitly in the ideal graph but that is not how it works). This - // ordering is required for both non-volatile and volatile - // puts. Normally that means we need to translate a StoreCM using - // the sequence + // n.b. a StoreCM node is only ever used when CMS (with or without + // CondCardMark) or G1 is configured. This abstract instruction + // differs from a normal card mark write (StoreB) because it implies + // a requirement to order visibility of the card mark (StoreCM) + // after that of the object put (StoreP/N) using a StoreStore memory + // barrier. Note that this is /not/ a requirement to order the + // instructions in the generated code (that is already guaranteed by + // the order of memory dependencies). Rather it is a requirement to + // ensure visibility order which only applies on architectures like + // AArch64 which do not implement TSO. This ordering is required for + // both non-volatile and volatile puts. + // + // That implies that we need to translate a StoreCM using the + // sequence // // dmb ishst // stlrb // - // However, in the case of a volatile put if we can recognise this - // configuration and plant an stlr for the object write then we can - // omit the dmb and just plant an strb since visibility of the stlr - // is ordered before visibility of subsequent stores. StoreCM nodes - // also arise when using G1 or using CMS with conditional card - // marking. In these cases (as we shall see) we don't need to insert - // the dmb when translating StoreCM because there is already an - // intervening StoreLoad barrier between it and the StoreP/N. - // - // It is also possible to perform the card mark conditionally on it - // currently being unmarked in which case the volatile put graph - // will look slightly different + // This dmb cannot be omitted even when the associated StoreX or + // CompareAndSwapX is implemented using stlr. However, as described + // below there are circumstances where a specific GC configuration + // requires a stronger barrier in which case it can be omitted. + // + // With the Serial or Parallel GC using +CondCardMark the card mark + // is performed conditionally on it currently being unmarked in + // which case the volatile put graph looks slightly different // // MemBarRelease____________________________________________ // || \\ Ctl \ Ctl \ \\ Mem \ // || StoreN/P[mo_release] CastP2X If LoadB | - // | \ / \ | + // | \ Bot / oop \ | // | MergeMem . . . StoreB // | / / // || / // MemBarVolatile // - // It is worth noting at this stage that both the above + // It is worth noting at this stage that all the above // configurations can be uniquely identified by checking that the // memory flow includes the following subgraph: // // MemBarRelease // {MemBarCPUOrder} - // | \ . . . - // | StoreX[mo_release] . . . - // | / - // MergeMem - // | + // | \ . . . + // | StoreX[mo_release] . . . + // Bot | / oop + // MergeMem + // | // MemBarVolatile // - // This is referred to as a *normal* subgraph. It can easily be - // detected starting from any candidate MemBarRelease, - // StoreX[mo_release] or MemBarVolatile. - // - // A simple variation on this normal case occurs for an unsafe CAS - // operation. The basic graph for a non-object CAS is + // This is referred to as a *normal* volatile store subgraph. It can + // easily be detected starting from any candidate MemBarRelease, + // StoreX[mo_release] or MemBarVolatile node. + // + // A small variation on this normal case occurs for an unsafe CAS + // operation. The basic memory flow subgraph for a non-object CAS is + // as follows // // MemBarRelease // || // MemBarCPUOrder - // || \\ . . . - // || CompareAndSwapX - // || | - // || SCMemProj - // | \ / - // | MergeMem - // | / + // | \\ . . . + // | CompareAndSwapX + // | | + // Bot | SCMemProj + // \ / Bot + // MergeMem + // / // MemBarCPUOrder // || // MemBarAcquire // // The same basic variations on this arrangement (mutatis mutandis) - // occur when a card mark is introduced. i.e. we se the same basic - // shape but the StoreP/N is replaced with CompareAndSawpP/N and the - // tail of the graph is a pair comprising a MemBarCPUOrder + - // MemBarAcquire. - // - // So, in the case of a CAS the normal graph has the variant form - // - // MemBarRelease - // MemBarCPUOrder - // | \ . . . - // | CompareAndSwapX . . . - // | | - // | SCMemProj - // | / . . . - // MergeMem - // | - // MemBarCPUOrder - // MemBarAcquire - // - // This graph can also easily be detected starting from any - // candidate MemBarRelease, CompareAndSwapX or MemBarAcquire. - // - // the code below uses two helper predicates, leading_to_normal and - // normal_to_leading to identify these normal graphs, one validating - // the layout starting from the top membar and searching down and - // the other validating the layout starting from the lower membar - // and searching up. - // - // There are two special case GC configurations when a normal graph - // may not be generated: when using G1 (which always employs a - // conditional card mark); and when using CMS with conditional card - // marking configured. These GCs are both concurrent rather than - // stop-the world GCs. So they introduce extra Ctl+Mem flow into the - // graph between the leading and trailing membar nodes, in - // particular enforcing stronger memory serialisation beween the - // object put and the corresponding conditional card mark. CMS - // employs a post-write GC barrier while G1 employs both a pre- and - // post-write GC barrier. Of course the extra nodes may be absent -- - // they are only inserted for object puts. This significantly - // complicates the task of identifying whether a MemBarRelease, - // StoreX[mo_release] or MemBarVolatile forms part of a volatile put - // when using these GC configurations (see below). It adds similar - // complexity to the task of identifying whether a MemBarRelease, - // CompareAndSwapX or MemBarAcquire forms part of a CAS. - // - // In both cases the post-write subtree includes an auxiliary - // MemBarVolatile (StoreLoad barrier) separating the object put and - // the read of the corresponding card. This poses two additional - // problems. - // - // Firstly, a card mark MemBarVolatile needs to be distinguished - // from a normal trailing MemBarVolatile. Resolving this first - // problem is straightforward: a card mark MemBarVolatile always - // projects a Mem feed to a StoreCM node and that is a unique marker + // occur when a card mark is introduced. i.e. the CPUOrder MemBar + // feeds the extra CastP2X, LoadB etc nodes but the above memory + // flow subgraph is still present. + // + // This is referred to as a *normal* CAS subgraph. It can easily be + // detected starting from any candidate MemBarRelease, + // StoreX[mo_release] or MemBarAcquire node. + // + // The code below uses two helper predicates, leading_to_trailing + // and trailing_to_leading to identify these normal graphs, one + // validating the layout starting from the top membar and searching + // down and the other validating the layout starting from the lower + // membar and searching up. + // + // There are two special case GC configurations when the simple + // normal graphs above may not be generated: when using G1 (which + // always employs a conditional card mark); and when using CMS with + // conditional card marking (+CondCardMark) configured. These GCs + // are both concurrent rather than stop-the world GCs. So they + // introduce extra Ctl+Mem flow into the graph between the leading + // and trailing membar nodes, in particular enforcing stronger + // memory serialisation beween the object put and the corresponding + // conditional card mark. CMS employs a post-write GC barrier while + // G1 employs both a pre- and post-write GC barrier. + // + // The post-write barrier subgraph for these configurations includes + // a MemBarVolatile node -- referred to as a card mark membar -- + // which is needed to order the card write (StoreCM) operation in + // the barrier, the preceding StoreX (or CompareAndSwapX) and Store + // operations performed by GC threads i.e. a card mark membar + // constitutes a StoreLoad barrier hence must be translated to a dmb + // ish (whether or not it sits inside a volatile store sequence). + // + // Of course, the use of the dmb ish for the card mark membar also + // implies theat the StoreCM which follows can omit the dmb ishst + // instruction. The necessary visibility ordering will already be + // guaranteed by the dmb ish. In sum, the dmb ishst instruction only + // needs to be generated for as part of the StoreCM sequence with GC + // configuration +CMS -CondCardMark. + // + // Of course all these extra barrier nodes may well be absent -- + // they are only inserted for object puts. Their potential presence + // significantly complicates the task of identifying whether a + // MemBarRelease, StoreX[mo_release], MemBarVolatile or + // MemBarAcquire forms part of a volatile put or CAS when using + // these GC configurations (see below) and also complicates the + // decision as to how to translate a MemBarVolatile and StoreCM. + // + // So, thjis means that a card mark MemBarVolatile occurring in the + // post-barrier graph it needs to be distinguished from a normal + // trailing MemBarVolatile. Resolving this is straightforward: a + // card mark MemBarVolatile always projects a Mem feed to a StoreCM + // node and that is a unique marker // // MemBarVolatile (card mark) // C | \ . . . // | StoreCM . . . // . . . // - // The second problem is how the code generator is to translate the - // card mark barrier? It always needs to be translated to a "dmb - // ish" instruction whether or not it occurs as part of a volatile - // put. A StoreLoad barrier is needed after the object put to ensure - // i) visibility to GC threads of the object put and ii) visibility - // to the mutator thread of any card clearing write by a GC - // thread. Clearly a normal store (str) will not guarantee this - // ordering but neither will a releasing store (stlr). The latter - // guarantees that the object put is visible but does not guarantee - // that writes by other threads have also been observed. - // - // So, returning to the task of translating the object put and the - // leading/trailing membar nodes: what do the non-normal node graph - // look like for these 2 special cases? and how can we determine the - // status of a MemBarRelease, StoreX[mo_release] or MemBarVolatile - // in both normal and non-normal cases? + // Returning to the task of translating the object put and the + // leading/trailing membar nodes: what do the node graphs look like + // for these 2 special cases? and how can we determine the status of + // a MemBarRelease, StoreX[mo_release] or MemBarVolatile in both + // normal and non-normal cases? // // A CMS GC post-barrier wraps its card write (StoreCM) inside an If // which selects conditonal execution based on the value loaded @@ -1608,91 +1601,117 @@ // which looks like this // // MemBarRelease - // MemBarCPUOrder_(leading)__________________ - // C | M \ \\ C \ - // | \ StoreN/P[mo_release] CastP2X - // | Bot \ / - // | MergeMem - // | / - // MemBarVolatile (card mark) - // C | || M | - // | LoadB | - // | | | - // | Cmp |\ - // | / | \ - // If | \ - // | \ | \ - // IfFalse IfTrue | \ - // \ / \ | \ - // \ / StoreCM | - // \ / | | - // Region . . . | - // | \ / - // | . . . \ / Bot + // MemBarCPUOrder_(leading)____________________ + // C | | M \ \\ M | C \ + // | | \ StoreN/P[mo_release] | CastP2X + // | | Bot \ / oop \ | + // | | MergeMem \ / + // | | / | / + // MemBarVolatile (card mark) | / + // C | || M | | / + // | LoadB | Bot oop | / Bot + // | | | / / + // | Cmp |\ / / + // | / | \ / / + // If | \ / / + // | \ | \ / / + // IfFalse IfTrue | \ / / + // \ / \ | | / / + // \ / StoreCM | / / + // \ / \ / / / + // Region Phi / / + // | \ Raw | / / + // | . . . | / / // | MergeMem - // | | + // | | // MemBarVolatile (trailing) // - // The first MergeMem merges the AliasIdxBot Mem slice from the - // leading membar and the oopptr Mem slice from the Store into the - // card mark membar. The trailing MergeMem merges the AliasIdxBot - // Mem slice from the card mark membar and the AliasIdxRaw slice - // from the StoreCM into the trailing membar (n.b. the latter - // proceeds via a Phi associated with the If region). - // - // The graph for a CAS varies slightly, the obvious difference being - // that the StoreN/P node is replaced by a CompareAndSwapP/N node - // and the trailing MemBarVolatile by a MemBarCPUOrder + - // MemBarAcquire pair. The other important difference is that the - // CompareAndSwap node's SCMemProj is not merged into the card mark - // membar - it still feeds the trailing MergeMem. This also means - // that the card mark membar receives its Mem feed directly from the - // leading membar rather than via a MergeMem. + // Notice that there are two MergeMem nodes below the leading + // membar. The first MergeMem merges the AliasIdxBot Mem slice from + // the leading membar and the oopptr Mem slice from the Store into + // the card mark membar. The trailing MergeMem merges the + // AliasIdxBot Mem slice from the leading membar, the AliasIdxRaw + // slice from the StoreCM and an oop slice from the StoreN/P node + // into the trailing membar (n.b. the raw slice proceeds via a Phi + // associated with the If region). + // + // So, in the case of CMS + CondCardMark the volatile object store + // graph still includes a normal volatile store subgraph from the + // leading membar to the trailing membar. However, it also contains + // the same shape memory flow to the card mark membar. The two flows + // can be distinguished by testing whether or not the downstream + // membar is a card mark membar. + // + // The graph for a CAS also varies with CMS + CondCardMark, in + // particular employing a control feed from the CompareAndSwapX node + // through a CmpI and If to the card mark membar and StoreCM which + // updates the associated card. This avoids executing the card mark + // if the CAS fails. However, it can be seen from the diagram below + // that the presence of the barrier does not alter the normal CAS + // memory subgraph where the leading membar feeds a CompareAndSwapX, + // an SCMemProj, a MergeMem then a final trailing MemBarCPUOrder and + // MemBarAcquire pair. // // MemBarRelease - // MemBarCPUOrder__(leading)_________________________ - // || \\ C \ - // MemBarVolatile (card mark) CompareAndSwapN/P CastP2X - // C | || M | | - // | LoadB | ______/| - // | | | / | - // | Cmp | / SCMemProj - // | / | / | - // If | / / - // | \ | / / - // IfFalse IfTrue | / / - // \ / \ |/ prec / - // \ / StoreCM / - // \ / | / - // Region . . . / - // | \ / - // | . . . \ / Bot - // | MergeMem - // | | - // MemBarCPUOrder - // MemBarAcquire (trailing) + // MemBarCPUOrder__(leading)_______________________ + // C / M | \\ C \ + // . . . | Bot CompareAndSwapN/P CastP2X + // | C / M | + // | CmpI | + // | / | + // | . . . | + // | IfTrue | + // | / | + // MemBarVolatile (card mark) | + // C | || M | | + // | LoadB | Bot ______/| + // | | | / | + // | Cmp | / SCMemProj + // | / | / | + // If | / / + // | \ | / / Bot + // IfFalse IfTrue | / / + // | / \ / / prec / + // . . . | / StoreCM / + // \ | / | raw / + // Region . . . / + // | \ / + // | . . . \ / Bot + // | MergeMem + // | / + // MemBarCPUOrder + // MemBarAcquire (trailing) // // This has a slightly different memory subgraph to the one seen - // previously but the core of it is the same as for the CAS normal - // sungraph + // previously but the core of it has a similar memory flow to the + // CAS normal subgraph: // // MemBarRelease // MemBarCPUOrder____ - // || \ . . . - // MemBarVolatile CompareAndSwapX . . . - // | \ | - // . . . SCMemProj - // | / . . . - // MergeMem - // | + // | \ . . . + // | CompareAndSwapX . . . + // | C / M | + // | CmpI | + // | / | + // | . . / + // Bot | IfTrue / + // | / / + // MemBarVolatile / + // | ... / + // StoreCM ... / + // | / + // . . . SCMemProj + // Raw \ / Bot + // MergeMem + // | // MemBarCPUOrder // MemBarAcquire // - // - // G1 is quite a lot more complicated. The nodes inserted on behalf - // of G1 may comprise: a pre-write graph which adds the old value to - // the SATB queue; the releasing store itself; and, finally, a - // post-write graph which performs a card mark. + // The G1 graph for a volatile object put is a lot more complicated. + // Nodes inserted on behalf of G1 may comprise: a pre-write graph + // which adds the old value to the SATB queue; the releasing store + // itself; and, finally, a post-write graph which performs a card + // mark. // // The pre-write graph may be omitted, but only when the put is // writing to a newly allocated (young gen) object and then only if @@ -1730,25 +1749,60 @@ // | CastP2X | StoreN/P[mo_release] | // | | | | // C | M | M | M | - // \ | | / + // \ | Raw | oop / Bot // . . . // (post write subtree elided) // . . . // C \ M / // MemBarVolatile (trailing) // + // Note that the three memory feeds into the post-write tree are an + // AliasRawIdx slice associated with the writes in the pre-write + // tree, an oop type slice from the StoreX specific to the type of + // the volatile field and the AliasBotIdx slice emanating from the + // leading membar. + // // n.b. the LoadB in this subgraph is not the card read -- it's a // read of the SATB queue active flag. // - // Once again the CAS graph is a minor variant on the above with the - // expected substitutions of CompareAndSawpX for StoreN/P and - // MemBarCPUOrder + MemBarAcquire for trailing MemBarVolatile. + // The CAS graph is once again a variant of the above with a + // CompareAndSwapX node and SCMemProj in place of the StoreX. The + // value from the CompareAndSwapX node is fed into the post-write + // graph aling with the AliasIdxRaw feed from the pre-barrier and + // the AliasIdxBot feeds from the leading membar and the ScMemProj. + // + // MemBarRelease (leading)____________ + // C | || M \ M \ M \ M \ . . . + // | LoadB \ LoadL LoadN \ + // | / \ \ + // If |\ \ + // | \ | \ \ + // IfFalse IfTrue | \ \ + // | | | \ \ + // | If | \ | + // | | \ | + // | \ | + // | . . . \ | + // | / | / \ | + // Region Phi[M] \ | + // | \ | \ | + // | \_____ | | | + // C | C \ | | | + // | CastP2X | CompareAndSwapX | + // | | res | | | + // C | M | | SCMemProj M | + // \ | Raw | | Bot / Bot + // . . . + // (post write subtree elided) + // . . . + // C \ M / + // MemBarVolatile (trailing) // // The G1 post-write subtree is also optional, this time when the // new value being written is either null or can be identified as a // newly allocated (young gen) object with no intervening control // flow. The latter cannot happen but the former may, in which case - // the card mark membar is omitted and the memory feeds form the + // the card mark membar is omitted and the memory feeds from the // leading membar and the SToreN/P are merged direct into the // trailing membar as per the normal subgraph. So, the only special // case which arises is when the post-write subgraph is generated. @@ -1770,94 +1824,106 @@ // // (pre-write subtree elided) // . . . . . . . . . . . . - // C | M | M | M | - // Region Phi[M] StoreN | - // | / \ | | - // / \_______ / \ | | - // C / C \ . . . \ | | - // If CastP2X . . . | | | - // / \ | | | - // / \ | | | - // IfFalse IfTrue | | | - // | | | | /| - // | If | | / | - // | / \ | | / | - // | / \ \ | / | - // | IfFalse IfTrue MergeMem | - // | . . . / \ / | - // | / \ / | - // | IfFalse IfTrue / | - // | . . . | / | - // | If / | - // | / \ / | - // | / \ / | - // | IfFalse IfTrue / | - // | . . . | / | - // | \ / | - // | \ / | - // | MemBarVolatile__(card mark) | - // | || C | M \ M \ | - // | LoadB If | | | - // | / \ | | | - // | . . . | | | - // | \ | | / - // | StoreCM | / - // | . . . | / - // | _________/ / - // | / _____________/ - // | . . . . . . | / / - // | | | / _________/ - // | | Phi[M] / / - // | | | / / - // | | | / / - // | Region . . . Phi[M] _____/ - // | / | / - // | | / - // | . . . . . . | / - // | / | / - // Region | | Phi[M] - // | | | / Bot - // \ MergeMem - // \ / - // MemBarVolatile - // - // As with CMS the initial MergeMem merges the AliasIdxBot Mem slice - // from the leading membar and the oopptr Mem slice from the Store - // into the card mark membar i.e. the memory flow to the card mark - // membar still looks like a normal graph. - // - // The trailing MergeMem merges an AliasIdxBot Mem slice with other - // Mem slices (from the StoreCM and other card mark queue stores). - // However in this case the AliasIdxBot Mem slice does not come - // direct from the card mark membar. It is merged through a series - // of Phi nodes. These are needed to merge the AliasIdxBot Mem flow - // from the leading membar with the Mem feed from the card mark - // membar. Each Phi corresponds to one of the Ifs which may skip - // around the card mark membar. So when the If implementing the NULL - // value check has been elided the total number of Phis is 2 - // otherwise it is 3. - // - // The CAS graph when using G1GC also includes a pre-write subgraph - // and an optional post-write subgraph. Teh sam evarioations are - // introduced as for CMS with conditional card marking i.e. the - // StoreP/N is swapped for a CompareAndSwapP/N, the tariling - // MemBarVolatile for a MemBarCPUOrder + MemBarAcquire pair and the - // Mem feed from the CompareAndSwapP/N includes a precedence - // dependency feed to the StoreCM and a feed via an SCMemProj to the - // trailing membar. So, as before the configuration includes the - // normal CAS graph as a subgraph of the memory flow. - // - // So, the upshot is that in all cases the volatile put graph will - // include a *normal* memory subgraph betwen the leading membar and - // its child membar, either a volatile put graph (including a - // releasing StoreX) or a CAS graph (including a CompareAndSwapX). - // When that child is not a card mark membar then it marks the end - // of the volatile put or CAS subgraph. If the child is a card mark - // membar then the normal subgraph will form part of a volatile put - // subgraph if and only if the child feeds an AliasIdxBot Mem feed - // to a trailing barrier via a MergeMem. That feed is either direct - // (for CMS) or via 2 or 3 Phi nodes merging the leading barrier - // memory flow (for G1). + // C | M | M | M | + // Region Phi[M] StoreN | + // | Raw | oop | Bot | + // / \_______ |\ |\ |\ + // C / C \ . . . | \ | \ | \ + // If CastP2X . . . | \ | \ | \ + // / \ | \ | \ | \ + // / \ | \ | \ | \ + // IfFalse IfTrue | | | \ + // | | \ | / | + // | If \ | \ / \ | + // | / \ \ | / \ | + // | / \ \ | / \ | | + // | IfFalse IfTrue MergeMem \ | | + // | . . . / \ | \ | | + // | / \ | | | | + // | IfFalse IfTrue | | | | + // | . . . | | | | | + // | If / | | | + // | / \ / | | | + // | / \ / | | | + // | IfFalse IfTrue / | | | + // | . . . | / | | | + // | \ / | | | + // | \ / | | | + // | MemBarVolatile__(card mark ) | | | + // | || C | \ | | | + // | LoadB If | / | | + // | / \ Raw | / / / + // | . . . | / / / + // | \ | / / / + // | StoreCM / / / + // | | / / / + // | . . . / / + // | / / + // | . . . / / + // | | | / / / + // | | Phi[M] / / / + // | | | / / / + // | | | / / / + // | Region . . . Phi[M] / / + // | | | / / + // \ | | / / + // \ | . . . | / / + // \ | | / / + // Region Phi[M] / / + // | \ / / + // \ MergeMem + // \ / + // MemBarVolatile + // + // As with CMS + CondCardMark the first MergeMem merges the + // AliasIdxBot Mem slice from the leading membar and the oopptr Mem + // slice from the Store into the card mark membar. However, in this + // case it may also merge an AliasRawIdx mem slice from the pre + // barrier write. + // + // The trailing MergeMem merges an AliasIdxBot Mem slice from the + // leading membar with an oop slice from the StoreN and an + // AliasRawIdx slice from the post barrier writes. In this case the + // AliasIdxRaw Mem slice is merged through a series of Phi nodes + // which combine feeds from the If regions in the post barrier + // subgraph. + // + // So, for G1 the same characteristic subgraph arises as for CMS + + // CondCardMark. There is a normal subgraph feeding the card mark + // membar and a normal subgraph feeding the trailing membar. + // + // The CAS graph when using G1GC also includes an optional + // post-write subgraph. It is very similar to the above graph except + // for a few details. + // + // - The control flow is gated by an additonal If which tests the + // result from the CompareAndSwapX node + // + // - The MergeMem which feeds the card mark membar only merges the + // AliasIdxBot slice from the leading membar and the AliasIdxRaw + // slice from the pre-barrier. It does not merge the SCMemProj + // AliasIdxBot slice. So, this subgraph does not look like the + // normal CAS subgraph. + // + // - The MergeMem which feeds the trailing membar merges the + // AliasIdxBot slice from the leading membar, the AliasIdxRaw slice + // from the post-barrier and the SCMemProj AliasIdxBot slice i.e. it + // has two AliasIdxBot input slices. However, this subgraph does + // still look like the normal CAS subgraph. + // + // So, the upshot is: + // + // In all cases a volatile put graph will include a *normal* + // volatile store subgraph betwen the leading membar and the + // trailing membar. It may also include a normal volatile store + // subgraph betwen the leading membar and the card mark membar. + // + // In all cases a CAS graph will contain a unique normal CAS graph + // feeding the trailing membar. + // + // In all cases where there is a card mark membar (either as part of + // a volatile object put or CAS) it will be fed by a MergeMem whose + // AliasIdxBot slice feed will be a leading membar. // // The predicates controlling generation of instructions for store // and barrier nodes employ a few simple helper functions (described @@ -1878,24 +1944,24 @@ opcode == Op_CompareAndSwapP); } - // leading_to_normal + // leading_to_trailing // //graph traversal helper which detects the normal case Mem feed from // a release membar (or, optionally, its cpuorder child) to a // dependent volatile membar i.e. it ensures that one or other of // the following Mem flow subgraph is present. // - // MemBarRelease - // MemBarCPUOrder {leading} - // | \ . . . - // | StoreN/P[mo_release] . . . - // | / - // MergeMem - // | - // MemBarVolatile {trailing or card mark} - // - // MemBarRelease - // MemBarCPUOrder {leading} + // MemBarRelease {leading} + // {MemBarCPUOrder} {optional} + // Bot | \ . . . + // | StoreN/P[mo_release] . . . + // | / + // MergeMem + // | + // MemBarVolatile {not card mark} + // + // MemBarRelease {leading} + // {MemBarCPUOrder} {optional} // | \ . . . // | CompareAndSwapX . . . // | @@ -1906,6 +1972,23 @@ // MemBarCPUOrder // MemBarAcquire {trailing} // + // the predicate needs to be capable of distinguishing the following + // volatile put graph which may arises when a GC post barrier + // inserts a card mark membar + // + // MemBarRelease {leading} + // {MemBarCPUOrder}__ + // Bot | \ \ + // | StoreN/P \ + // | / \ | + // MergeMem \ | + // | \ | + // MemBarVolatile \ | + // {card mark} \ | + // MergeMem + // | + // {not card mark} MemBarVolatile + // // if the correct configuration is present returns the trailing // membar otherwise NULL. // @@ -1916,7 +1999,7 @@ // the returned value may be a card mark or trailing membar // - MemBarNode *leading_to_normal(MemBarNode *leading) + MemBarNode *leading_to_trailing(MemBarNode *leading) { assert((leading->Opcode() == Op_MemBarRelease || leading->Opcode() == Op_MemBarCPUOrder), @@ -1933,15 +2016,21 @@ StoreNode * st = NULL; LoadStoreNode *cas = NULL; MergeMemNode *mm = NULL; + MergeMemNode *mm2 = NULL; for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { x = mem->fast_out(i); if (x->is_MergeMem()) { if (mm != NULL) { - return NULL; + if (mm2 != NULL) { + // should not see more than 2 merge mems + return NULL; + } else { + mm2 = x->as_MergeMem(); + } + } else { + mm = x->as_MergeMem(); } - // two merge mems is one too many - mm = x->as_MergeMem(); } else if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) { // two releasing stores/CAS nodes is one too many if (st != NULL || cas != NULL) { @@ -1961,13 +2050,13 @@ return NULL; } - // must have a merge if we also have st + // must have at least one merge if we also have st if (st && !mm) { return NULL; } - Node *y = NULL; if (cas) { + Node *y = NULL; // look for an SCMemProj for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) { x = cas->fast_out(i); @@ -1987,10 +2076,29 @@ break; } } - if (mm == NULL) + if (mm == NULL) { return NULL; + } + MemBarNode *mbar = NULL; + // ensure the merge feeds a trailing membar cpuorder + acquire pair + for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) { + x = mm->fast_out(i); + if (x->is_MemBar()) { + int opcode = x->Opcode(); + if (opcode == Op_MemBarCPUOrder) { + MemBarNode *z = x->as_MemBar(); + z = child_membar(z); + if (z != NULL && z->Opcode() == Op_MemBarAcquire) { + mbar = z; + } + } + break; + } + } + return mbar; } else { - // ensure the store feeds the existing mergemem; + Node *y = NULL; + // ensure the store feeds the first mergemem; for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) { if (st->fast_out(i) == mm) { y = st; @@ -2000,55 +2108,89 @@ if (y == NULL) { return NULL; } - } - - MemBarNode *mbar = NULL; - // ensure the merge feeds to the expected type of membar - for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) { - x = mm->fast_out(i); - if (x->is_MemBar()) { - int opcode = x->Opcode(); - if (opcode == Op_MemBarVolatile && st) { - mbar = x->as_MemBar(); - } else if (cas && opcode == Op_MemBarCPUOrder) { - MemBarNode *y = x->as_MemBar(); - y = child_membar(y); - if (y != NULL && y->Opcode() == Op_MemBarAcquire) { - mbar = y; + if (mm2 != NULL) { + // ensure the store feeds the second mergemem; + y = NULL; + for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) { + if (st->fast_out(i) == mm2) { + y = st; } } - break; + if (y == NULL) { + return NULL; + } + } + + MemBarNode *mbar = NULL; + // ensure the first mergemem feeds a volatile membar + for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) { + x = mm->fast_out(i); + if (x->is_MemBar()) { + int opcode = x->Opcode(); + if (opcode == Op_MemBarVolatile) { + mbar = x->as_MemBar(); + } + break; + } + } + if (mm2 == NULL) { + // this is our only option for a trailing membar + return mbar; } - } - - return mbar; - } - - // normal_to_leading + // ensure the second mergemem feeds a volatile membar + MemBarNode *mbar2 = NULL; + for (DUIterator_Fast imax, i = mm2->fast_outs(imax); i < imax; i++) { + x = mm2->fast_out(i); + if (x->is_MemBar()) { + int opcode = x->Opcode(); + if (opcode == Op_MemBarVolatile) { + mbar2 = x->as_MemBar(); + } + break; + } + } + // if we have two merge mems we must have two volatile membars + if (mbar == NULL || mbar2 == NULL) { + return NULL; + } + // return the trailing membar + if (is_card_mark_membar(mbar2)) { + return mbar; + } else { + if (is_card_mark_membar(mbar)) { + return mbar2; + } else { + return NULL; + } + } + } + } + + // trailing_to_leading // // graph traversal helper which detects the normal case Mem feed - // from either a card mark or a trailing membar to a preceding - // release membar (optionally its cpuorder child) i.e. it ensures - // that one or other of the following Mem flow subgraphs is present. - // - // MemBarRelease - // MemBarCPUOrder {leading} - // | \ . . . - // | StoreN/P[mo_release] . . . - // | / - // MergeMem - // | - // MemBarVolatile {card mark or trailing} - // - // MemBarRelease - // MemBarCPUOrder {leading} + // from a trailing membar to a preceding release membar (optionally + // its cpuorder child) i.e. it ensures that one or other of the + // following Mem flow subgraphs is present. + // + // MemBarRelease {leading} + // MemBarCPUOrder {optional} + // | Bot | \ . . . + // | | StoreN/P[mo_release] . . . + // | | / + // | MergeMem + // | | + // MemBarVolatile {not card mark} + // + // MemBarRelease {leading} + // MemBarCPUOrder {optional} // | \ . . . // | CompareAndSwapX . . . // | // . . . SCMemProj // \ | // | MergeMem - // | / + // | | // MemBarCPUOrder // MemBarAcquire {trailing} // @@ -2058,15 +2200,20 @@ // if the configuration is present returns the cpuorder member for // preference or when absent the release membar otherwise NULL. // - // n.b. the input membar is expected to be a MemBarVolatile but - // need not be a card mark membar. - - MemBarNode *normal_to_leading(const MemBarNode *barrier) + // n.b. the input membar is expected to be a MemBarVolatile or + // MemBarAcquire. if it is a MemBarVolatile it must *not* be a card + // mark membar. + + MemBarNode *trailing_to_leading(const MemBarNode *barrier) { // input must be a volatile membar assert((barrier->Opcode() == Op_MemBarVolatile || barrier->Opcode() == Op_MemBarAcquire), "expecting a volatile or an acquire membar"); + + assert((barrier->Opcode() != Op_MemBarVolatile) || + !is_card_mark_membar(barrier), + "not expecting a card mark membar"); Node *x; bool is_cas = barrier->Opcode() == Op_MemBarAcquire; @@ -2179,169 +2326,35 @@ return NULL; } - // card_mark_to_trailing - // - // graph traversal helper which detects extra, non-normal Mem feed - // from a card mark volatile membar to a trailing membar i.e. it - // ensures that one of the following three GC post-write Mem flow - // subgraphs is present. - // - // 1) - // . . . - // | - // MemBarVolatile (card mark) - // | | - // | StoreCM - // | | - // | . . . - // Bot | / - // MergeMem - // | - // | - // MemBarVolatile {trailing} - // - // 2) - // MemBarRelease/CPUOrder (leading) - // | - // | - // |\ . . . - // | \ | - // | \ MemBarVolatile (card mark) - // | \ | | - // \ \ | StoreCM . . . - // \ \ | - // \ Phi - // \ / - // Phi . . . + // card_mark_to_leading + // + // graph traversal helper which traverses from a card mark volatile + // membar to a leading membar i.e. it ensures that the following Mem + // flow subgraph is present. + // + // MemBarRelease {leading} + // {MemBarCPUOrder} {optional} + // | . . . // Bot | / - // MergeMem + // MergeMem // | - // MemBarVolatile {trailing} - // - // - // 3) - // MemBarRelease/CPUOrder (leading) - // | - // |\ - // | \ - // | \ . . . - // | \ | - // |\ \ MemBarVolatile (card mark) - // | \ \ | | - // | \ \ | StoreCM . . . - // | \ \ | - // \ \ Phi - // \ \ / - // \ Phi - // \ / - // Phi . . . - // Bot | / - // MergeMem - // | - // | - // MemBarVolatile {trailing} - // - // configuration 1 is only valid if UseConcMarkSweepGC && - // UseCondCardMark - // - // configurations 2 and 3 are only valid if UseG1GC. - // - // if a valid configuration is present returns the trailing membar - // otherwise NULL. - // - // n.b. the supplied membar is expected to be a card mark - // MemBarVolatile i.e. the caller must ensure the input node has the - // correct operand and feeds Mem to a StoreCM node - - MemBarNode *card_mark_to_trailing(const MemBarNode *barrier) + // MemBarVolatile (card mark) + // | \ + // . . . StoreCM + // + // if the configuration is present returns the cpuorder member for + // preference or when absent the release membar otherwise NULL. + // + // n.b. the input membar is expected to be a MemBarVolatile amd must + // be a card mark membar. + + MemBarNode *card_mark_to_leading(const MemBarNode *barrier) { // input must be a card mark volatile membar assert(is_card_mark_membar(barrier), "expecting a card mark membar"); - Node *feed = barrier->proj_out(TypeFunc::Memory); - Node *x; - MergeMemNode *mm = NULL; - - const int MAX_PHIS = 3; // max phis we will search through - int phicount = 0; // current search count - - bool retry_feed = true; - while (retry_feed) { - // see if we have a direct MergeMem feed - for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) { - x = feed->fast_out(i); - // the correct Phi will be merging a Bot memory slice - if (x->is_MergeMem()) { - mm = x->as_MergeMem(); - break; - } - } - if (mm) { - retry_feed = false; - } else if (UseG1GC & phicount++ < MAX_PHIS) { - // the barrier may feed indirectly via one or two Phi nodes - PhiNode *phi = NULL; - for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) { - x = feed->fast_out(i); - // the correct Phi will be merging a Bot memory slice - if (x->is_Phi() && x->adr_type() == TypePtr::BOTTOM) { - phi = x->as_Phi(); - break; - } - } - if (!phi) { - return NULL; - } - // look for another merge below this phi - feed = phi; - } else { - // couldn't find a merge - return NULL; - } - } - - // sanity check this feed turns up as the expected slice - assert(mm->as_MergeMem()->in(Compile::AliasIdxBot) == feed, "expecting membar to feed AliasIdxBot slice to Merge"); - - MemBarNode *trailing = NULL; - // be sure we have a trailing membar the merge - for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) { - x = mm->fast_out(i); - if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) { - trailing = x->as_MemBar(); - break; - } - } - - return trailing; - } - - // trailing_to_card_mark - // - // graph traversal helper which detects extra, non-normal Mem feed - // from a trailing volatile membar to a preceding card mark volatile - // membar i.e. it identifies whether one of the three possible extra - // GC post-write Mem flow subgraphs is present - // - // this predicate checks for the same flow as the previous predicate - // but starting from the bottom rather than the top. - // - // if the configuration is present returns the card mark membar - // otherwise NULL - // - // n.b. the supplied membar is expected to be a trailing - // MemBarVolatile i.e. the caller must ensure the input node has the - // correct opcode - - MemBarNode *trailing_to_card_mark(const MemBarNode *trailing) - { - assert(trailing->Opcode() == Op_MemBarVolatile, - "expecting a volatile membar"); - assert(!is_card_mark_membar(trailing), - "not expecting a card mark membar"); - // the Mem feed to the membar should be a merge - Node *x = trailing->in(TypeFunc::Memory); + Node *x = barrier->in(TypeFunc::Memory); if (!x->is_MergeMem()) { return NULL; } @@ -2349,117 +2362,19 @@ MergeMemNode *mm = x->as_MergeMem(); x = mm->in(Compile::AliasIdxBot); - // with G1 we may possibly see a Phi or two before we see a Memory - // Proj from the card mark membar - - const int MAX_PHIS = 3; // max phis we will search through - int phicount = 0; // current search count - - bool retry_feed = !x->is_Proj(); - - while (retry_feed) { - if (UseG1GC && x->is_Phi() && phicount++ < MAX_PHIS) { - PhiNode *phi = x->as_Phi(); - ProjNode *proj = NULL; - PhiNode *nextphi = NULL; - bool found_leading = false; - for (uint i = 1; i < phi->req(); i++) { - x = phi->in(i); - if (x->is_Phi()) { - nextphi = x->as_Phi(); - } else if (x->is_Proj()) { - int opcode = x->in(0)->Opcode(); - if (opcode == Op_MemBarVolatile) { - proj = x->as_Proj(); - } else if (opcode == Op_MemBarRelease || - opcode == Op_MemBarCPUOrder) { - // probably a leading membar - found_leading = true; - } - } - } - // if we found a correct looking proj then retry from there - // otherwise we must see a leading and a phi or this the - // wrong config - if (proj != NULL) { - x = proj; - retry_feed = false; - } else if (found_leading && nextphi != NULL) { - // retry from this phi to check phi2 - x = nextphi; - } else { - // not what we were looking for - return NULL; - } - } else { - return NULL; - } - } - // the proj has to come from the card mark membar - x = x->in(0); + if (!x->is_MemBar()) { return NULL; } - MemBarNode *card_mark_membar = x->as_MemBar(); - - if (!is_card_mark_membar(card_mark_membar)) { - return NULL; - } - - return card_mark_membar; - } - - // trailing_to_leading - // - // graph traversal helper which checks the Mem flow up the graph - // from a (non-card mark) trailing membar attempting to locate and - // return an associated leading membar. it first looks for a - // subgraph in the normal configuration (relying on helper - // normal_to_leading). failing that it then looks for one of the - // possible post-write card mark subgraphs linking the trailing node - // to a the card mark membar (relying on helper - // trailing_to_card_mark), and then checks that the card mark membar - // is fed by a leading membar (once again relying on auxiliary - // predicate normal_to_leading). - // - // if the configuration is valid returns the cpuorder member for - // preference or when absent the release membar otherwise NULL. - // - // n.b. the input membar is expected to be either a volatile or - // acquire membar but in the former case must *not* be a card mark - // membar. - - MemBarNode *trailing_to_leading(const MemBarNode *trailing) - { - assert((trailing->Opcode() == Op_MemBarAcquire || - trailing->Opcode() == Op_MemBarVolatile), - "expecting an acquire or volatile membar"); - assert((trailing->Opcode() != Op_MemBarVolatile || - !is_card_mark_membar(trailing)), - "not expecting a card mark membar"); - - MemBarNode *leading = normal_to_leading(trailing); - - if (leading) { + MemBarNode *leading = x->as_MemBar(); + + if (leading_membar(leading)) { return leading; } - // nothing more to do if this is an acquire - if (trailing->Opcode() == Op_MemBarAcquire) { - return NULL; - } - - MemBarNode *card_mark_membar = trailing_to_card_mark(trailing); - - if (!card_mark_membar) { - return NULL; - } - - return normal_to_leading(card_mark_membar); - } - - // predicates controlling emit of ldr/ldar and associated dmb + return NULL; + } bool unnecessary_acquire(const Node *barrier) { @@ -2675,19 +2590,8 @@ } // must start with a normal feed - MemBarNode *child_barrier = leading_to_normal(barrier); - - if (!child_barrier) { - return false; - } - - if (!is_card_mark_membar(child_barrier)) { - // this is the trailing membar and we are done - return true; - } - - // must be sure this card mark feeds a trailing membar - MemBarNode *trailing = card_mark_to_trailing(child_barrier); + MemBarNode *trailing = leading_to_trailing(barrier); + return (trailing != NULL); } @@ -2709,7 +2613,7 @@ } // ok, if it's not a card mark then we still need to check if it is - // a trailing membar of a volatile put hgraph. + // a trailing membar of a volatile put graph. return (trailing_to_leading(mbvol) != NULL); } @@ -2759,20 +2663,9 @@ } // does this lead a normal subgraph? - MemBarNode *mbvol = leading_to_normal(barrier); - - if (!mbvol) { - return false; - } - - // all done unless this is a card mark - if (!is_card_mark_membar(mbvol)) { - return true; - } - - // we found a card mark -- just make sure we have a trailing barrier - - return (card_mark_to_trailing(mbvol) != NULL); + MemBarNode *trailing = leading_to_trailing(barrier); + + return (trailing != NULL); } // predicate controlling translation of CAS @@ -2814,7 +2707,7 @@ "CAS not fed by cpuorder+release membar pair!"); // does this lead a normal subgraph? - MemBarNode *mbar = leading_to_normal(barrier); + MemBarNode *mbar = leading_to_trailing(barrier); assert(mbar != NULL, "CAS not embedded in normal graph!"); @@ -2835,48 +2728,27 @@ // we only ever need to generate a dmb ishst between an object put // and the associated card mark when we are using CMS without - // conditional card marking + // conditional card marking. Any other occurence will happen when + // performing a card mark using CMS with conditional card marking or + // G1. In those cases the preceding MamBarVolatile will be + // translated to a dmb ish which guarantes visibility of the + // preceding StoreN/P before this StoreCM if (!UseConcMarkSweepGC || UseCondCardMark) { return true; } - // if we are implementing volatile puts using barriers then the - // object put as an str so we must insert the dmb ishst + // if we are implementing volatile puts using barriers then we must + // insert the dmb ishst if (UseBarriersForVolatile) { return false; } - // we can omit the dmb ishst if this StoreCM is part of a volatile - // put because in thta case the put will be implemented by stlr - // - // we need to check for a normal subgraph feeding this StoreCM. - // that means the StoreCM must be fed Memory from a leading membar, - // either a MemBarRelease or its dependent MemBarCPUOrder, and the - // leading membar must be part of a normal subgraph - - Node *x = storecm->in(StoreNode::Memory); - - if (!x->is_Proj()) { - return false; - } - - x = x->in(0); - - if (!x->is_MemBar()) { - return false; - } - - MemBarNode *leading = x->as_MemBar(); - - // reject invalid candidates - if (!leading_membar(leading)) { - return false; - } - - // we can omit the StoreStore if it is the head of a normal subgraph - return (leading_to_normal(leading) != NULL); + // we must be using CMS with conditional card marking so we ahve to + // generate the StoreStore + + return false; } @@ -13409,7 +13281,7 @@ __ fmovs($dst$$Register, as_FloatRegister($src$$reg)); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_f2i); %} @@ -13427,7 +13299,7 @@ __ fmovs(as_FloatRegister($dst$$reg), $src$$Register); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_i2f); %} @@ -13445,7 +13317,7 @@ __ fmovd($dst$$Register, as_FloatRegister($src$$reg)); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_d2l); %} @@ -13463,7 +13335,7 @@ __ fmovd(as_FloatRegister($dst$$reg), $src$$Register); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_l2d); %} @@ -14319,6 +14191,25 @@ ins_pipe(pipe_cmp_branch); %} +instruct cmpN_imm0_branch(cmpOp cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{ + match(If cmp (CmpN op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne + || n->in(1)->as_Bool()->_test._test == BoolTest::eq); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "cbw$cmp $op1, $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + if (cond == Assembler::EQ) + __ cbzw($op1$$Register, *L); + else + __ cbnzw($op1$$Register, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{ match(If cmp (CmpP (DecodeN oop) zero)); predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne @@ -14911,19 +14802,19 @@ %} instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, - iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr) + iRegI_R0 result, rFlagsReg cr) %{ predicate(!CompactStrings); match(Set result (StrEquals (Binary str1 str2) cnt)); - effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); - - format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + + format %{ "String Equals $str1,$str2,$cnt -> $result" %} ins_encode %{ // Count is in 8-bit bytes; non-Compact chars are 16 bits. __ asrw($cnt$$Register, $cnt$$Register, 1); - __ string_equals($str1$$Register, $str2$$Register, - $cnt$$Register, $result$$Register, - $tmp$$Register); + __ arrays_equals($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, + 2, /*is_string*/true); %} ins_pipe(pipe_class_memory); %} @@ -14937,9 +14828,10 @@ format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} ins_encode %{ - __ byte_arrays_equals($ary1$$Register, $ary2$$Register, - $result$$Register, $tmp$$Register); - %} + __ arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, + 1, /*is_string*/false); + %} ins_pipe(pipe_class_memory); %} @@ -14952,12 +14844,14 @@ format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} ins_encode %{ - __ char_arrays_equals($ary1$$Register, $ary2$$Register, - $result$$Register, $tmp$$Register); + __ arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, + 2, /*is_string*/false); %} ins_pipe(pipe_class_memory); %} + // encode char[] to byte[] in ISO_8859_1 instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, vRegD_V0 Vtmp1, vRegD_V1 Vtmp2, @@ -16608,7 +16502,7 @@ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift64_imm); + ins_pipe(vshift64); %} instruct vsll4I(vecX dst, vecX src, vecX shift) %{ @@ -16622,7 +16516,7 @@ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift128_imm); + ins_pipe(vshift128); %} instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ @@ -16635,7 +16529,7 @@ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift64_imm); + ins_pipe(vshift64); %} instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ @@ -16648,7 +16542,7 @@ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift128_imm); + ins_pipe(vshift128); %} instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ @@ -16766,7 +16660,7 @@ as_FloatRegister($src$$reg), (int)$shift$$constant & 63); %} - ins_pipe(vshift128); + ins_pipe(vshift128_imm); %} instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -74,7 +74,7 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) { address pc = _instructions->start() + pc_offset; NativeInstruction* inst = nativeInstruction_at(pc); - if (inst->is_adr_aligned()) { + if (inst->is_adr_aligned() || inst->is_ldr_literal()) { address dest = _constants->start() + data_offset; _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS)); TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -4481,224 +4481,125 @@ BLOCK_COMMENT("} string_compare"); } - -void MacroAssembler::string_equals(Register str1, Register str2, - Register cnt, Register result, - Register tmp1) { - Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING, - NEXT_WORD; - - const Register tmp2 = rscratch1; - assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2); - - BLOCK_COMMENT("string_equals {"); - - // Start by assuming that the strings are not equal. - mov(result, zr); - - // A very short string - cmpw(cnt, 4); - br(Assembler::LT, SHORT_STRING); - - // Check if the strings start at the same location. - cmp(str1, str2); - br(Assembler::EQ, SAME_CHARS); - - // Compare longwords - { - subw(cnt, cnt, 4); // The last longword is a special case - - // Move both string pointers to the last longword of their - // strings, negate the remaining count, and convert it to bytes. - lea(str1, Address(str1, cnt, Address::uxtw(1))); - lea(str2, Address(str2, cnt, Address::uxtw(1))); - sub(cnt, zr, cnt, LSL, 1); - - // Loop, loading longwords and comparing them into rscratch2. - bind(NEXT_WORD); - ldr(tmp1, Address(str1, cnt)); - ldr(tmp2, Address(str2, cnt)); - adds(cnt, cnt, wordSize); - eor(rscratch2, tmp1, tmp2); - cbnz(rscratch2, DONE); - br(Assembler::LT, NEXT_WORD); - - // Last longword. In the case where length == 4 we compare the - // same longword twice, but that's still faster than another - // conditional branch. - - ldr(tmp1, Address(str1)); - ldr(tmp2, Address(str2)); - eor(rscratch2, tmp1, tmp2); - cbz(rscratch2, SAME_CHARS); - b(DONE); - } - - bind(SHORT_STRING); - // Is the length zero? - cbz(cnt, SAME_CHARS); - - bind(SHORT_LOOP); - load_unsigned_short(tmp1, Address(post(str1, 2))); - load_unsigned_short(tmp2, Address(post(str2, 2))); - subw(tmp1, tmp1, tmp2); - cbnz(tmp1, DONE); - sub(cnt, cnt, 1); - cbnz(cnt, SHORT_LOOP); - - // Strings are equal. - bind(SAME_CHARS); - mov(result, true); - - // That's it - bind(DONE); - - BLOCK_COMMENT("} string_equals"); -} - - -void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1) +// Compare Strings or char/byte arrays. + +// is_string is true iff this is a string comparison. + +// For Strings we're passed the address of the first characters in a1 +// and a2 and the length in cnt1. + +// For byte and char arrays we're passed the arrays themselves and we +// have to extract length fields and do null checks here. + +// elem_size is the element size in bytes: either 1 or 2. + +// There are two implementations. For arrays >= 8 bytes, all +// comparisons (including the final one, which may overlap) are +// performed 8 bytes at a time. For arrays < 8 bytes, we compare a +// halfword, then a short, and then a byte. + +void MacroAssembler::arrays_equals(Register a1, Register a2, + Register result, Register cnt1, + int elem_size, bool is_string) { - Register cnt1 = rscratch1; - Register cnt2 = rscratch2; + Label SAME, DONE, SHORT, NEXT_WORD, ONE; + Register tmp1 = rscratch1; Register tmp2 = rscratch2; - - Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - - BLOCK_COMMENT("byte_arrays_equals {"); - - // different until proven equal - mov(result, false); - - // same array? - cmp(ary1, ary2); - br(Assembler::EQ, SAME); - - // ne if either null - cbz(ary1, DIFFER); - cbz(ary2, DIFFER); - - // lengths ne? - ldrw(cnt1, Address(ary1, length_offset)); - ldrw(cnt2, Address(ary2, length_offset)); - cmp(cnt1, cnt2); - br(Assembler::NE, DIFFER); - - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - - subs(cnt1, cnt1, 8); - br(LT, TAIL07); - - BIND(NEXT); - ldr(tmp1, Address(post(ary1, 8))); - ldr(tmp2, Address(post(ary2, 8))); - subs(cnt1, cnt1, 8); + Register cnt2 = tmp2; // cnt2 only used in array length compare + int elem_per_word = wordSize/elem_size; + int log_elem_size = exact_log2(elem_size); + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset + = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); + + assert(elem_size == 1 || elem_size == 2, "must be char or byte"); + assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2); + + BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {"); + + mov(result, false); + + if (!is_string) { + // if (a==a2) + // return true; + eor(rscratch1, a1, a2); + cbz(rscratch1, SAME); + // if (a==null || a2==null) + // return false; + cbz(a1, DONE); + cbz(a2, DONE); + // if (a1.length != a2.length) + // return false; + ldrw(cnt1, Address(a1, length_offset)); + ldrw(cnt2, Address(a2, length_offset)); + eorw(tmp1, cnt1, cnt2); + cbnzw(tmp1, DONE); + + lea(a1, Address(a1, base_offset)); + lea(a2, Address(a2, base_offset)); + } + + // Check for short strings, i.e. smaller than wordSize. + subs(cnt1, cnt1, elem_per_word); + br(Assembler::LT, SHORT); + // Main 8 byte comparison loop. + bind(NEXT_WORD); { + ldr(tmp1, Address(post(a1, wordSize))); + ldr(tmp2, Address(post(a2, wordSize))); + subs(cnt1, cnt1, elem_per_word); eor(tmp1, tmp1, tmp2); - cbnz(tmp1, DIFFER); - br(GE, NEXT); - - BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4 - tst(cnt1, 0b100); - br(EQ, TAIL03); - ldrw(tmp1, Address(post(ary1, 4))); - ldrw(tmp2, Address(post(ary2, 4))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4 - tst(cnt1, 0b10); - br(EQ, TAIL01); - ldrh(tmp1, Address(post(ary1, 2))); - ldrh(tmp2, Address(post(ary2, 2))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - BIND(TAIL01); // 0-1 byte left - tst(cnt1, 0b01); - br(EQ, SAME); - ldrb(tmp1, ary1); - ldrb(tmp2, ary2); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(SAME); - mov(result, true); - BIND(DIFFER); // result already set - - BLOCK_COMMENT("} byte_arrays_equals"); + cbnz(tmp1, DONE); + } br(GT, NEXT_WORD); + // Last longword. In the case where length == 4 we compare the + // same longword twice, but that's still faster than another + // conditional branch. + // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when + // length == 4. + if (log_elem_size > 0) + lsl(cnt1, cnt1, log_elem_size); + ldr(tmp1, Address(a1, cnt1)); + ldr(tmp2, Address(a2, cnt1)); + eor(tmp1, tmp1, tmp2); + cbnz(tmp1, DONE); + b(SAME); + + bind(SHORT); + Label TAIL03, TAIL01; + + tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left. + { + ldrw(tmp1, Address(post(a1, 4))); + ldrw(tmp2, Address(post(a2, 4))); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + bind(TAIL03); + tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left. + { + ldrh(tmp1, Address(post(a1, 2))); + ldrh(tmp2, Address(post(a2, 2))); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + bind(TAIL01); + if (elem_size == 1) { // Only needed when comparing byte arrays. + tbz(cnt1, 0, SAME); // 0-1 bytes left. + { + ldrb(tmp1, a1); + ldrb(tmp2, a2); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + } + // Arrays are equal. + bind(SAME); + mov(result, true); + + // That's it. + bind(DONE); + BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals"); } -// Compare char[] arrays aligned to 4 bytes -void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1) -{ - Register cnt1 = rscratch1; - Register cnt2 = rscratch2; - Register tmp2 = rscratch2; - - Label SAME, DIFFER, NEXT, TAIL03, TAIL01; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - BLOCK_COMMENT("char_arrays_equals {"); - - // different until proven equal - mov(result, false); - - // same array? - cmp(ary1, ary2); - br(Assembler::EQ, SAME); - - // ne if either null - cbz(ary1, DIFFER); - cbz(ary2, DIFFER); - - // lengths ne? - ldrw(cnt1, Address(ary1, length_offset)); - ldrw(cnt2, Address(ary2, length_offset)); - cmp(cnt1, cnt2); - br(Assembler::NE, DIFFER); - - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - - subs(cnt1, cnt1, 4); - br(LT, TAIL03); - - BIND(NEXT); - ldr(tmp1, Address(post(ary1, 8))); - ldr(tmp2, Address(post(ary2, 8))); - subs(cnt1, cnt1, 4); - eor(tmp1, tmp1, tmp2); - cbnz(tmp1, DIFFER); - br(GE, NEXT); - - BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4 - tst(cnt1, 0b10); - br(EQ, TAIL01); - ldrw(tmp1, Address(post(ary1, 4))); - ldrw(tmp2, Address(post(ary2, 4))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - BIND(TAIL01); // 0-1 chars left - tst(cnt1, 0b01); - br(EQ, SAME); - ldrh(tmp1, ary1); - ldrh(tmp2, ary2); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(SAME); - mov(result, true); - BIND(DIFFER); // result already set - - BLOCK_COMMENT("} char_arrays_equals"); -} // encode char[] to byte[] in ISO_8859_1 void MacroAssembler::encode_iso_array(Register src, Register dst, diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1186,13 +1186,11 @@ void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, Register tmp1); - void string_equals(Register str1, Register str2, - Register cnt, Register result, - Register tmp1); - void char_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1); - void byte_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1); + + void arrays_equals(Register a1, Register a2, + Register result, Register cnt1, + int elem_size, bool is_string); + void encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -105,13 +105,20 @@ inline friend NativeInstruction* nativeInstruction_at(address address); static bool is_adrp_at(address instr); + static bool is_ldr_literal_at(address instr); + + bool is_ldr_literal() { + return is_ldr_literal_at(addr_at(0)); + } + static bool is_ldrw_to_zr(address instr); static bool is_call_at(address instr) { const uint32_t insn = (*(uint32_t*)instr); return (insn >> 26) == 0b100101; } + bool is_call() { return is_call_at(addr_at(0)); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -163,30 +163,20 @@ sp_after_call_off = -26, d15_off = -26, - d14_off = -25, d13_off = -24, - d12_off = -23, d11_off = -22, - d10_off = -21, d9_off = -20, - d8_off = -19, r28_off = -18, - r27_off = -17, r26_off = -16, - r25_off = -15, r24_off = -14, - r23_off = -13, r22_off = -12, - r21_off = -11, r20_off = -10, - r19_off = -9, call_wrapper_off = -8, result_off = -7, result_type_off = -6, method_off = -5, entry_point_off = -4, - parameters_off = -3, parameter_size_off = -2, thread_off = -1, fp_f = 0, @@ -208,30 +198,20 @@ const Address result_type (rfp, result_type_off * wordSize); const Address method (rfp, method_off * wordSize); const Address entry_point (rfp, entry_point_off * wordSize); - const Address parameters (rfp, parameters_off * wordSize); const Address parameter_size(rfp, parameter_size_off * wordSize); const Address thread (rfp, thread_off * wordSize); const Address d15_save (rfp, d15_off * wordSize); - const Address d14_save (rfp, d14_off * wordSize); const Address d13_save (rfp, d13_off * wordSize); - const Address d12_save (rfp, d12_off * wordSize); const Address d11_save (rfp, d11_off * wordSize); - const Address d10_save (rfp, d10_off * wordSize); const Address d9_save (rfp, d9_off * wordSize); - const Address d8_save (rfp, d8_off * wordSize); const Address r28_save (rfp, r28_off * wordSize); - const Address r27_save (rfp, r27_off * wordSize); const Address r26_save (rfp, r26_off * wordSize); - const Address r25_save (rfp, r25_off * wordSize); const Address r24_save (rfp, r24_off * wordSize); - const Address r23_save (rfp, r23_off * wordSize); const Address r22_save (rfp, r22_off * wordSize); - const Address r21_save (rfp, r21_off * wordSize); const Address r20_save (rfp, r20_off * wordSize); - const Address r19_save (rfp, r19_off * wordSize); // stub code @@ -254,31 +234,20 @@ // rthread because we want to sanity check rthread later __ str(c_rarg7, thread); __ strw(c_rarg6, parameter_size); - __ str(c_rarg5, parameters); - __ str(c_rarg4, entry_point); - __ str(c_rarg3, method); - __ str(c_rarg2, result_type); - __ str(c_rarg1, result); - __ str(c_rarg0, call_wrapper); - __ str(r19, r19_save); - __ str(r20, r20_save); - __ str(r21, r21_save); - __ str(r22, r22_save); - __ str(r23, r23_save); - __ str(r24, r24_save); - __ str(r25, r25_save); - __ str(r26, r26_save); - __ str(r27, r27_save); - __ str(r28, r28_save); - - __ strd(v8, d8_save); - __ strd(v9, d9_save); - __ strd(v10, d10_save); - __ strd(v11, d11_save); - __ strd(v12, d12_save); - __ strd(v13, d13_save); - __ strd(v14, d14_save); - __ strd(v15, d15_save); + __ stp(c_rarg4, c_rarg5, entry_point); + __ stp(c_rarg2, c_rarg3, result_type); + __ stp(c_rarg0, c_rarg1, call_wrapper); + + __ stp(r20, r19, r20_save); + __ stp(r22, r21, r22_save); + __ stp(r24, r23, r24_save); + __ stp(r26, r25, r26_save); + __ stp(r28, r27, r28_save); + + __ stpd(v9, v8, d9_save); + __ stpd(v11, v10, d11_save); + __ stpd(v13, v12, d13_save); + __ stpd(v15, v14, d15_save); // install Java thread in global register now we have saved // whatever value it held @@ -385,33 +354,22 @@ #endif // restore callee-save registers - __ ldrd(v15, d15_save); - __ ldrd(v14, d14_save); - __ ldrd(v13, d13_save); - __ ldrd(v12, d12_save); - __ ldrd(v11, d11_save); - __ ldrd(v10, d10_save); - __ ldrd(v9, d9_save); - __ ldrd(v8, d8_save); - - __ ldr(r28, r28_save); - __ ldr(r27, r27_save); - __ ldr(r26, r26_save); - __ ldr(r25, r25_save); - __ ldr(r24, r24_save); - __ ldr(r23, r23_save); - __ ldr(r22, r22_save); - __ ldr(r21, r21_save); - __ ldr(r20, r20_save); - __ ldr(r19, r19_save); - __ ldr(c_rarg0, call_wrapper); - __ ldr(c_rarg1, result); + __ ldpd(v15, v14, d15_save); + __ ldpd(v13, v12, d13_save); + __ ldpd(v11, v10, d11_save); + __ ldpd(v9, v8, d9_save); + + __ ldp(r28, r27, r28_save); + __ ldp(r26, r25, r26_save); + __ ldp(r24, r23, r24_save); + __ ldp(r22, r21, r22_save); + __ ldp(r20, r19, r20_save); + + __ ldp(c_rarg0, c_rarg1, call_wrapper); __ ldrw(c_rarg2, result_type); __ ldr(c_rarg3, method); - __ ldr(c_rarg4, entry_point); - __ ldr(c_rarg5, parameters); - __ ldr(c_rarg6, parameter_size); - __ ldr(c_rarg7, thread); + __ ldp(c_rarg4, c_rarg5, entry_point); + __ ldp(c_rarg6, c_rarg7, parameter_size); #ifndef PRODUCT // tell the simulator we are about to end Java execution @@ -666,7 +624,7 @@ // count - element count // tmp - scratch register // - // Destroy no registers! + // Destroy no registers except rscratch1 and rscratch2 // void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) { BarrierSet* bs = Universe::heap()->barrier_set(); @@ -674,12 +632,13 @@ case BarrierSet::G1SATBCTLogging: // With G1, don't generate the call if we statically know that the target in uninitialized if (!dest_uninitialized) { - __ push(RegSet::range(r0, r29), sp); // integer registers except lr & sp + __ push_call_clobbered_registers(); if (count == c_rarg0) { if (addr == c_rarg1) { // exactly backwards!! - __ stp(c_rarg0, c_rarg1, __ pre(sp, -2 * wordSize)); - __ ldp(c_rarg1, c_rarg0, __ post(sp, -2 * wordSize)); + __ mov(rscratch1, c_rarg0); + __ mov(c_rarg0, c_rarg1); + __ mov(c_rarg1, rscratch1); } else { __ mov(c_rarg1, count); __ mov(c_rarg0, addr); @@ -689,7 +648,7 @@ __ mov(c_rarg1, count); } __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); - __ pop(RegSet::range(r0, r29), sp); // integer registers except lr & sp } + __ pop_call_clobbered_registers(); break; case BarrierSet::CardTableForRS: case BarrierSet::CardTableExtension: @@ -719,7 +678,7 @@ case BarrierSet::G1SATBCTLogging: { - __ push(RegSet::range(r0, r29), sp); // integer registers except lr & sp + __ push_call_clobbered_registers(); // must compute element count unless barrier set interface is changed (other platforms supply count) assert_different_registers(start, end, scratch); __ lea(scratch, Address(end, BytesPerHeapOop)); @@ -728,7 +687,7 @@ __ mov(c_rarg0, start); __ mov(c_rarg1, scratch); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); - __ pop(RegSet::range(r0, r29), sp); // integer registers except lr & sp } + __ pop_call_clobbered_registers(); } break; case BarrierSet::CardTableForRS: @@ -1394,10 +1353,10 @@ // no-overlap entry point used by generate_conjoint_long_oop_copy(). // address generate_disjoint_oop_copy(bool aligned, address *entry, - const char *name, bool dest_uninitialized = false) { + const char *name, bool dest_uninitialized) { const bool is_oop = true; const size_t size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); - return generate_disjoint_copy(size, aligned, is_oop, entry, name); + return generate_disjoint_copy(size, aligned, is_oop, entry, name, dest_uninitialized); } // Arguments: @@ -1412,10 +1371,11 @@ // address generate_conjoint_oop_copy(bool aligned, address nooverlap_target, address *entry, - const char *name, bool dest_uninitialized = false) { + const char *name, bool dest_uninitialized) { const bool is_oop = true; const size_t size = UseCompressedOops ? sizeof (jint) : sizeof (jlong); - return generate_conjoint_copy(size, aligned, is_oop, nooverlap_target, entry, name); + return generate_conjoint_copy(size, aligned, is_oop, nooverlap_target, entry, + name, dest_uninitialized); } @@ -1522,6 +1482,8 @@ } #endif //ASSERT + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); + // save the original count __ mov(count_save, count); @@ -1988,9 +1950,11 @@ bool aligned = !UseCompressedOops; StubRoutines::_arrayof_oop_disjoint_arraycopy - = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy"); + = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy", + /*dest_uninitialized*/false); StubRoutines::_arrayof_oop_arraycopy - = generate_conjoint_oop_copy(aligned, entry, &entry_oop_arraycopy, "arrayof_oop_arraycopy"); + = generate_conjoint_oop_copy(aligned, entry, &entry_oop_arraycopy, "arrayof_oop_arraycopy", + /*dest_uninitialized*/false); // Aligned versions without pre-barriers StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(aligned, &entry, "arrayof_oop_disjoint_arraycopy_uninit", diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/globals_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,7 @@ define_pd_global(uintx, TypeProfileLevel, 111); -// No performance work done here yet. -define_pd_global(bool, CompactStrings, false); +define_pd_global(bool, CompactStrings, true); // Platform dependent flag handling: flags only defined on this platform. #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -45,6 +45,9 @@ #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegion.hpp" #endif // INCLUDE_ALL_GCS +#ifdef COMPILER2 +#include "opto/intrinsicnode.hpp" +#endif #ifdef PRODUCT #define BLOCK_COMMENT(str) // nothing @@ -3168,6 +3171,553 @@ /////////////////////////////////////////// String intrinsics //////////////////////////////////////////// +#ifdef COMPILER2 +// Intrinsics for CompactStrings + +// Compress char[] to byte[] by compressing 16 bytes at once. +void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, + Label& Lfailure) { + + const Register tmp0 = R0; + assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5); + Label Lloop, Lslow; + + // Check if cnt >= 8 (= 16 bytes) + lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF00FF00FF + srwi_(tmp2, cnt, 3); + beq(CCR0, Lslow); + ori(tmp1, tmp1, 0xFF); + rldimi(tmp1, tmp1, 32, 0); + mtctr(tmp2); + + // 2x unrolled loop + bind(Lloop); + ld(tmp2, 0, src); // _0_1_2_3 (Big Endian) + ld(tmp4, 8, src); // _4_5_6_7 + + orr(tmp0, tmp2, tmp4); + rldicl(tmp3, tmp2, 6*8, 64-24); // _____1_2 + rldimi(tmp2, tmp2, 2*8, 2*8); // _0_2_3_3 + rldicl(tmp5, tmp4, 6*8, 64-24); // _____5_6 + rldimi(tmp4, tmp4, 2*8, 2*8); // _4_6_7_7 + + andc_(tmp0, tmp0, tmp1); + bne(CCR0, Lfailure); // Not latin1. + addi(src, src, 16); + + rlwimi(tmp3, tmp2, 0*8, 24, 31);// _____1_3 + srdi(tmp2, tmp2, 3*8); // ____0_2_ + rlwimi(tmp5, tmp4, 0*8, 24, 31);// _____5_7 + srdi(tmp4, tmp4, 3*8); // ____4_6_ + + orr(tmp2, tmp2, tmp3); // ____0123 + orr(tmp4, tmp4, tmp5); // ____4567 + + stw(tmp2, 0, dst); + stw(tmp4, 4, dst); + addi(dst, dst, 8); + bdnz(Lloop); + + bind(Lslow); // Fallback to slow version +} + +// Compress char[] to byte[]. cnt must be positive int. +void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure) { + Label Lloop; + mtctr(cnt); + + bind(Lloop); + lhz(tmp, 0, src); + cmplwi(CCR0, tmp, 0xff); + bgt(CCR0, Lfailure); // Not latin1. + addi(src, src, 2); + stb(tmp, 0, dst); + addi(dst, dst, 1); + bdnz(Lloop); +} + +// Inflate byte[] to char[] by inflating 16 bytes at once. +void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) { + const Register tmp0 = R0; + assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5); + Label Lloop, Lslow; + + // Check if cnt >= 8 + srwi_(tmp2, cnt, 3); + beq(CCR0, Lslow); + lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF + ori(tmp1, tmp1, 0xFF); + mtctr(tmp2); + + // 2x unrolled loop + bind(Lloop); + lwz(tmp2, 0, src); // ____0123 (Big Endian) + lwz(tmp4, 4, src); // ____4567 + addi(src, src, 8); + + rldicl(tmp3, tmp2, 7*8, 64-8); // _______2 + rlwimi(tmp2, tmp2, 3*8, 16, 23);// ____0113 + rldicl(tmp5, tmp4, 7*8, 64-8); // _______6 + rlwimi(tmp4, tmp4, 3*8, 16, 23);// ____4557 + + andc(tmp0, tmp2, tmp1); // ____0_1_ + rlwimi(tmp2, tmp3, 2*8, 0, 23); // _____2_3 + andc(tmp3, tmp4, tmp1); // ____4_5_ + rlwimi(tmp4, tmp5, 2*8, 0, 23); // _____6_7 + + rldimi(tmp2, tmp0, 3*8, 0*8); // _0_1_2_3 + rldimi(tmp4, tmp3, 3*8, 0*8); // _4_5_6_7 + + std(tmp2, 0, dst); + std(tmp4, 8, dst); + addi(dst, dst, 16); + bdnz(Lloop); + + bind(Lslow); // Fallback to slow version +} + +// Inflate byte[] to char[]. cnt must be positive int. +void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp) { + Label Lloop; + mtctr(cnt); + + bind(Lloop); + lbz(tmp, 0, src); + addi(src, src, 1); + sth(tmp, 0, dst); + addi(dst, dst, 2); + bdnz(Lloop); +} + +void MacroAssembler::string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, + Register tmp1, Register result, int ae) { + const Register tmp0 = R0, + diff = tmp1; + + assert_different_registers(str1, str2, cnt1, cnt2, tmp0, tmp1, result); + Label Ldone, Lslow, Lloop, Lreturn_diff; + + // Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a) + // we interchange str1 and str2 in the UL case and negate the result. + // Like this, str1 is always latin1 encoded, except for the UU case. + // In addition, we need 0 (or sign which is 0) extend. + + if (ae == StrIntrinsicNode::UU) { + srwi(cnt1, cnt1, 1); + } else { + clrldi(cnt1, cnt1, 32); + } + + if (ae != StrIntrinsicNode::LL) { + srwi(cnt2, cnt2, 1); + } else { + clrldi(cnt2, cnt2, 32); + } + + // See if the lengths are different, and calculate min in cnt1. + // Save diff in case we need it for a tie-breaker. + subf_(diff, cnt2, cnt1); // diff = cnt1 - cnt2 + // if (diff > 0) { cnt1 = cnt2; } + if (VM_Version::has_isel()) { + isel(cnt1, CCR0, Assembler::greater, /*invert*/ false, cnt2); + } else { + Label Lskip; + blt(CCR0, Lskip); + mr(cnt1, cnt2); + bind(Lskip); + } + + // Rename registers + Register chr1 = result; + Register chr2 = tmp0; + + // Compare multiple characters in fast loop (only implemented for same encoding). + int stride1 = 8, stride2 = 8; + if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { + int log2_chars_per_iter = (ae == StrIntrinsicNode::LL) ? 3 : 2; + Label Lfastloop, Lskipfast; + + srwi_(tmp0, cnt1, log2_chars_per_iter); + beq(CCR0, Lskipfast); + rldicl(cnt2, cnt1, 0, 64 - log2_chars_per_iter); // Remaining characters. + li(cnt1, 1 << log2_chars_per_iter); // Initialize for failure case: Rescan characters from current iteration. + mtctr(tmp0); + + bind(Lfastloop); + ld(chr1, 0, str1); + ld(chr2, 0, str2); + cmpd(CCR0, chr1, chr2); + bne(CCR0, Lslow); + addi(str1, str1, stride1); + addi(str2, str2, stride2); + bdnz(Lfastloop); + mr(cnt1, cnt2); // Remaining characters. + bind(Lskipfast); + } + + // Loop which searches the first difference character by character. + cmpwi(CCR0, cnt1, 0); + beq(CCR0, Lreturn_diff); + bind(Lslow); + mtctr(cnt1); + + switch (ae) { + case StrIntrinsicNode::LL: stride1 = 1; stride2 = 1; break; + case StrIntrinsicNode::UL: // fallthru (see comment above) + case StrIntrinsicNode::LU: stride1 = 1; stride2 = 2; break; + case StrIntrinsicNode::UU: stride1 = 2; stride2 = 2; break; + default: ShouldNotReachHere(); break; + } + + bind(Lloop); + if (stride1 == 1) { lbz(chr1, 0, str1); } else { lhz(chr1, 0, str1); } + if (stride2 == 1) { lbz(chr2, 0, str2); } else { lhz(chr2, 0, str2); } + subf_(result, chr2, chr1); // result = chr1 - chr2 + bne(CCR0, Ldone); + addi(str1, str1, stride1); + addi(str2, str2, stride2); + bdnz(Lloop); + + // If strings are equal up to min length, return the length difference. + bind(Lreturn_diff); + mr(result, diff); + + // Otherwise, return the difference between the first mismatched chars. + bind(Ldone); + if (ae == StrIntrinsicNode::UL) { + neg(result, result); // Negate result (see note above). + } +} + +void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register tmp1, Register result, bool is_byte) { + const Register tmp0 = R0; + assert_different_registers(ary1, ary2, limit, tmp0, tmp1, result); + Label Ldone, Lskiploop, Lloop, Lfastloop, Lskipfast; + bool limit_needs_shift = false; + + if (is_array_equ) { + const int length_offset = arrayOopDesc::length_offset_in_bytes(); + const int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR); + + // Return true if the same array. + cmpd(CCR0, ary1, ary2); + beq(CCR0, Lskiploop); + + // Return false if one of them is NULL. + cmpdi(CCR0, ary1, 0); + cmpdi(CCR1, ary2, 0); + li(result, 0); + cror(CCR0, Assembler::equal, CCR1, Assembler::equal); + beq(CCR0, Ldone); + + // Load the lengths of arrays. + lwz(limit, length_offset, ary1); + lwz(tmp0, length_offset, ary2); + + // Return false if the two arrays are not equal length. + cmpw(CCR0, limit, tmp0); + bne(CCR0, Ldone); + + // Load array addresses. + addi(ary1, ary1, base_offset); + addi(ary2, ary2, base_offset); + } else { + limit_needs_shift = !is_byte; + li(result, 0); // Assume not equal. + } + + // Rename registers + Register chr1 = tmp0; + Register chr2 = tmp1; + + // Compare 8 bytes per iteration in fast loop. + const int log2_chars_per_iter = is_byte ? 3 : 2; + + srwi_(tmp0, limit, log2_chars_per_iter + (limit_needs_shift ? 1 : 0)); + beq(CCR0, Lskipfast); + mtctr(tmp0); + + bind(Lfastloop); + ld(chr1, 0, ary1); + ld(chr2, 0, ary2); + addi(ary1, ary1, 8); + addi(ary2, ary2, 8); + cmpd(CCR0, chr1, chr2); + bne(CCR0, Ldone); + bdnz(Lfastloop); + + bind(Lskipfast); + rldicl_(limit, limit, limit_needs_shift ? 64 - 1 : 0, 64 - log2_chars_per_iter); // Remaining characters. + beq(CCR0, Lskiploop); + mtctr(limit); + + // Character by character. + bind(Lloop); + if (is_byte) { + lbz(chr1, 0, ary1); + lbz(chr2, 0, ary2); + addi(ary1, ary1, 1); + addi(ary2, ary2, 1); + } else { + lhz(chr1, 0, ary1); + lhz(chr2, 0, ary2); + addi(ary1, ary1, 2); + addi(ary2, ary2, 2); + } + cmpw(CCR0, chr1, chr2); + bne(CCR0, Ldone); + bdnz(Lloop); + + bind(Lskiploop); + li(result, 1); // All characters are equal. + bind(Ldone); +} + +void MacroAssembler::string_indexof(Register result, Register haystack, Register haycnt, + Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae) { + + // Ensure 0=2, bail out otherwise. + // ************************************************************************************************** + + // Compute last haystack addr to use if no match gets found. + clrldi(haycnt, haycnt, 32); // Ensure positive int is valid as 64 bit value. + addi(addr, haystack, -h_csize); // Accesses use pre-increment. + if (needlecntval == 0) { // variable needlecnt + cmpwi(CCR6, needlecnt, 2); + clrldi(needlecnt, needlecnt, 32); // Ensure positive int is valid as 64 bit value. + blt(CCR6, L_TooShort); // Variable needlecnt: handle short needle separately. + } + + if (n_csize == 2) { lwz(n_start, 0, needle); } else { lhz(n_start, 0, needle); } // Load first 2 characters of needle. + + if (needlecntval == 0) { // variable needlecnt + subf(ch1, needlecnt, haycnt); // Last character index to compare is haycnt-needlecnt. + addi(needlecnt, needlecnt, -2); // Rest of needle. + } else { // constant needlecnt + guarantee(needlecntval != 1, "IndexOf with single-character needle must be handled separately"); + assert((needlecntval & 0x7fff) == needlecntval, "wrong immediate"); + addi(ch1, haycnt, -needlecntval); // Last character index to compare is haycnt-needlecnt. + if (needlecntval > 3) { li(needlecnt, needlecntval - 2); } // Rest of needle. + } + + if (h_csize == 2) { slwi(ch1, ch1, 1); } // Scale to number of bytes. + + if (ae ==StrIntrinsicNode::UL) { + srwi(tmp4, n_start, 1*8); // ___0 + rlwimi(n_start, tmp4, 2*8, 0, 23); // _0_1 + } + + add(last_addr, haystack, ch1); // Point to last address to compare (haystack+2*(haycnt-needlecnt)). + + // Main Loop (now we have at least 2 characters). + Label L_OuterLoop, L_InnerLoop, L_FinalCheck, L_Comp1, L_Comp2; + bind(L_OuterLoop); // Search for 1st 2 characters. + Register addr_diff = tmp4; + subf(addr_diff, addr, last_addr); // Difference between already checked address and last address to check. + addi(addr, addr, h_csize); // This is the new address we want to use for comparing. + srdi_(ch2, addr_diff, h_csize); + beq(CCR0, L_FinalCheck); // 2 characters left? + mtctr(ch2); // num of characters / 2 + bind(L_InnerLoop); // Main work horse (2x unrolled search loop) + if (h_csize == 2) { // Load 2 characters of haystack (ignore alignment). + lwz(ch1, 0, addr); + lwz(ch2, 2, addr); + } else { + lhz(ch1, 0, addr); + lhz(ch2, 1, addr); + } + cmpw(CCR0, ch1, n_start); // Compare 2 characters (1 would be sufficient but try to reduce branches to CompLoop). + cmpw(CCR1, ch2, n_start); + beq(CCR0, L_Comp1); // Did we find the needle start? + beq(CCR1, L_Comp2); + addi(addr, addr, 2 * h_csize); + bdnz(L_InnerLoop); + bind(L_FinalCheck); + andi_(addr_diff, addr_diff, h_csize); // Remaining characters not covered by InnerLoop: (num of characters) & 1. + beq(CCR0, L_NotFound); + if (h_csize == 2) { lwz(ch1, 0, addr); } else { lhz(ch1, 0, addr); } // One position left at which we have to compare. + cmpw(CCR1, ch1, n_start); + beq(CCR1, L_Comp1); + bind(L_NotFound); + li(result, -1); // not found + b(L_End); + + // ************************************************************************************************** + // Special Case: unfortunately, the variable needle case can be called with needlecnt<2 + // ************************************************************************************************** + if (needlecntval == 0) { // We have to handle these cases separately. + Label L_OneCharLoop; + bind(L_TooShort); + mtctr(haycnt); + if (n_csize == 2) { lhz(n_start, 0, needle); } else { lbz(n_start, 0, needle); } // First character of needle + bind(L_OneCharLoop); + if (h_csize == 2) { lhzu(ch1, 2, addr); } else { lbzu(ch1, 1, addr); } + cmpw(CCR1, ch1, n_start); + beq(CCR1, L_Found); // Did we find the one character needle? + bdnz(L_OneCharLoop); + li(result, -1); // Not found. + b(L_End); + } + + // ************************************************************************************************** + // Regular Case Part II: compare rest of needle (first 2 characters have been compared already) + // ************************************************************************************************** + + // Compare the rest + bind(L_Comp2); + addi(addr, addr, h_csize); // First comparison has failed, 2nd one hit. + bind(L_Comp1); // Addr points to possible needle start. + if (needlecntval != 2) { // Const needlecnt==2? + if (needlecntval != 3) { + if (needlecntval == 0) { beq(CCR6, L_Found); } // Variable needlecnt==2? + Register n_ind = tmp4, + h_ind = n_ind; + li(n_ind, 2 * n_csize); // First 2 characters are already compared, use index 2. + mtctr(needlecnt); // Decremented by 2, still > 0. + Label L_CompLoop; + bind(L_CompLoop); + if (ae ==StrIntrinsicNode::UL) { + h_ind = ch1; + sldi(h_ind, n_ind, 1); + } + if (n_csize == 2) { lhzx(ch2, needle, n_ind); } else { lbzx(ch2, needle, n_ind); } + if (h_csize == 2) { lhzx(ch1, addr, h_ind); } else { lbzx(ch1, addr, h_ind); } + cmpw(CCR1, ch1, ch2); + bne(CCR1, L_OuterLoop); + addi(n_ind, n_ind, n_csize); + bdnz(L_CompLoop); + } else { // No loop required if there's only one needle character left. + if (n_csize == 2) { lhz(ch2, 2 * 2, needle); } else { lbz(ch2, 2 * 1, needle); } + if (h_csize == 2) { lhz(ch1, 2 * 2, addr); } else { lbz(ch1, 2 * 1, addr); } + cmpw(CCR1, ch1, ch2); + bne(CCR1, L_OuterLoop); + } + } + // Return index ... + bind(L_Found); + subf(result, haystack, addr); // relative to haystack, ... + if (h_csize == 2) { srdi(result, result, 1); } // in characters. + bind(L_End); +} // string_indexof + +void MacroAssembler::string_indexof_char(Register result, Register haystack, Register haycnt, + Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte) { + assert_different_registers(haystack, haycnt, needle, tmp1, tmp2); + + Label L_InnerLoop, L_FinalCheck, L_Found1, L_Found2, L_NotFound, L_End; + Register addr = tmp1, + ch1 = tmp2, + ch2 = R0; + + const int h_csize = is_byte ? 1 : 2; + +//4: + srwi_(tmp2, haycnt, 1); // Shift right by exact_log2(UNROLL_FACTOR). + mr(addr, haystack); + beq(CCR0, L_FinalCheck); + mtctr(tmp2); // Move to count register. +//8: + bind(L_InnerLoop); // Main work horse (2x unrolled search loop). + if (!is_byte) { + lhz(ch1, 0, addr); + lhz(ch2, 2, addr); + } else { + lbz(ch1, 0, addr); + lbz(ch2, 1, addr); + } + (needle != R0) ? cmpw(CCR0, ch1, needle) : cmplwi(CCR0, ch1, (unsigned int)needleChar); + (needle != R0) ? cmpw(CCR1, ch2, needle) : cmplwi(CCR1, ch2, (unsigned int)needleChar); + beq(CCR0, L_Found1); // Did we find the needle? + beq(CCR1, L_Found2); + addi(addr, addr, 2 * h_csize); + bdnz(L_InnerLoop); +//16: + bind(L_FinalCheck); + andi_(R0, haycnt, 1); + beq(CCR0, L_NotFound); + if (!is_byte) { lhz(ch1, 0, addr); } else { lbz(ch1, 0, addr); } // One position left at which we have to compare. + (needle != R0) ? cmpw(CCR1, ch1, needle) : cmplwi(CCR1, ch1, (unsigned int)needleChar); + beq(CCR1, L_Found1); +//21: + bind(L_NotFound); + li(result, -1); // Not found. + b(L_End); + + bind(L_Found2); + addi(addr, addr, h_csize); +//24: + bind(L_Found1); // Return index ... + subf(result, haystack, addr); // relative to haystack, ... + if (!is_byte) { srdi(result, result, 1); } // in characters. + bind(L_End); +} // string_indexof_char + + +void MacroAssembler::has_negatives(Register src, Register cnt, Register result, + Register tmp1, Register tmp2) { + const Register tmp0 = R0; + assert_different_registers(src, result, cnt, tmp0, tmp1, tmp2); + Label Lfastloop, Lslow, Lloop, Lnoneg, Ldone; + + // Check if cnt >= 8 (= 16 bytes) + lis(tmp1, (int)(short)0x8080); // tmp1 = 0x8080808080808080 + srwi_(tmp2, cnt, 4); + li(result, 1); // Assume there's a negative byte. + beq(CCR0, Lslow); + ori(tmp1, tmp1, 0x8080); + rldimi(tmp1, tmp1, 32, 0); + mtctr(tmp2); + + // 2x unrolled loop + bind(Lfastloop); + ld(tmp2, 0, src); + ld(tmp0, 8, src); + + orr(tmp0, tmp2, tmp0); + + and_(tmp0, tmp0, tmp1); + bne(CCR0, Ldone); // Found negative byte. + addi(src, src, 16); + + bdnz(Lfastloop); + + bind(Lslow); // Fallback to slow version + rldicl_(tmp0, cnt, 0, 64-4); + beq(CCR0, Lnoneg); + mtctr(tmp0); + bind(Lloop); + lbz(tmp0, 0, src); + addi(src, src, 1); + andi_(tmp0, tmp0, 0x80); + bne(CCR0, Ldone); // Found negative byte. + bdnz(Lloop); + bind(Lnoneg); + li(result, 0); + + bind(Ldone); +} + + +// Intrinsics for non-CompactStrings + // Search for a single jchar in an jchar[]. // // Assumes that result differs from all other registers. @@ -3613,6 +4163,8 @@ bind(Ldone_false); } +#endif // Compiler2 + // Helpers for Intrinsic Emitters // // Revert the byte order of a 32bit value in a register diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -679,6 +679,39 @@ void clear_memory_doubleword(Register base_ptr, Register cnt_dwords, Register tmp = R0); +#ifdef COMPILER2 + // Intrinsics for CompactStrings + // Compress char[] to byte[] by compressing 16 bytes at once. + void string_compress_16(Register src, Register dst, Register cnt, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, + Label& Lfailure); + + // Compress char[] to byte[]. cnt must be positive int. + void string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure); + + // Inflate byte[] to char[] by inflating 16 bytes at once. + void string_inflate_16(Register src, Register dst, Register cnt, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5); + + // Inflate byte[] to char[]. cnt must be positive int. + void string_inflate(Register src, Register dst, Register cnt, Register tmp); + + void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, + Register tmp1, Register result, int ae); + + void array_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register tmp1, Register result, bool is_byte); + + void string_indexof(Register result, Register haystack, Register haycnt, + Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae); + + void string_indexof_char(Register result, Register haystack, Register haycnt, + Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte); + + void has_negatives(Register src, Register cnt, Register result, Register tmp1, Register tmp2); + + // Intrinsics for non-CompactStrings // Needle of length 1. void string_indexof_1(Register result, Register haystack, Register haycnt, Register needle, jchar needleChar, @@ -694,6 +727,7 @@ Register tmp5_reg); void char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg, Register tmp1_reg, Register tmp2_reg); +#endif // Emitters for BigInteger.multiplyToLen intrinsic. inline void multiply64(Register dest_hi, Register dest_lo, diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ // // Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2012, 2015 SAP SE. All rights reserved. +// Copyright (c) 2012, 2016 SAP SE. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -2024,13 +2024,13 @@ return (UsePopCountInstruction && VM_Version::has_popcntw()); case Op_StrComp: - return SpecialStringCompareTo && !CompactStrings; + return SpecialStringCompareTo; case Op_StrEquals: - return SpecialStringEquals && !CompactStrings; + return SpecialStringEquals; case Op_StrIndexOf: - return SpecialStringIndexOf && !CompactStrings; + return SpecialStringIndexOf; case Op_StrIndexOfChar: - return SpecialStringIndexOf && !CompactStrings; + return SpecialStringIndexOf; } return true; // Per default match rules are supported. @@ -11022,6 +11022,584 @@ ins_pipe(pipe_class_default); %} +instruct string_compareL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, + iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp); + ins_cost(300); + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp$$Register, + $result$$Register, StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_default); +%} + +instruct string_compareU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, + iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp); + ins_cost(300); + format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp$$Register, + $result$$Register, StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_default); +%} + +instruct string_compareLU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, + iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp); + ins_cost(300); + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_compare($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + $tmp$$Register, + $result$$Register, StrIntrinsicNode::LU); + %} + ins_pipe(pipe_class_default); +%} + +instruct string_compareUL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, + iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ctr, KILL cr0, TEMP tmp); + ins_cost(300); + format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result \t// KILL $tmp" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_compare($str2$$Register, $str1$$Register, + $cnt2$$Register, $cnt1$$Register, + $tmp$$Register, + $result$$Register, StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_default); +%} + +instruct string_equalsL(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst result, + iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "String Equals byte[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ array_equals(false, $str1$$Register, $str2$$Register, + $cnt$$Register, $tmp$$Register, + $result$$Register, true /* byte */); + %} + ins_pipe(pipe_class_default); +%} + +instruct string_equalsU(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt, iRegIdst result, + iRegIdst tmp, regCTR ctr, flagsRegCR0 cr0) %{ + predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(TEMP_DEF result, USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "String Equals char[] $str1,$str2,$cnt -> $result \t// KILL $tmp" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ array_equals(false, $str1$$Register, $str2$$Register, + $cnt$$Register, $tmp$$Register, + $result$$Register, false /* byte */); + %} + ins_pipe(pipe_class_default); +%} + +instruct array_equalsB(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result, + iRegIdst tmp1, iRegIdst tmp2, regCTR ctr, flagsRegCR0 cr0, flagsRegCR0 cr1) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (AryEq ary1 ary2)); + effect(TEMP_DEF result, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0, KILL cr1); + ins_cost(300); + format %{ "Array Equals $ary1,$ary2 -> $result \t// KILL $tmp1,$tmp2" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ array_equals(true, $ary1$$Register, $ary2$$Register, + $tmp1$$Register, $tmp2$$Register, + $result$$Register, true /* byte */); + %} + ins_pipe(pipe_class_default); +%} + +instruct array_equalsC(rarg1RegP ary1, rarg2RegP ary2, iRegIdst result, + iRegIdst tmp1, iRegIdst tmp2, regCTR ctr, flagsRegCR0 cr0, flagsRegCR0 cr1) %{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(TEMP_DEF result, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0, KILL cr1); + ins_cost(300); + format %{ "Array Equals $ary1,$ary2 -> $result \t// KILL $tmp1,$tmp2" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ array_equals(true, $ary1$$Register, $ary2$$Register, + $tmp1$$Register, $tmp2$$Register, + $result$$Register, false /* byte */); + %} + ins_pipe(pipe_class_default); +%} + +instruct indexOf_imm1_char_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + immP needleImm, immL offsetImm, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm))); + effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); + ins_cost(150); + + format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]" + "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} + + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + immPOper *needleOper = (immPOper *)$needleImm; + const TypeOopPtr *t = needleOper->type()->isa_oopptr(); + ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * + jchar chr; +#ifdef VM_LITTLE_ENDIAN + chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(0).as_byte()); +#else + chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(1).as_byte()); +#endif + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, chr, + $tmp1$$Register, $tmp2$$Register, false /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm1_char_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + immP needleImm, immL offsetImm, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm))); + effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL); + ins_cost(150); + + format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]" + "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} + + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + immPOper *needleOper = (immPOper *)$needleImm; + const TypeOopPtr *t = needleOper->type()->isa_oopptr(); + ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * + jchar chr = (jchar)needle_values->element_value(0).as_byte(); + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, chr, + $tmp1$$Register, $tmp2$$Register, true /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm1_char_UL(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + immP needleImm, immL offsetImm, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm))); + effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL); + ins_cost(150); + + format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]" + "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} + + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + immPOper *needleOper = (immPOper *)$needleImm; + const TypeOopPtr *t = needleOper->type()->isa_oopptr(); + ciTypeArray* needle_values = t->const_oop()->as_type_array(); // Pointer to live char * + jchar chr = (jchar)needle_values->element_value(0).as_byte(); + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, chr, + $tmp1$$Register, $tmp2$$Register, false /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm1_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + rscratch2RegP needle, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL needle, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(180); + + format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" + " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Node *ndl = in(operand_index($needle)); // The node that defines needle. + ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); + guarantee(needle_values, "sanity"); + jchar chr; +#ifdef VM_LITTLE_ENDIAN + chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(0).as_byte()); +#else + chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(1).as_byte()); +#endif + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, chr, + $tmp1$$Register, $tmp2$$Register, false /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm1_L(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + rscratch2RegP needle, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL needle, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(180); + + format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" + " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Node *ndl = in(operand_index($needle)); // The node that defines needle. + ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); + guarantee(needle_values, "sanity"); + jchar chr = (jchar)needle_values->element_value(0).as_byte(); + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, chr, + $tmp1$$Register, $tmp2$$Register, true /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm1_UL(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + rscratch2RegP needle, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL needle, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(180); + + format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]" + " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Node *ndl = in(operand_index($needle)); // The node that defines needle. + ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); + guarantee(needle_values, "sanity"); + jchar chr = (jchar)needle_values->element_value(0).as_byte(); + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, chr, + $tmp1$$Register, $tmp2$$Register, false /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOfChar_U(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + iRegIsrc ch, iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{ + match(Set result (StrIndexOfChar (Binary haystack haycnt) ch)); + effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr); + predicate(CompactStrings); + ins_cost(180); + + format %{ "String IndexOfChar $haystack[0..$haycnt], $ch" + " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_indexof_char($result$$Register, + $haystack$$Register, $haycnt$$Register, + $ch$$Register, 0 /* this is not used if the character is already in a register */, + $tmp1$$Register, $tmp2$$Register, false /*is_byte*/); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, + iRegPsrc needle, uimmI15 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(250); + + format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" + " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Node *ndl = in(operand_index($needle)); // The node that defines needle. + ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); + + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, + iRegPsrc needle, uimmI15 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(250); + + format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" + " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Node *ndl = in(operand_index($needle)); // The node that defines needle. + ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); + + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_imm_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, + iRegPsrc needle, uimmI15 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6, KILL ctr); + // Required for EA: check if it is still a type_array. + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(250); + + format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]" + " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Node *ndl = in(operand_index($needle)); // The node that defines needle. + ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array(); + + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_U(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt, + iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt))); + effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/ + TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr); + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU); + ins_cost(300); + + format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" + " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UU); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_L(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt, + iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt))); + effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/ + TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr); + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL); + ins_cost(300); + + format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" + " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::LL); + %} + ins_pipe(pipe_class_compare); +%} + +instruct indexOf_UL(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt, + iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt))); + effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/ + TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6, KILL ctr); + predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL); + ins_cost(300); + + format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]" + " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, NULL, $needlecnt$$Register, 0, // needlecnt not constant. + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, StrIntrinsicNode::UL); + %} + ins_pipe(pipe_class_compare); +%} + +// char[] to byte[] compression +instruct string_compress(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst result, iRegLdst tmp1, + iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{ + match(Set result (StrCompressedCopy src (Binary dst len))); + effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, + USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "String Compress $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Label Lskip, Ldone; + __ li($result$$Register, 0); + __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, + $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, Ldone); + __ rldicl_($tmp1$$Register, $len$$Register, 0, 64-3); // Remaining characters. + __ beq(CCR0, Lskip); + __ string_compress($src$$Register, $dst$$Register, $tmp1$$Register, $tmp2$$Register, Ldone); + __ bind(Lskip); + __ mr($result$$Register, $len$$Register); + __ bind(Ldone); + %} + ins_pipe(pipe_class_default); +%} + +// byte[] to char[] inflation +instruct string_inflate(Universe dummy, rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegLdst tmp1, + iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{ + match(Set dummy (StrInflatedCopy src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "String Inflate $src,$dst,$len \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Label Ldone; + __ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, + $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register); + __ rldicl_($tmp1$$Register, $len$$Register, 0, 64-3); // Remaining characters. + __ beq(CCR0, Ldone); + __ string_inflate($src$$Register, $dst$$Register, $tmp1$$Register, $tmp2$$Register); + __ bind(Ldone); + %} + ins_pipe(pipe_class_default); +%} + +// StringCoding.java intrinsics +instruct has_negatives(rarg1RegP ary1, iRegIsrc len, iRegIdst result, iRegLdst tmp1, iRegLdst tmp2, + regCTR ctr, flagsRegCR0 cr0) +%{ + match(Set result (HasNegatives ary1 len)); + effect(TEMP_DEF result, USE_KILL ary1, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "has negatives byte[] $ary1,$len -> $result \t// KILL $tmp1, $tmp2" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ has_negatives($ary1$$Register, $len$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// encode char[] to byte[] in ISO_8859_1 +instruct encode_iso_array(rarg1RegP src, rarg2RegP dst, iRegIsrc len, iRegIdst result, iRegLdst tmp1, + iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, iRegLdst tmp5, regCTR ctr, flagsRegCR0 cr0) %{ + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, + USE_KILL src, USE_KILL dst, KILL ctr, KILL cr0); + ins_cost(300); + format %{ "Encode array $src,$dst,$len -> $result \t// KILL $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + Label Lslow, Lfailure1, Lfailure2, Ldone; + __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $tmp1$$Register, + $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register, Lfailure1); + __ rldicl_($result$$Register, $len$$Register, 0, 64-3); // Remaining characters. + __ beq(CCR0, Ldone); + __ bind(Lslow); + __ string_compress($src$$Register, $dst$$Register, $result$$Register, $tmp2$$Register, Lfailure2); + __ li($result$$Register, 0); + __ b(Ldone); + + __ bind(Lfailure1); + __ mr($result$$Register, $len$$Register); + __ mfctr($tmp1$$Register); + __ rldimi_($result$$Register, $tmp1$$Register, 3, 0); // Remaining characters. + __ beq(CCR0, Ldone); + __ b(Lslow); + + __ bind(Lfailure2); + __ mfctr($result$$Register); // Remaining characters. + + __ bind(Ldone); + __ subf($result$$Register, $result$$Register, $len$$Register); + %} + ins_pipe(pipe_class_default); +%} + + // String_IndexOf for needle of length 1. // // Match needle into immediate operands: no loadConP node needed. Saves one @@ -11060,11 +11638,11 @@ if (java_lang_String::has_coder_field()) { // New compact strings byte array strings #ifdef VM_LITTLE_ENDIAN - chr = (((jchar)needle_values->element_value(1).as_byte()) << 8) | - (jchar)needle_values->element_value(0).as_byte(); + chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(0).as_byte()); #else - chr = (((jchar)needle_values->element_value(0).as_byte()) << 8) | - (jchar)needle_values->element_value(1).as_byte(); + chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(1).as_byte()); #endif } else { // Old char array strings @@ -11115,11 +11693,11 @@ if (java_lang_String::has_coder_field()) { // New compact strings byte array strings #ifdef VM_LITTLE_ENDIAN - chr = (((jchar)needle_values->element_value(1).as_byte()) << 8) | - (jchar)needle_values->element_value(0).as_byte(); + chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(0).as_byte()); #else - chr = (((jchar)needle_values->element_value(0).as_byte()) << 8) | - (jchar)needle_values->element_value(1).as_byte(); + chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) | + ((jchar)(unsigned char)needle_values->element_value(1).as_byte()); #endif } else { // Old char array strings @@ -11321,6 +11899,20 @@ %} %} +instruct minI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ + match(Set dst (MinI src1 src2)); + effect(KILL cr0); + predicate(VM_Version::has_isel()); + ins_cost(DEFAULT_COST*2); + + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ cmpw(CCR0, $src1$$Register, $src2$$Register); + __ isel($dst$$Register, CCR0, Assembler::less, /*invert*/false, $src1$$Register, $src2$$Register); + %} + ins_pipe(pipe_class_default); +%} + instruct maxI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ match(Set dst (MaxI src1 src2)); ins_cost(DEFAULT_COST*6); @@ -11341,6 +11933,20 @@ %} %} +instruct maxI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{ + match(Set dst (MaxI src1 src2)); + effect(KILL cr0); + predicate(VM_Version::has_isel()); + ins_cost(DEFAULT_COST*2); + + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ cmpw(CCR0, $src1$$Register, $src2$$Register); + __ isel($dst$$Register, CCR0, Assembler::greater, /*invert*/false, $src1$$Register, $src2$$Register); + %} + ins_pipe(pipe_class_default); +%} + //---------- Population Count Instructions ------------------------------------ // Popcnt for Power7. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -2609,9 +2609,7 @@ * R5_ARG3 - int length (of buffer) * * scratch: - * R6_ARG4 - crc table address - * R7_ARG5 - tmp1 - * R8_ARG6 - tmp2 + * R2, R6-R12 * * Ouput: * R3_RET - int crc result @@ -2623,22 +2621,25 @@ address start = __ function_entry(); // Remember stub start address (is rtn value). // arguments to kernel_crc32: - Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. - Register data = R4_ARG2; // source byte array - Register dataLen = R5_ARG3; // #bytes to process - Register table = R6_ARG4; // crc table address - - Register t0 = R9; // work reg for kernel* emitters - Register t1 = R10; // work reg for kernel* emitters - Register t2 = R11; // work reg for kernel* emitters - Register t3 = R12; // work reg for kernel* emitters + const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. + const Register data = R4_ARG2; // source byte array + const Register dataLen = R5_ARG3; // #bytes to process + const Register table = R6_ARG4; // crc table address + + const Register t0 = R2; + const Register t1 = R7; + const Register t2 = R8; + const Register t3 = R9; + const Register tc0 = R10; + const Register tc1 = R11; + const Register tc2 = R12; BLOCK_COMMENT("Stub body {"); assert_different_registers(crc, data, dataLen, table); StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_1byte(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table); BLOCK_COMMENT("return"); __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ // If PowerArchitecturePPC64 hasn't been specified explicitly determine from features. if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) { - if (VM_Version::has_tcheck() && VM_Version::has_lqarx()) { + if (VM_Version::has_lqarx()) { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 8); } else if (VM_Version::has_popcntw()) { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7); @@ -68,8 +68,7 @@ bool PowerArchitecturePPC64_ok = false; switch (PowerArchitecturePPC64) { - case 8: if (!VM_Version::has_tcheck() ) break; - if (!VM_Version::has_lqarx() ) break; + case 8: if (!VM_Version::has_lqarx() ) break; case 7: if (!VM_Version::has_popcntw()) break; case 6: if (!VM_Version::has_cmpb() ) break; case 5: if (!VM_Version::has_popcntb()) break; @@ -80,7 +79,7 @@ UINTX_FORMAT " on this machine", PowerArchitecturePPC64); // Power 8: Configure Data Stream Control Register. - if (PowerArchitecturePPC64 >= 8) { + if (has_mfdscr()) { config_dscr(); } @@ -112,7 +111,7 @@ // Create and print feature-string. char buf[(num_features+1) * 16]; // Max 16 chars per feature. jio_snprintf(buf, sizeof(buf), - "ppc64%s%s%s%s%s%s%s%s%s%s%s%s", + "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s", (has_fsqrt() ? " fsqrt" : ""), (has_isel() ? " isel" : ""), (has_lxarxeh() ? " lxarxeh" : ""), @@ -125,7 +124,8 @@ (has_lqarx() ? " lqarx" : ""), (has_vcipher() ? " vcipher" : ""), (has_vpmsumb() ? " vpmsumb" : ""), - (has_tcheck() ? " tcheck" : "") + (has_tcheck() ? " tcheck" : ""), + (has_mfdscr() ? " mfdscr" : "") // Make sure number of %s matches num_features! ); _features_string = os::strdup(buf); @@ -610,6 +610,7 @@ a->vcipher(VR0, VR1, VR2); // code[10] -> vcipher a->vpmsumb(VR0, VR1, VR2); // code[11] -> vpmsumb a->tcheck(0); // code[12] -> tcheck + a->mfdscr(R0); // code[13] -> mfdscr a->blr(); // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. @@ -657,6 +658,7 @@ if (code[feature_cntr++]) features |= vcipher_m; if (code[feature_cntr++]) features |= vpmsumb_m; if (code[feature_cntr++]) features |= tcheck_m; + if (code[feature_cntr++]) features |= mfdscr_m; // Print the detection code. if (PrintAssembly) { @@ -670,8 +672,6 @@ // Power 8: Configure Data Stream Control Register. void VM_Version::config_dscr() { - assert(has_tcheck(), "Only execute on Power 8 or later!"); - // 7 InstWords for each call (function descriptor + blr instruction). const int code_size = (2+2*7)*BytesPerInstWord; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ vcipher, vpmsumb, tcheck, + mfdscr, num_features // last entry to count features }; enum Feature_Flag_Set { @@ -62,6 +63,7 @@ vcipher_m = (1 << vcipher), vpmsumb_m = (1 << vpmsumb), tcheck_m = (1 << tcheck ), + mfdscr_m = (1 << mfdscr ), all_features_m = (unsigned long)-1 }; @@ -94,6 +96,7 @@ static bool has_vcipher() { return (_features & vcipher_m) != 0; } static bool has_vpmsumb() { return (_features & vpmsumb_m) != 0; } static bool has_tcheck() { return (_features & tcheck_m) != 0; } + static bool has_mfdscr() { return (_features & mfdscr_m) != 0; } // Assembler testing static void allow_all(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1349,9 +1349,12 @@ } } else if (dst.first()->is_stack()) { // reg to stack - __ st_ptr(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); + // Some compilers (gcc) expect a clean 32 bit value on function entry + __ signx(src.first()->as_Register(), L5); + __ st_ptr(L5, SP, reg2offset(dst.first()) + STACK_BIAS); } else { - __ mov(src.first()->as_Register(), dst.first()->as_Register()); + // Some compilers (gcc) expect a clean 32 bit value on function entry + __ signx(src.first()->as_Register(), dst.first()->as_Register()); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Mon Mar 21 11:21:08 2016 +0100 @@ -948,28 +948,28 @@ } #endif - uint instr; - instr = (Assembler::ldst_op << 30) - | (dst_enc << 25) - | (primary << 19) - | (src1_enc << 14); + uint instr = (Assembler::ldst_op << 30) + | (dst_enc << 25) + | (primary << 19) + | (src1_enc << 14); uint index = src2_enc; int disp = disp32; if (src1_enc == R_SP_enc || src1_enc == R_FP_enc) { disp += STACK_BIAS; - // Quick fix for JDK-8029668: check that stack offset fits, bailout if not + // Check that stack offset fits, load into O7 if not if (!Assembler::is_simm13(disp)) { - ra->C->record_method_not_compilable("unable to handle large constant offsets"); - return; + MacroAssembler _masm(&cbuf); + __ set(disp, O7); + if (index != R_G0_enc) { + __ add(O7, reg_to_register_object(index), O7); + } + index = R_O7_enc; + disp = 0; } } - // We should have a compiler bailout here rather than a guarantee. - // Better yet would be some mechanism to handle variable-size matches correctly. - guarantee(Assembler::is_simm13(disp), "Do not match large constant offsets" ); - if( disp == 0 ) { // use reg-reg form // bit 13 is already zero @@ -983,7 +983,7 @@ cbuf.insts()->emit_int32(instr); #ifdef ASSERT - { + if (VerifyOops) { MacroAssembler _masm(&cbuf); if (is_verified_oop_base) { __ verify_oop(reg_to_register_object(src1_enc)); @@ -1342,7 +1342,7 @@ // Figure out which register class each belongs in: rc_int, rc_float, rc_stack enum RC { rc_bad, rc_int, rc_float, rc_stack }; static enum RC rc_class( OptoReg::Name reg ) { - if( !OptoReg::is_valid(reg) ) return rc_bad; + if (!OptoReg::is_valid(reg)) return rc_bad; if (OptoReg::is_stack(reg)) return rc_stack; VMReg r = OptoReg::as_VMReg(reg); if (r->is_Register()) return rc_int; @@ -1350,66 +1350,79 @@ return rc_float; } -static int impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size, outputStream* st ) { +#ifndef PRODUCT +ATTRIBUTE_PRINTF(2, 3) +static void print_helper(outputStream* st, const char* format, ...) { + if (st->position() > 0) { + st->cr(); + st->sp(); + } + va_list ap; + va_start(ap, format); + st->vprint(format, ap); + va_end(ap); +} +#endif // !PRODUCT + +static void impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool is_load, int offset, int reg, int opcode, const char *op_str, outputStream* st) { if (cbuf) { emit_form3_mem_reg(*cbuf, ra, mach, opcode, -1, R_SP_enc, offset, 0, Matcher::_regEncode[reg]); } #ifndef PRODUCT - else if (!do_size) { - if (size != 0) st->print("\n\t"); - if (is_load) st->print("%s [R_SP + #%d],R_%s\t! spill",op_str,offset,OptoReg::regname(reg)); - else st->print("%s R_%s,[R_SP + #%d]\t! spill",op_str,OptoReg::regname(reg),offset); + else { + if (is_load) { + print_helper(st, "%s [R_SP + #%d],R_%s\t! spill", op_str, offset, OptoReg::regname(reg)); + } else { + print_helper(st, "%s R_%s,[R_SP + #%d]\t! spill", op_str, OptoReg::regname(reg), offset); + } } #endif - return size+4; } -static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int op1, int op2, const char *op_str, int size, outputStream* st ) { - if( cbuf ) emit3( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src] ); +static void impl_mov_helper(CodeBuffer *cbuf, int src, int dst, int op1, int op2, const char *op_str, outputStream* st) { + if (cbuf) { + emit3(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src]); + } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("%s R_%s,R_%s\t! spill",op_str,OptoReg::regname(src),OptoReg::regname(dst)); + else { + print_helper(st, "%s R_%s,R_%s\t! spill", op_str, OptoReg::regname(src), OptoReg::regname(dst)); } #endif - return size+4; } -uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, - PhaseRegAlloc *ra_, - bool do_size, - outputStream* st ) const { +static void mach_spill_copy_implementation_helper(const MachNode* mach, + CodeBuffer *cbuf, + PhaseRegAlloc *ra_, + outputStream* st) { // Get registers to move - OptoReg::Name src_second = ra_->get_reg_second(in(1)); - OptoReg::Name src_first = ra_->get_reg_first(in(1)); - OptoReg::Name dst_second = ra_->get_reg_second(this ); - OptoReg::Name dst_first = ra_->get_reg_first(this ); + OptoReg::Name src_second = ra_->get_reg_second(mach->in(1)); + OptoReg::Name src_first = ra_->get_reg_first(mach->in(1)); + OptoReg::Name dst_second = ra_->get_reg_second(mach); + OptoReg::Name dst_first = ra_->get_reg_first(mach); enum RC src_second_rc = rc_class(src_second); - enum RC src_first_rc = rc_class(src_first); + enum RC src_first_rc = rc_class(src_first); enum RC dst_second_rc = rc_class(dst_second); - enum RC dst_first_rc = rc_class(dst_first); - - assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); - - // Generate spill code! - int size = 0; - - if( src_first == dst_first && src_second == dst_second ) - return size; // Self copy, no move + enum RC dst_first_rc = rc_class(dst_first); + + assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register"); + + if (src_first == dst_first && src_second == dst_second) { + return; // Self copy, no move + } // -------------------------------------- // Check for mem-mem move. Load into unused float registers and fall into // the float-store case. - if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second ) { + if ((src_first&1) == 0 && src_first+1 == src_second) { src_second = OptoReg::Name(R_F31_num); src_second_rc = rc_float; - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::lddf_op3,"LDDF",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::lddf_op3, "LDDF", st); } else { - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::ldf_op3 ,"LDF ",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::ldf_op3, "LDF ", st); } src_first = OptoReg::Name(R_F30_num); src_first_rc = rc_float; @@ -1417,7 +1430,7 @@ if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { int offset = ra_->reg2offset(src_second); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F31_num,Assembler::ldf_op3,"LDF ",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F31_num, Assembler::ldf_op3, "LDF ", st); src_second = OptoReg::Name(R_F31_num); src_second_rc = rc_float; } @@ -1427,36 +1440,38 @@ if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) { int offset = frame::register_save_words*wordSize; if (cbuf) { - emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 ); - impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); - impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); - emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 ); + emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16); + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); + emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16); } #ifndef PRODUCT - else if (!do_size) { - if (size != 0) st->print("\n\t"); - st->print( "SUB R_SP,16,R_SP\n"); - impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); - impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); - st->print("\tADD R_SP,16,R_SP\n"); + else { + print_helper(st, "SUB R_SP,16,R_SP"); + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); + print_helper(st, "ADD R_SP,16,R_SP"); } #endif - size += 16; } // Check for float->int copy on T4 if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) { // Further check for aligned-adjacent pair, so we can use a double move - if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mdtox_opf, "MOVDTOX", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mstouw_opf, "MOVSTOUW", st); } // Check for int->float copy on T4 if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) { // Further check for aligned-adjacent pair, so we can use a double move - if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mxtod_opf, "MOVXTOD", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mwtos_opf, "MOVWTOS", st); } // -------------------------------------- @@ -1466,10 +1481,10 @@ // there. Misaligned sources only come from native-long-returns (handled // special below). #ifndef _LP64 - if( src_first_rc == rc_int && // source is already big-endian + if (src_first_rc == rc_int && // source is already big-endian src_second_rc != rc_bad && // 64-bit move - ((dst_first&1)!=0 || dst_second != dst_first+1) ) { // misaligned dst - assert( (src_first&1)==0 && src_second == src_first+1, "source must be aligned" ); + ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst + assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned"); // Do the big-endian flop. OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ; enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc; @@ -1478,30 +1493,28 @@ // -------------------------------------- // Check for integer reg-reg copy - if( src_first_rc == rc_int && dst_first_rc == rc_int ) { + if (src_first_rc == rc_int && dst_first_rc == rc_int) { #ifndef _LP64 - if( src_first == R_O0_num && src_second == R_O1_num ) { // Check for the evil O0/O1 native long-return case + if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value // as stored in memory. On a big-endian machine like SPARC, this means that the _second // operand contains the least significant word of the 64-bit value and vice versa. OptoReg::Name tmp = OptoReg::Name(R_O7_num); - assert( (dst_first&1)==0 && dst_second == dst_first+1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); + assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); // Shift O0 left in-place, zero-extend O1, then OR them into the dst - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020 ); - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000 ); - emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second] ); + if ( cbuf ) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000); + emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); - st->print("SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); - st->print("OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); + } else { + print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); + print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); + print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); #endif } - return size+12; - } - else if( dst_first == R_I0_num && dst_second == R_I1_num ) { + return; + } else if (dst_first == R_I0_num && dst_second == R_I1_num) { // returning a long value in I0/I1 // a SpillCopy must be able to target a return instruction's reg_class // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value @@ -1511,27 +1524,25 @@ if (src_first == dst_first) { tdest = OptoReg::Name(R_O7_num); - size += 4; } - if( cbuf ) { - assert( (src_first&1) == 0 && (src_first+1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); + if (cbuf) { + assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); // Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1 // ShrL_reg_imm6 - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000 ); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000); // ShrR_reg_imm6 src, 0, dst - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000 ); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000); if (tdest != dst_first) { - emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest] ); + emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]); } } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); // %%%%% !!!!! - st->print("SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); - st->print("SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); + else { + print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); + print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); if (tdest != dst_first) { - st->print("MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); + print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); } } #endif // PRODUCT @@ -1539,65 +1550,77 @@ } #endif // !_LP64 // Else normal reg-reg copy - assert( src_second != dst_first, "smashed second before evacuating it" ); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::or_op3,0,"MOV ",size, st); - assert( (src_first&1) == 0 && (dst_first&1) == 0, "never move second-halves of int registers" ); + assert(src_second != dst_first, "smashed second before evacuating it"); + impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st); + assert((src_first & 1) == 0 && (dst_first & 1) == 0, "never move second-halves of int registers"); // This moves an aligned adjacent pair. // See if we are done. - if( src_first+1 == src_second && dst_first+1 == dst_second ) - return size; + if (src_first + 1 == src_second && dst_first + 1 == dst_second) { + return; + } } // Check for integer store - if( src_first_rc == rc_int && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_int && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(dst_first); // Further check for aligned-adjacent pair, so we can use a double store - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stx_op3,"STX ",size, st); - size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stw_op3,"STW ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stx_op3, "STX ", st); + return; + } + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stw_op3, "STW ", st); } // Check for integer load - if( dst_first_rc == rc_int && src_first_rc == rc_stack ) { + if (dst_first_rc == rc_int && src_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldx_op3 ,"LDX ",size, st); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldx_op3, "LDX ", st); + return; + } + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); } // Check for float reg-reg copy - if( src_first_rc == rc_float && dst_first_rc == rc_float ) { + if (src_first_rc == rc_float && dst_first_rc == rc_float) { // Further check for aligned-adjacent pair, so we can use a double move - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovd_opf,"FMOVD",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovs_opf,"FMOVS",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovd_opf, "FMOVD", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovs_opf, "FMOVS", st); } // Check for float store - if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_float && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(dst_first); // Further check for aligned-adjacent pair, so we can use a double store - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stdf_op3,"STDF",size, st); - size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stdf_op3, "STDF", st); + return; + } + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); } // Check for float load - if( dst_first_rc == rc_float && src_first_rc == rc_stack ) { + if (dst_first_rc == rc_float && src_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lddf_op3,"LDDF",size, st); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldf_op3 ,"LDF ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lddf_op3, "LDDF", st); + return; + } + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldf_op3, "LDF ", st); } // -------------------------------------------------------------------- // Check for hi bits still needing moving. Only happens for misaligned // arguments to native calls. - if( src_second == dst_second ) - return size; // Self copy; no move - assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); + if (src_second == dst_second) { + return; // Self copy; no move + } + assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad"); #ifndef _LP64 // In the LP64 build, all registers can be moved as aligned/adjacent @@ -1609,52 +1632,57 @@ // 32-bits of a 64-bit register, but are needed in low bits of another // register (else it's a hi-bits-to-hi-bits copy which should have // happened already as part of a 64-bit move) - if( src_second_rc == rc_int && dst_second_rc == rc_int ) { - assert( (src_second&1)==1, "its the evil O0/O1 native return case" ); - assert( (dst_second&1)==0, "should have moved with 1 64-bit move" ); + if (src_second_rc == rc_int && dst_second_rc == rc_int) { + assert((src_second & 1) == 1, "its the evil O0/O1 native return case"); + assert((dst_second & 1) == 0, "should have moved with 1 64-bit move"); // Shift src_second down to dst_second's low bits. - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 ); + if (cbuf) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(dst_second)); + } else { + print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second)); #endif } - return size+4; + return; } // Check for high word integer store. Must down-shift the hi bits // into a temp register, then fall into the case of storing int bits. - if( src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second&1)==1 ) { + if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) { // Shift src_second down to dst_second's low bits. - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 ); + if (cbuf) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(R_O7_num)); + } else { + print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num)); #endif } - size+=4; src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num! } // Check for high word integer load - if( dst_second_rc == rc_int && src_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,true ,ra_->reg2offset(src_second),dst_second,Assembler::lduw_op3,"LDUW",size, st); + if (dst_second_rc == rc_int && src_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st); // Check for high word integer store - if( src_second_rc == rc_int && dst_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stw_op3 ,"STW ",size, st); + if (src_second_rc == rc_int && dst_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st); // Check for high word float store - if( src_second_rc == rc_float && dst_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stf_op3 ,"STF ",size, st); + if (src_second_rc == rc_float && dst_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st); #endif // !_LP64 Unimplemented(); +} + +uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, + PhaseRegAlloc *ra_, + bool do_size, + outputStream* st) const { + assert(!do_size, "not supported"); + mach_spill_copy_implementation_helper(this, cbuf, ra_, st); return 0; } @@ -1669,19 +1697,19 @@ } uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { - return implementation( NULL, ra_, true, NULL ); + return MachNode::size(ra_); } //============================================================================= #ifndef PRODUCT -void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { +void MachNopNode::format(PhaseRegAlloc *, outputStream *st) const { st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); } #endif -void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { +void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const { MacroAssembler _masm(&cbuf); - for(int i = 0; i < _count; i += 1) { + for (int i = 0; i < _count; i += 1) { __ nop(); } } @@ -5197,7 +5225,6 @@ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $src,$dst\t! stkI to regF" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -5208,7 +5235,6 @@ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $src,$dst\t! stkL to regD" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -5219,7 +5245,6 @@ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$dst\t! regF to stkI" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -5230,7 +5255,6 @@ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$dst\t! regD to stkL" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -5240,7 +5264,6 @@ instruct regI_to_stkLHi(stackSlotL dst, iRegI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST*2); - size(8); format %{ "STW $src,$dst.hi\t! long\n\t" "STW R_G0,$dst.lo" %} opcode(Assembler::stw_op3); @@ -5252,7 +5275,6 @@ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! regL to stkD" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5266,7 +5288,6 @@ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $src,$dst\t!stk" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5278,7 +5299,6 @@ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$dst\t!stk" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5290,7 +5310,6 @@ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t! long" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5302,7 +5321,6 @@ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! long" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5314,7 +5332,6 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t!ptr" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5325,7 +5342,6 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t!ptr" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5771,7 +5787,6 @@ match(Set dst (LoadL_unaligned mem)); effect(KILL tmp); ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); - size(16); format %{ "LDUW $mem+4,R_O7\t! misaligned long\n" "\tLDUW $mem ,$dst\n" "\tSLLX #32, $dst, $dst\n" @@ -5786,7 +5801,6 @@ match(Set dst (LoadRange mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $mem,$dst\t! range" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -5797,7 +5811,6 @@ instruct loadI_freg(regF dst, memory mem) %{ match(Set dst (LoadI mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $mem,$dst\t! for fitos/fitod" %} opcode(Assembler::ldf_op3); @@ -5876,7 +5889,6 @@ match(Set dst (LoadD mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $mem,$dst" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -5887,7 +5899,6 @@ instruct loadD_unaligned(regD_low dst, memory mem ) %{ match(Set dst (LoadD_unaligned mem)); ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); - size(8); format %{ "LDF $mem ,$dst.hi\t! misaligned double\n" "\tLDF $mem+4,$dst.lo\t!" %} opcode(Assembler::ldf_op3); @@ -5900,7 +5911,6 @@ match(Set dst (LoadF mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $mem,$dst" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -6119,7 +6129,6 @@ predicate(AllocatePrefetchInstr == 0); match( PrefetchAllocation mem ); ins_cost(MEMORY_REF_COST); - size(4); format %{ "PREFETCH $mem,2\t! Prefetch allocation" %} opcode(Assembler::prefetch_op3); @@ -6175,7 +6184,6 @@ match(Set mem (StoreB mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6186,7 +6194,6 @@ match(Set mem (StoreB mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6197,7 +6204,6 @@ match(Set mem (StoreCM mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! CMS card-mark byte 0" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6209,7 +6215,6 @@ match(Set mem (StoreC mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6220,7 +6225,6 @@ match(Set mem (StoreC mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6232,7 +6236,6 @@ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6243,7 +6246,6 @@ instruct storeL(memory mem, iRegL src) %{ match(Set mem (StoreL mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem\t! long" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6254,7 +6256,6 @@ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6265,7 +6266,6 @@ match(Set mem (StoreL mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6277,7 +6277,6 @@ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$mem\t! after fstoi/fdtoi" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6288,7 +6287,6 @@ instruct storeP(memory dst, sp_ptr_RegP src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); - size(4); #ifndef _LP64 format %{ "STW $src,$dst\t! ptr" %} @@ -6304,7 +6302,6 @@ instruct storeP0(memory dst, immP0 src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); - size(4); #ifndef _LP64 format %{ "STW $src,$dst\t! ptr" %} @@ -6379,7 +6376,6 @@ match(Set mem (StoreD mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$mem" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6390,7 +6386,6 @@ match(Set mem (StoreD mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6402,7 +6397,6 @@ match(Set mem (StoreF mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$mem" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6413,7 +6407,6 @@ match(Set mem (StoreF mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem\t! storeF0" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -7068,7 +7061,6 @@ ins_cost(MEMORY_REF_COST); #ifndef _LP64 - size(4); format %{ "LDUW $mem,$dst\t! ptr" %} opcode(Assembler::lduw_op3, 0, REGP_OP); #else @@ -8138,7 +8130,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $src,$dst\t! MoveF2I" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -8150,7 +8141,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $src,$dst\t! MoveI2F" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -8162,7 +8152,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t! MoveD2L" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -8174,7 +8163,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $src,$dst\t! MoveL2D" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -8186,7 +8174,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$dst\t! MoveF2I" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -8198,7 +8185,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$dst\t! MoveI2F" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -8210,7 +8196,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$dst\t! MoveD2L" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -8222,7 +8207,6 @@ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! MoveL2D" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -8427,7 +8411,6 @@ instruct convI2D_mem(regD_low dst, memory mem) %{ match(Set dst (ConvI2D (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); format %{ "LDF $mem,$dst\n\t" "FITOD $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitod_opf); @@ -8468,7 +8451,6 @@ instruct convI2F_mem( regF dst, memory mem ) %{ match(Set dst (ConvI2F (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); format %{ "LDF $mem,$dst\n\t" "FITOS $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitos_opf); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -463,3 +463,37 @@ } return result; } + + +int VM_Version::parse_features(const char* implementation) { + int features = unknown_m; + // Convert to UPPER case before compare. + char* impl = os::strdup_check_oom(implementation); + + for (int i = 0; impl[i] != 0; i++) + impl[i] = (char)toupper((uint)impl[i]); + + if (strstr(impl, "SPARC64") != NULL) { + features |= sparc64_family_m; + } else if (strstr(impl, "SPARC-M") != NULL) { + // M-series SPARC is based on T-series. + features |= (M_family_m | T_family_m); + } else if (strstr(impl, "SPARC-T") != NULL) { + features |= T_family_m; + if (strstr(impl, "SPARC-T1") != NULL) { + features |= T1_model_m; + } + } else { + if (strstr(impl, "SPARC") == NULL) { +#ifndef PRODUCT + // kstat on Solaris 8 virtual machines (branded zones) + // returns "(unsupported)" implementation. Solaris 8 is not + // supported anymore, but include this check to be on the + // safe side. + warning("Can't parse CPU implementation = '%s', assume generic SPARC", impl); +#endif + } + } + os::free((void*)impl); + return features; +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -121,7 +121,7 @@ static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } static int maximum_niagara1_processor_count() { return 32; } - + static int parse_features(const char* implementation); public: // Initialization static void initialize(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -161,13 +161,7 @@ create_klass_exception), rarg, rarg2); } else { - // kind of lame ExternalAddress can't take NULL because - // external_word_Relocation will assert. - if (message != NULL) { - __ lea(rarg2, ExternalAddress((address)message)); - } else { - __ movptr(rarg2, NULL_WORD); - } + __ lea(rarg2, ExternalAddress((address)message)); __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), rarg, rarg2); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/x86/vm/x86_32.ad --- a/hotspot/src/cpu/x86/vm/x86_32.ad Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Mon Mar 21 11:21:08 2016 +0100 @@ -7236,6 +7236,7 @@ instruct compareAndSwapL( rRegI res, eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{ predicate(VM_Version::supports_cx8()); match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" "MOV $res,0\n\t" @@ -7249,6 +7250,7 @@ instruct compareAndSwapP( rRegI res, pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{ match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" "MOV $res,0\n\t" @@ -7261,6 +7263,7 @@ instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{ match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" "MOV $res,0\n\t" @@ -7271,6 +7274,31 @@ ins_pipe( pipe_cmpxchg ); %} +instruct compareAndExchangeL( eSIRegP mem_ptr, eADXRegL oldval, eBCXRegL newval, eFlagsReg cr ) %{ + predicate(VM_Version::supports_cx8()); + match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval))); + effect(KILL cr); + format %{ "CMPXCHG8 [$mem_ptr],$newval\t# If EDX:EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %} + ins_encode( enc_cmpxchg8(mem_ptr) ); + ins_pipe( pipe_cmpxchg ); +%} + +instruct compareAndExchangeP( pRegP mem_ptr, eAXRegP oldval, eCXRegP newval, eFlagsReg cr) %{ + match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval))); + effect(KILL cr); + format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %} + ins_encode( enc_cmpxchg(mem_ptr) ); + ins_pipe( pipe_cmpxchg ); +%} + +instruct compareAndExchangeI( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{ + match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval))); + effect(KILL cr); + format %{ "CMPXCHG [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %} + ins_encode( enc_cmpxchg(mem_ptr) ); + ins_pipe( pipe_cmpxchg ); +%} + instruct xaddI_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{ predicate(n->as_LoadStore()->result_not_used()); match(Set dummy (GetAndAddI mem add)); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Mon Mar 21 11:21:08 2016 +0100 @@ -7281,6 +7281,7 @@ %{ predicate(VM_Version::supports_cx8()); match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "cmpxchgq $mem_ptr,$newval\t# " @@ -7305,6 +7306,7 @@ %{ predicate(VM_Version::supports_cx8()); match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "cmpxchgq $mem_ptr,$newval\t# " @@ -7328,6 +7330,7 @@ rFlagsReg cr) %{ match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "cmpxchgl $mem_ptr,$newval\t# " @@ -7351,6 +7354,7 @@ rax_RegN oldval, rRegN newval, rFlagsReg cr) %{ match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval))); + match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval))); effect(KILL cr, KILL oldval); format %{ "cmpxchgl $mem_ptr,$newval\t# " @@ -7368,6 +7372,83 @@ ins_pipe( pipe_cmpxchg ); %} +instruct compareAndExchangeI( + memory mem_ptr, + rax_RegI oldval, rRegI newval, + rFlagsReg cr) +%{ + match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval))); + effect(KILL cr); + + format %{ "cmpxchgl $mem_ptr,$newval\t# " + "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %} + opcode(0x0F, 0xB1); + ins_encode(lock_prefix, + REX_reg_mem(newval, mem_ptr), + OpcP, OpcS, + reg_mem(newval, mem_ptr) // lock cmpxchg + ); + ins_pipe( pipe_cmpxchg ); +%} + +instruct compareAndExchangeL( + memory mem_ptr, + rax_RegL oldval, rRegL newval, + rFlagsReg cr) +%{ + predicate(VM_Version::supports_cx8()); + match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval))); + effect(KILL cr); + + format %{ "cmpxchgq $mem_ptr,$newval\t# " + "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %} + opcode(0x0F, 0xB1); + ins_encode(lock_prefix, + REX_reg_mem_wide(newval, mem_ptr), + OpcP, OpcS, + reg_mem(newval, mem_ptr) // lock cmpxchg + ); + ins_pipe( pipe_cmpxchg ); +%} + +instruct compareAndExchangeN( + memory mem_ptr, + rax_RegN oldval, rRegN newval, + rFlagsReg cr) %{ + match(Set oldval (CompareAndExchangeN mem_ptr (Binary oldval newval))); + effect(KILL cr); + + format %{ "cmpxchgl $mem_ptr,$newval\t# " + "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %} + opcode(0x0F, 0xB1); + ins_encode(lock_prefix, + REX_reg_mem(newval, mem_ptr), + OpcP, OpcS, + reg_mem(newval, mem_ptr) // lock cmpxchg + ); + ins_pipe( pipe_cmpxchg ); +%} + +instruct compareAndExchangeP( + memory mem_ptr, + rax_RegP oldval, rRegP newval, + rFlagsReg cr) +%{ + predicate(VM_Version::supports_cx8()); + match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval))); + effect(KILL cr); + + format %{ "cmpxchgq $mem_ptr,$newval\t# " + "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %} + opcode(0x0F, 0xB1); + ins_encode(lock_prefix, + REX_reg_mem_wide(newval, mem_ptr), + OpcP, OpcS, + reg_mem(newval, mem_ptr) // lock cmpxchg + ); + ins_pipe( pipe_cmpxchg ); +%} + instruct xaddI_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{ predicate(n->as_LoadStore()->result_not_used()); match(Set dummy (GetAndAddI mem add)); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Find16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Find16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Save24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Save24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Zoom16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Zoom16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Down16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Down16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Up16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Up16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Find16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Find16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Save24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Save24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Zoom16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Zoom16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Down16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Down16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Up16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Up16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight16.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight16.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight24.gif Binary file hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight24.gif has changed diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java Mon Mar 21 11:21:08 2016 +0100 @@ -22,6 +22,7 @@ */ package jdk.vm.ci.amd64; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD; import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static jdk.vm.ci.code.Register.SPECIAL; @@ -220,7 +221,7 @@ private final AMD64Kind largestKind; public AMD64(EnumSet features, EnumSet flags) { - super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8); + super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8); this.features = features; this.flags = flags; assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Mon Mar 21 11:21:08 2016 +0100 @@ -1141,7 +1141,7 @@ @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset; @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset; - @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset; + @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"aarch64, amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset; @HotSpotVMField(name = "JavaFrameAnchor::_flags", type = "int", get = HotSpotVMField.Type.OFFSET, archs = {"sparc"}) @Stable private int javaFrameAnchorFlagsOffset; public int threadLastJavaSpOffset() { @@ -1152,11 +1152,8 @@ return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset; } - /** - * This value is only valid on AMD64. - */ public int threadLastJavaFpOffset() { - // TODO add an assert for AMD64 + assert getHostArchitectureName().equals("aarch64") || getHostArchitectureName().equals("amd64"); return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/aix/vm/os_aix.cpp --- a/hotspot/src/os/aix/vm/os_aix.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" #include "jvm_aix.h" +#include "logging/log.hpp" #include "libo4.hpp" #include "libperfstat_aix.hpp" #include "libodm_aix.hpp" @@ -791,13 +792,8 @@ const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - trcVerbose("newborn Thread : pthread-id %u, ktid " UINT64_FORMAT - ", stack %p ... %p, stacksize 0x%IX (%IB)", - pthread_id, kernel_thread_id, - thread->stack_end(), - thread->stack_base(), - thread->stack_size(), - thread->stack_size()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); // Normally, pthread stacks on AIX live in the data segment (are allocated with malloc() // by the pthread library). In rare cases, this may not be the case, e.g. when third-party @@ -805,7 +801,7 @@ // guard pages on those stacks, because the stacks may reside in memory which is not // protectable (shmated). if (thread->stack_base() > ::sbrk(0)) { - trcVerbose("Thread " UINT64_FORMAT ": stack not in data segment.", (uint64_t) pthread_id); + log_warning(os, thread)("Thread stack not in data segment."); } // Try to randomize the cache line index of hot stack frames. @@ -839,8 +835,8 @@ // Call one more level start routine. thread->run(); - trcVerbose("Thread finished : pthread-id %u, ktid " UINT64_FORMAT ".", - pthread_id, kernel_thread_id); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); return 0; } @@ -908,20 +904,19 @@ pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); - pthread_attr_destroy(&attr); - + + char buf[64]; if (ret == 0) { - trcVerbose("Created New Thread : pthread-id %u", tid); + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); } else { - if (os::Aix::on_pase()) { - // QIBM_MULTI_THREADED=Y is needed when the launcher is started on iSeries - // using QSH. Otherwise pthread_create fails with errno=11. - trcVerbose("(Please make sure you set the environment variable " - "QIBM_MULTI_THREADED=Y before running this program.)"); - } - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + + pthread_attr_destroy(&attr); + + if (ret != 0) { // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -958,13 +953,6 @@ const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - trcVerbose("attaching Thread : pthread-id %u, ktid " UINT64_FORMAT ", stack %p ... %p, stacksize 0x%IX (%IB)", - pthread_id, kernel_thread_id, - thread->stack_end(), - thread->stack_base(), - thread->stack_size(), - thread->stack_size()); - // OSThread::thread_id is the pthread id. osthread->set_thread_id(pthread_id); @@ -990,6 +978,9 @@ // and save the caller's signal mask os::Aix::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); + return true; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/bsd/vm/os_bsd.cpp --- a/hotspot/src/os/bsd/vm/os_bsd.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_bsd.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_bsd.inline.hpp" @@ -681,6 +682,9 @@ osthread->set_thread_id(os::Bsd::gettid()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + #ifdef __APPLE__ uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id()); guarantee(unique_thread_id != 0, "unique thread id was not found"); @@ -716,6 +720,9 @@ // call one more level start routine thread->run(); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return 0; } @@ -776,12 +783,18 @@ pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); if (ret != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -858,6 +871,9 @@ // and save the caller's signal mask os::Bsd::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return true; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -662,6 +662,9 @@ osthread->set_thread_id(os::current_thread_id()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { @@ -691,6 +694,9 @@ // call one more level start routine thread->run(); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return 0; } @@ -756,12 +762,18 @@ pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); if (ret != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -858,6 +870,9 @@ // and save the caller's signal mask os::Linux::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return true; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/posix/vm/os_posix.cpp --- a/hotspot/src/os/posix/vm/os_posix.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/posix/vm/os_posix.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1071,6 +1071,19 @@ #endif } +char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr) { + size_t stack_size = 0; + size_t guard_size = 0; + int detachstate = 0; + pthread_attr_getstacksize(attr, &stack_size); + pthread_attr_getguardsize(attr, &guard_size); + pthread_attr_getdetachstate(attr, &detachstate); + jio_snprintf(buf, buflen, "stacksize: " SIZE_FORMAT "k, guardsize: " SIZE_FORMAT "k, %s", + stack_size / 1024, guard_size / 1024, + (detachstate == PTHREAD_CREATE_DETACHED ? "detached" : "joinable")); + return buf; +} + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/posix/vm/os_posix.hpp --- a/hotspot/src/os/posix/vm/os_posix.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/posix/vm/os_posix.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -76,6 +76,11 @@ static address ucontext_get_pc(const ucontext_t* ctx); // Set PC into context. Needed for continuation after signal. static void ucontext_set_pc(ucontext_t* ctx, address pc); + + // Helper function; describes pthread attributes as short string. String is written + // to buf with len buflen; buf is returned. + static char* describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr); + }; /* diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/solaris/vm/os_solaris.cpp --- a/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_solaris.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_solaris.inline.hpp" @@ -68,6 +69,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" // put OS-includes here @@ -736,6 +738,9 @@ osthr->set_lwp_id(_lwp_self()); // Store lwp in case we are bound thread->_schedctl = (void *) schedctl_init(); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { @@ -781,6 +786,8 @@ Atomic::dec(&os::Solaris::_os_thread_count); } + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id()); + if (UseDetachedThreads) { thr_exit(NULL); ShouldNotReachHere(); @@ -853,6 +860,9 @@ // and save the caller's signal mask os::Solaris::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + return true; } @@ -879,6 +889,24 @@ return true; } +// Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr() +static char* describe_thr_create_attributes(char* buf, size_t buflen, + size_t stacksize, long flags) { + stringStream ss(buf, buflen); + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); + ss.print("flags: "); + #define PRINT_FLAG(f) if (flags & f) ss.print( #f " "); + #define ALL(X) \ + X(THR_SUSPENDED) \ + X(THR_DETACHED) \ + X(THR_BOUND) \ + X(THR_NEW_LWP) \ + X(THR_DAEMON) + ALL(PRINT_FLAG) + #undef ALL + #undef PRINT_FLAG + return buf; +} bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { @@ -974,10 +1002,17 @@ osthread->set_thread_id(-1); status = thr_create(NULL, stack_size, java_start, thread, flags, &tid); + + char buf[64]; + if (status == 0) { + log_info(os, thread)("Thread started (tid: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + } else { + log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.", + strerror(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + } + if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::create_thread"); - } thread->set_osthread(NULL); // Need to clean up stuff we've allocated so far delete osthread; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -35,6 +35,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_windows.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_windows.inline.hpp" @@ -71,6 +72,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef _DEBUG @@ -436,6 +438,8 @@ res = 20115; // java thread } + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", os::current_thread_id()); + // Install a win32 structured exception handler around every thread created // by VM, so VM can generate error dump when an exception occurred in non- // Java thread (e.g. VM thread). @@ -446,6 +450,8 @@ // Nothing to do. } + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id()); + // One less thread is executing // When the VMThread gets here, the main thread may have already exited // which frees the CodeHeap containing the Atomic::add code @@ -509,6 +515,10 @@ osthread->set_state(RUNNABLE); thread->set_osthread(osthread); + + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + return true; } @@ -530,6 +540,27 @@ return true; } +// Helper function to trace _beginthreadex attributes, +// similar to os::Posix::describe_pthread_attr() +static char* describe_beginthreadex_attributes(char* buf, size_t buflen, + size_t stacksize, unsigned initflag) { + stringStream ss(buf, buflen); + if (stacksize == 0) { + ss.print("stacksize: default, "); + } else { + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); + } + ss.print("flags: "); + #define PRINT_FLAG(f) if (initflag & f) ss.print( #f " "); + #define ALL(X) \ + X(CREATE_SUSPENDED) \ + X(STACK_SIZE_PARAM_IS_A_RESERVATION) + ALL(PRINT_FLAG) + #undef ALL + #undef PRINT_FLAG + return buf; +} + // Allocate and initialize a new OSThread bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { @@ -596,14 +627,24 @@ // document because JVM uses C runtime library. The good news is that the // flag appears to work with _beginthredex() as well. + const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION; HANDLE thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, (unsigned (__stdcall *)(void*)) java_start, thread, - CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, + initflag, &thread_id); + char buf[64]; + if (thread_handle != NULL) { + log_info(os, thread)("Thread started (tid: %u, attributes: %s)", + thread_id, describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + } else { + log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.", + strerror(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + } + if (thread_handle == NULL) { // Need to clean up stuff we've allocated so far CloseHandle(osthread->interrupt_event()); @@ -1668,8 +1709,7 @@ if (is_workstation) { st->print("10"); } else { - // The server version name of Windows 10 is not known at this time - st->print("%d.%d", major_version, minor_version); + st->print("Server 2016"); } break; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -264,6 +264,7 @@ // We need to keep these here as long as we have to build on Solaris // versions before 10. + #ifndef SI_ARCHITECTURE_32 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ #endif @@ -272,36 +273,87 @@ #define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */ #endif -static void do_sysinfo(int si, const char* string, int* features, int mask) { - char tmp; - size_t bufsize = sysinfo(si, &tmp, 1); +#ifndef SI_CPUBRAND +#define SI_CPUBRAND 523 /* return cpu brand string */ +#endif - // All SI defines used below must be supported. - guarantee(bufsize != -1, "must be supported"); +class Sysinfo { + char* _string; +public: + Sysinfo(int si) : _string(NULL) { + char tmp; + size_t bufsize = sysinfo(si, &tmp, 1); - char* buf = (char*) os::malloc(bufsize, mtInternal); - - if (buf == NULL) - return; + if (bufsize != -1) { + char* buf = (char*) os::malloc(bufsize, mtInternal); + if (buf != NULL) { + if (sysinfo(si, buf, bufsize) == bufsize) { + _string = buf; + } else { + os::free(buf); + } + } + } + } - if (sysinfo(si, buf, bufsize) == bufsize) { - // Compare the string. - if (strcmp(buf, string) == 0) { - *features |= mask; + ~Sysinfo() { + if (_string != NULL) { + os::free(_string); } } - os::free(buf); -} + const char* value() const { + return _string; + } + + bool valid() const { + return _string != NULL; + } + + bool match(const char* s) const { + return valid() ? strcmp(_string, s) == 0 : false; + } + + bool match_substring(const char* s) const { + return valid() ? strstr(_string, s) != NULL : false; + } +}; + +class Sysconf { + int _value; +public: + Sysconf(int sc) : _value(-1) { + _value = sysconf(sc); + } + bool valid() const { + return _value != -1; + } + int value() const { + return _value; + } +}; + + +#ifndef _SC_DCACHE_LINESZ +#define _SC_DCACHE_LINESZ 508 /* Data cache line size */ +#endif + +#ifndef _SC_L2CACHE_LINESZ +#define _SC_L2CACHE_LINESZ 527 /* Size of L2 cache line */ +#endif int VM_Version::platform_features(int features) { assert(os::Solaris::supports_getisax(), "getisax() must be available"); // Check 32-bit architecture. - do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); + if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) { + features |= v8_instructions_m; + } // Check 64-bit architecture. - do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); + if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) { + features |= generic_v9_m; + } // Extract valid instruction set extensions. uint_t avs[2]; @@ -388,67 +440,63 @@ if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; // Determine the machine type. - do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); + if (Sysinfo(SI_MACHINE).match("sun4v")) { + features |= sun4v_m; + } - { - // Using kstat to determine the machine type. + bool use_solaris_12_api = false; + Sysinfo impl(SI_CPUBRAND); + if (impl.valid()) { + // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes + // is available to us as well + use_solaris_12_api = true; + features |= parse_features(impl.value()); + } else { + // Otherwise use kstat to determine the machine type. kstat_ctl_t* kc = kstat_open(); kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL); - const char* implementation = "UNKNOWN"; + const char* implementation; + bool has_implementation = false; if (ksp != NULL) { if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) { kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; for (int i = 0; i < ksp->ks_ndata; i++) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { implementation = KSTAT_NAMED_STR_PTR(&knm[i]); + has_implementation = true; #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("cpu_info.implementation: %s", implementation); } #endif - // Convert to UPPER case before compare. - char* impl = os::strdup_check_oom(implementation); - - for (int i = 0; impl[i] != 0; i++) - impl[i] = (char)toupper((uint)impl[i]); - - if (strstr(impl, "SPARC64") != NULL) { - features |= sparc64_family_m; - } else if (strstr(impl, "SPARC-M") != NULL) { - // M-series SPARC is based on T-series. - features |= (M_family_m | T_family_m); - } else if (strstr(impl, "SPARC-T") != NULL) { - features |= T_family_m; - if (strstr(impl, "SPARC-T1") != NULL) { - features |= T1_model_m; - } - } else { - if (strstr(impl, "SPARC") == NULL) { -#ifndef PRODUCT - // kstat on Solaris 8 virtual machines (branded zones) - // returns "(unsupported)" implementation. Solaris 8 is not - // supported anymore, but include this check to be on the - // safe side. - warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl); -#endif - implementation = "SPARC"; - } - } - os::free((void*)impl); + features |= parse_features(implementation); break; } } // for( } } - assert(strcmp(implementation, "UNKNOWN") != 0, - "unknown cpu info (changed kstat interface?)"); + assert(has_implementation, "unknown cpu info (changed kstat interface?)"); kstat_close(kc); } - // Figure out cache line sizes using PICL - PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); - _L1_data_cache_line_size = picl.L1_data_cache_line_size(); - _L2_data_cache_line_size = picl.L2_data_cache_line_size(); + bool is_sun4v = (features & sun4v_m) != 0; + if (use_solaris_12_api && is_sun4v) { + // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes + Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ); + if (l1_dcache_line_size.valid()) { + _L1_data_cache_line_size = l1_dcache_line_size.value(); + } + Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ); + if (l2_dcache_line_size.valid()) { + _L2_data_cache_line_size = l2_dcache_line_size.value(); + } + } else { + // Otherwise figure out the cache line sizes using PICL + bool is_fujitsu = (features & sparc64_family_m) != 0; + PICL picl(is_fujitsu, is_sun4v); + _L1_data_cache_line_size = picl.L1_data_cache_line_size(); + _L2_data_cache_line_size = picl.L2_data_cache_line_size(); + } return features; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp --- a/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -51,11 +51,8 @@ // movl reg, [reg + thread_ptr_offset] Load thread // void MacroAssembler::get_thread(Register thread) { - // can't use ExternalAddress because it can't take NULL - AddressLiteral null(0, relocInfo::none); - prefix(FS_segment); - movptr(thread, null); + movptr(thread, ExternalAddress(NULL)); assert(os::win32::get_thread_ptr_offset() != 0, "Thread Pointer Offset has not been initialized"); movl(thread, Address(thread, os::win32::get_thread_ptr_offset())); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/adlc/formssel.cpp --- a/hotspot/src/share/vm/adlc/formssel.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/adlc/formssel.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -3491,6 +3491,8 @@ "LoadPLocked", "StorePConditional", "StoreIConditional", "StoreLConditional", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", + "WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN", + "CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN", "StoreCM", "ClearArray", "GetAndAddI", "GetAndSetI", "GetAndSetP", diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_CFGPrinter.hpp --- a/hotspot/src/share/vm/c1/c1_CFGPrinter.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_CFGPrinter.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,9 @@ // compilation for later analysis. class CFGPrinterOutput; -class IntervalList; +class Interval; + +typedef GrowableArray IntervalList; class CFGPrinter : public AllStatic { private: diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_Canonicalizer.cpp --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -222,27 +222,36 @@ } void Canonicalizer::do_ArrayLength (ArrayLength* x) { - NewArray* array = x->array()->as_NewArray(); - if (array != NULL && array->length() != NULL) { - Constant* length = array->length()->as_Constant(); - if (length != NULL) { - // do not use the Constant itself, but create a new Constant - // with same value Otherwise a Constant is live over multiple - // blocks without being registered in a state array. + NewArray* na; + Constant* ct; + LoadField* lf; + + if ((na = x->array()->as_NewArray()) != NULL) { + // New arrays might have the known length. + // Do not use the Constant itself, but create a new Constant + // with same value Otherwise a Constant is live over multiple + // blocks without being registered in a state array. + Constant* length; + if (na->length() != NULL && + (length = na->length()->as_Constant()) != NULL) { assert(length->type()->as_IntConstant() != NULL, "array length must be integer"); set_constant(length->type()->as_IntConstant()->value()); } - } else { - LoadField* lf = x->array()->as_LoadField(); - if (lf != NULL) { - ciField* field = lf->field(); - if (field->is_constant() && field->is_static()) { - // final static field - ciObject* c = field->constant_value().as_object(); - if (c->is_array()) { - ciArray* array = (ciArray*) c; - set_constant(array->length()); - } + + } else if ((ct = x->array()->as_Constant()) != NULL) { + // Constant arrays have constant lengths. + ArrayConstant* cnst = ct->type()->as_ArrayConstant(); + if (cnst != NULL) { + set_constant(cnst->value()->length()); + } + + } else if ((lf = x->array()->as_LoadField()) != NULL) { + ciField* field = lf->field(); + if (field->is_constant() && field->is_static()) { + assert(PatchALot || ScavengeRootsInCode < 2, "Constant field loads are folded during parsing"); + ciObject* c = field->constant_value().as_object(); + if (!c->is_null_object()) { + set_constant(c->as_array()->length()); } } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_Compiler.cpp --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -228,8 +228,6 @@ case vmIntrinsics::_getCharStringU: case vmIntrinsics::_putCharStringU: #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif break; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -43,6 +43,9 @@ #if INCLUDE_ALL_GCS #include "gc/g1/heapRegion.hpp" #endif // INCLUDE_ALL_GCS +#ifdef TRACE_HAVE_INTRINSICS +#include "trace/traceMacros.hpp" +#endif #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -3067,42 +3070,7 @@ __ move(reg, result); } -#ifdef TRACE_HAVE_INTRINSICS -void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) { - LIR_Opr thread = getThreadPointer(); - LIR_Opr osthread = new_pointer_register(); - __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread); - size_t thread_id_size = OSThread::thread_id_size(); - if (thread_id_size == (size_t) BytesPerLong) { - LIR_Opr id = new_register(T_LONG); - __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id); - __ convert(Bytecodes::_l2i, id, rlock_result(x)); - } else if (thread_id_size == (size_t) BytesPerInt) { - __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x)); - } else { - ShouldNotReachHere(); - } -} - -void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { - CodeEmitInfo* info = state_for(x); - CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check - BasicType klass_pointer_type = NOT_LP64(T_INT) LP64_ONLY(T_LONG); - assert(info != NULL, "must have info"); - LIRItem arg(x->argument_at(1), this); - arg.load_item(); - LIR_Opr klass = new_pointer_register(); - __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), klass_pointer_type), klass, info); - LIR_Opr id = new_register(T_LONG); - ByteSize offset = TRACE_ID_OFFSET; - LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG); - __ move(trace_id_addr, id); - __ logical_or(id, LIR_OprFact::longConst(0x01l), id); - __ store(id, trace_id_addr); - __ logical_and(id, LIR_OprFact::longConst(~0x3l), id); - __ move(id, rlock_result(x)); -} -#endif + void LIRGenerator::do_Intrinsic(Intrinsic* x) { switch (x->id()) { @@ -3115,8 +3083,6 @@ } #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break; - case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break; case vmIntrinsics::_counterTime: do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), x); break; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_LIRGenerator.hpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -440,10 +440,7 @@ void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux); void do_RuntimeCall(address routine, Intrinsic* x); -#ifdef TRACE_HAVE_INTRINSICS - void do_ThreadIDIntrinsic(Intrinsic* x); - void do_ClassIDIntrinsic(Intrinsic* x); -#endif + ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, ciKlass* callee_signature_k); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1434,41 +1434,73 @@ } #ifndef PRODUCT +int interval_cmp(Interval* const& l, Interval* const& r) { + return l->from() - r->from(); +} + +bool find_interval(Interval* interval, IntervalArray* intervals) { + bool found; + int idx = intervals->find_sorted(interval, found); + + if (!found) { + return false; + } + + int from = interval->from(); + + // The index we've found using binary search is pointing to an interval + // that is defined in the same place as the interval we were looking for. + // So now we have to look around that index and find exact interval. + for (int i = idx; i >= 0; i--) { + if (intervals->at(i) == interval) { + return true; + } + if (intervals->at(i)->from() != from) { + break; + } + } + + for (int i = idx + 1; i < intervals->length(); i++) { + if (intervals->at(i) == interval) { + return true; + } + if (intervals->at(i)->from() != from) { + break; + } + } + + return false; +} + bool LinearScan::is_sorted(IntervalArray* intervals) { int from = -1; - int i, j; - for (i = 0; i < intervals->length(); i ++) { + int null_count = 0; + + for (int i = 0; i < intervals->length(); i++) { Interval* it = intervals->at(i); if (it != NULL) { - if (from > it->from()) { - assert(false, ""); - return false; - } + assert(from <= it->from(), "Intervals are unordered"); from = it->from(); - } - } - - // check in both directions if sorted list and unsorted list contain same intervals - for (i = 0; i < interval_count(); i++) { - if (interval_at(i) != NULL) { - int num_found = 0; - for (j = 0; j < intervals->length(); j++) { - if (interval_at(i) == intervals->at(j)) { - num_found++; - } - } - assert(num_found == 1, "lists do not contain same intervals"); - } - } - for (j = 0; j < intervals->length(); j++) { - int num_found = 0; - for (i = 0; i < interval_count(); i++) { - if (interval_at(i) == intervals->at(j)) { - num_found++; - } - } - assert(num_found == 1, "lists do not contain same intervals"); - } + } else { + null_count++; + } + } + + assert(null_count == 0, "Sorted intervals should not contain nulls"); + + null_count = 0; + + for (int i = 0; i < interval_count(); i++) { + Interval* interval = interval_at(i); + if (interval != NULL) { + assert(find_interval(interval, intervals), "Lists do not contain same intervals"); + } else { + null_count++; + } + } + + assert(interval_count() - null_count == intervals->length(), + "Sorted list should contain the same amount of non-NULL intervals as unsorted list"); return true; } @@ -1536,7 +1568,7 @@ sorted_len++; } } - IntervalArray* sorted_list = new IntervalArray(sorted_len); + IntervalArray* sorted_list = new IntervalArray(sorted_len, sorted_len, NULL); // special sorting algorithm: the original interval-list is almost sorted, // only some intervals are swapped. So this is much faster than a complete QuickSort @@ -1574,8 +1606,8 @@ _needs_full_resort = false; } - IntervalArray* old_list = _sorted_intervals; - IntervalList* new_list = _new_intervals_from_allocation; + IntervalArray* old_list = _sorted_intervals; + IntervalList* new_list = _new_intervals_from_allocation; int old_len = old_list->length(); int new_len = new_list->length(); @@ -1589,7 +1621,8 @@ new_list->sort(interval_cmp); // merge old and new list (both already sorted) into one combined list - IntervalArray* combined_list = new IntervalArray(old_len + new_len); + int combined_list_len = old_len + new_len; + IntervalArray* combined_list = new IntervalArray(combined_list_len, combined_list_len, NULL); int old_idx = 0; int new_idx = 0; @@ -3211,6 +3244,10 @@ has_error = true; } + // special intervals that are created in MoveResolver + // -> ignore them because the range information has no meaning there + if (i1->from() == 1 && i1->to() == 2) continue; + if (i1->first() == Range::end()) { tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr(); has_error = true; @@ -3225,18 +3262,13 @@ for (int j = i + 1; j < len; j++) { Interval* i2 = interval_at(j); - if (i2 == NULL) continue; - - // special intervals that are created in MoveResolver - // -> ignore them because the range information has no meaning there - if (i1->from() == 1 && i1->to() == 2) continue; - if (i2->from() == 1 && i2->to() == 2) continue; + if (i2 == NULL || (i2->from() == 1 && i2->to() == 2)) continue; int r1 = i1->assigned_reg(); int r1Hi = i1->assigned_regHi(); int r2 = i2->assigned_reg(); int r2Hi = i2->assigned_regHi(); - if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) { + if ((r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi))) && i1->intersects(i2)) { tty->print_cr("Intervals %d and %d overlap and have the same register assigned", i1->reg_num(), i2->reg_num()); i1->print(); tty->cr(); i2->print(); tty->cr(); @@ -3429,7 +3461,8 @@ void RegisterVerifier::verify(BlockBegin* start) { // setup input registers (method arguments) for first block - IntervalList* input_state = new IntervalList(state_size(), NULL); + int input_state_len = state_size(); + IntervalList* input_state = new IntervalList(input_state_len, input_state_len, NULL); CallingConvention* args = compilation()->frame_map()->incoming_arguments(); for (int n = 0; n < args->length(); n++) { LIR_Opr opr = args->at(n); @@ -3543,7 +3576,7 @@ IntervalList* RegisterVerifier::copy(IntervalList* input_state) { IntervalList* copy_state = new IntervalList(input_state->length()); - copy_state->push_all(input_state); + copy_state->appendAll(input_state); return copy_state; } @@ -5506,7 +5539,7 @@ IntervalList* processed = _spill_intervals[reg]; for (int i = 0; i < _spill_intervals[regHi]->length(); i++) { Interval* it = _spill_intervals[regHi]->at(i); - if (processed->index_of(it) == -1) { + if (processed->find_from_end(it) == -1) { remove_from_list(it); split_and_spill_interval(it); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_LinearScan.hpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,8 +42,8 @@ class MoveResolver; class Range; -define_array(IntervalArray, Interval*) -define_stack(IntervalList, IntervalArray) +typedef GrowableArray IntervalArray; +typedef GrowableArray IntervalList; define_array(IntervalsArray, IntervalList*) define_stack(IntervalsList, IntervalsArray) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/c1/c1_Runtime1.cpp diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/ci/ciArray.cpp --- a/hotspot/src/share/vm/ci/ciArray.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/ci/ciArray.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -107,8 +107,9 @@ intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt); intptr_t index = (element_offset - header) >> shift; intptr_t offset = header + ((intptr_t)index << shift); - if (offset != element_offset || index != (jint)index) + if (offset != element_offset || index != (jint)index || index < 0 || index >= length()) { return ciConstant(); + } return element_value((jint) index); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/ci/ciConstantPoolCache.cpp --- a/hotspot/src/share/vm/ci/ciConstantPoolCache.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/ci/ciConstantPoolCache.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -41,15 +41,21 @@ _keys = new (arena) GrowableArray(arena, expected_size, 0, 0); } +int ciConstantPoolCache::key_compare(const int& key, const int& elt) { + if (key < elt) return -1; + else if (key > elt) return 1; + else return 0; +} + // ------------------------------------------------------------------ // ciConstantPoolCache::get // // Get the entry at some index void* ciConstantPoolCache::get(int index) { ASSERT_IN_VM; - int pos = find(index); - if (pos >= _keys->length() || - _keys->at(pos) != index) { + bool found = false; + int pos = _keys->find_sorted(index, found); + if (!found) { // This element is not present in the cache. return NULL; } @@ -57,42 +63,15 @@ } // ------------------------------------------------------------------ -// ciConstantPoolCache::find -// -// Use binary search to find the position of this index in the cache. -// If there is no entry in the cache corresponding to this oop, return -// the position at which the index would be inserted. -int ciConstantPoolCache::find(int key) { - int min = 0; - int max = _keys->length()-1; - - while (max >= min) { - int mid = (max + min) / 2; - int value = _keys->at(mid); - if (value < key) { - min = mid + 1; - } else if (value > key) { - max = mid - 1; - } else { - return mid; - } - } - return min; -} - -// ------------------------------------------------------------------ // ciConstantPoolCache::insert // // Insert a ciObject into the table at some index. void ciConstantPoolCache::insert(int index, void* elem) { - int i; - int pos = find(index); - for (i = _keys->length()-1; i >= pos; i--) { - _keys->at_put_grow(i+1, _keys->at(i)); - _elements->at_put_grow(i+1, _elements->at(i)); - } - _keys->at_put_grow(pos, index); - _elements->at_put_grow(pos, elem); + bool found = false; + int pos = _keys->find_sorted(index, found); + assert(!found, "duplicate"); + _keys->insert_before(pos, index); + _elements->insert_before(pos, elem); } // ------------------------------------------------------------------ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/ci/ciConstantPoolCache.hpp --- a/hotspot/src/share/vm/ci/ciConstantPoolCache.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/ci/ciConstantPoolCache.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -38,7 +38,7 @@ GrowableArray* _keys; GrowableArray* _elements; - int find(int index); + static int key_compare(const int& key, const int& elt); public: ciConstantPoolCache(Arena* arena, int expected_size); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/ci/ciObjectFactory.cpp --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -260,6 +260,13 @@ return new_object; } +int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) { + Metadata* value = elt->constant_encoding(); + if (key < value) return -1; + else if (key > value) return 1; + else return 0; +} + // ------------------------------------------------------------------ // ciObjectFactory::get_metadata // @@ -280,7 +287,8 @@ } #endif // ASSERT int len = _ci_metadata->length(); - int index = find(key, _ci_metadata); + bool found = false; + int index = _ci_metadata->find_sorted(key, found); #ifdef ASSERT if (CIObjectFactoryVerify) { for (int i=0; i<_ci_metadata->length(); i++) { @@ -290,7 +298,8 @@ } } #endif - if (!is_found_at(index, key, _ci_metadata)) { + + if (!found) { // The ciMetadata does not yet exist. Create it and insert it // into the cache. ciMetadata* new_object = create_new_metadata(key); @@ -300,10 +309,10 @@ if (len != _ci_metadata->length()) { // creating the new object has recursively entered new objects // into the table. We need to recompute our index. - index = find(key, _ci_metadata); + index = _ci_metadata->find_sorted(key, found); } - assert(!is_found_at(index, key, _ci_metadata), "no double insert"); - insert(index, new_object, _ci_metadata); + assert(!found, "no double insert"); + _ci_metadata->insert_before(index, new_object); return new_object; } return _ci_metadata->at(index)->as_metadata(); @@ -655,60 +664,6 @@ obj->set_ident(_next_ident++); } -// ------------------------------------------------------------------ -// ciObjectFactory::find -// -// Use binary search to find the position of this oop in the cache. -// If there is no entry in the cache corresponding to this oop, return -// the position at which the oop should be inserted. -int ciObjectFactory::find(Metadata* key, GrowableArray* objects) { - int min = 0; - int max = objects->length()-1; - - // print_contents(); - - while (max >= min) { - int mid = (max + min) / 2; - Metadata* value = objects->at(mid)->constant_encoding(); - if (value < key) { - min = mid + 1; - } else if (value > key) { - max = mid - 1; - } else { - return mid; - } - } - return min; -} - -// ------------------------------------------------------------------ -// ciObjectFactory::is_found_at -// -// Verify that the binary seach found the given key. -bool ciObjectFactory::is_found_at(int index, Metadata* key, GrowableArray* objects) { - return (index < objects->length() && - objects->at(index)->constant_encoding() == key); -} - - -// ------------------------------------------------------------------ -// ciObjectFactory::insert -// -// Insert a ciObject into the table at some index. -void ciObjectFactory::insert(int index, ciMetadata* obj, GrowableArray* objects) { - int len = objects->length(); - if (len == index) { - objects->append(obj); - } else { - objects->append(objects->at(len-1)); - int pos; - for (pos = len-2; pos >= index; pos--) { - objects->at_put(pos+1,objects->at(pos)); - } - objects->at_put(index, obj); - } -} - static ciObjectFactory::NonPermObject* emptyBucket = NULL; // ------------------------------------------------------------------ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/ci/ciObjectFactory.hpp --- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -68,9 +68,7 @@ NonPermObject* _non_perm_bucket[NON_PERM_BUCKETS]; int _non_perm_count; - int find(Metadata* key, GrowableArray* objects); - bool is_found_at(int index, Metadata* key, GrowableArray* objects); - void insert(int index, ciMetadata* obj, GrowableArray* objects); + static int metadata_compare(Metadata* const& key, ciMetadata* const& elt); ciObject* create_new_object(oop o); ciMetadata* create_new_metadata(Metadata* o); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -5380,7 +5380,7 @@ } } - TRACE_INIT_ID(ik); + TRACE_INIT_KLASS_ID(ik); // If we reach here, all is well. // Now remove the InstanceKlass* from the _klass_to_deallocate field diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/classLoader.cpp --- a/hotspot/src/share/vm/classfile/classLoader.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -37,6 +37,7 @@ #include "gc/shared/generation.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/oopMapCache.hpp" +#include "logging/logTag.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" @@ -417,34 +418,30 @@ #if INCLUDE_CDS void ClassLoader::exit_with_path_failure(const char* error, const char* message) { assert(DumpSharedSpaces, "only called at dump time"); - tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure"); + tty->print_cr("Hint: enable -Xlog:classpath=info to diagnose the failure"); vm_exit_during_initialization(error, message); } #endif -void ClassLoader::trace_class_path(outputStream* out, const char* msg, const char* name) { - if (!TraceClassPaths) { - return; - } - - if (msg) { - out->print("%s", msg); - } - if (name) { - if (strlen(name) < 256) { - out->print("%s", name); - } else { - // For very long paths, we need to print each character separately, - // as print_cr() has a length limit - while (name[0] != '\0') { - out->print("%c", name[0]); - name++; +void ClassLoader::trace_class_path(const char* msg, const char* name) { + if (log_is_enabled(Info, classpath)) { + ResourceMark rm; + outputStream* out = LogHandle(classpath)::info_stream(); + if (msg) { + out->print("%s", msg); + } + if (name) { + if (strlen(name) < 256) { + out->print("%s", name); + } else { + // For very long paths, we need to print each character separately, + // as print_cr() has a length limit + while (name[0] != '\0') { + out->print("%c", name[0]); + name++; + } } } - } - if (msg && msg[0] == '[') { - out->print_cr("]"); - } else { out->cr(); } } @@ -470,11 +467,13 @@ void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); const char* sys_class_path = Arguments::get_sysclasspath(); + const char* java_class_path = Arguments::get_appclasspath(); if (PrintSharedArchiveAndExit) { // Don't print sys_class_path - this is the bootcp of this current VM process, not necessarily // the same as the bootcp of the shared archive. } else { - trace_class_path(tty, "[Bootstrap loader class path=", sys_class_path); + trace_class_path("bootstrap loader class path=", sys_class_path); + trace_class_path("classpath: ", java_class_path); } #if INCLUDE_CDS if (DumpSharedSpaces) { @@ -578,9 +577,7 @@ } } } - if (TraceClassPaths) { - tty->print_cr("[Opened %s]", path); - } + log_info(classpath)("opened: %s", path); log_info(classload)("opened: %s", path); } else { // Directory diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/classLoader.hpp --- a/hotspot/src/share/vm/classfile/classLoader.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/classLoader.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -331,7 +331,7 @@ static void exit_with_path_failure(const char* error, const char* message); #endif - static void trace_class_path(outputStream* out, const char* msg, const char* name = NULL); + static void trace_class_path(const char* msg, const char* name = NULL); // VM monitoring and management support static jlong classloader_time_ms(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/dictionary.cpp --- a/hotspot/src/share/vm/classfile/dictionary.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/dictionary.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -135,8 +135,10 @@ // via a store to _pd_set. OrderAccess::release_store_ptr(&_pd_set, new_head); } - if (TraceProtectionDomainVerification && WizardMode) { - print(); + if (log_is_enabled(Trace, protectiondomain)) { + ResourceMark rm; + outputStream* log = LogHandle(protectiondomain)::trace_stream(); + print_count(log); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/dictionary.hpp --- a/hotspot/src/share/vm/classfile/dictionary.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/dictionary.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -29,6 +29,7 @@ #include "oops/instanceKlass.hpp" #include "oops/oop.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" class DictionaryEntry; class PSPromotionManager; @@ -323,14 +324,14 @@ return (klass->name() == class_name && _loader_data == loader_data); } - void print() { + void print_count(outputStream *st) { int count = 0; for (ProtectionDomainEntry* current = _pd_set; current != NULL; current = current->_next) { count++; } - tty->print_cr("pd set = #%d", count); + st->print_cr("pd set count = #%d", count); } }; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/klassFactory.cpp --- a/hotspot/src/share/vm/classfile/klassFactory.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/klassFactory.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "classfile/klassFactory.hpp" #include "memory/resourceArea.hpp" #include "prims/jvmtiEnvBase.hpp" +#include "trace/traceMacros.hpp" static ClassFileStream* prologue(ClassFileStream* stream, Symbol* name, @@ -136,5 +137,7 @@ result->set_cached_class_file(cached_class_file); } + TRACE_KLASS_CREATION(result, parser, THREAD); + return result; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,15 +26,15 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/sharedPathsMiscInfo.hpp" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/metaspaceShared.hpp" #include "runtime/arguments.hpp" +#include "utilities/ostream.hpp" void SharedPathsMiscInfo::add_path(const char* path, int type) { - if (TraceClassPaths) { - tty->print("[type=%s] ", type_name(type)); - trace_class_path("[Add misc shared path ", path); - } + log_info(classpath)("type=%s ", type_name(type)); + ClassLoader::trace_class_path("add misc shared path ", path); write(path, strlen(path) + 1); write_jint(jint(type)); } @@ -67,11 +67,29 @@ } bool SharedPathsMiscInfo::fail(const char* msg, const char* name) { - ClassLoader::trace_class_path(tty, msg, name); + ClassLoader::trace_class_path(msg, name); MetaspaceShared::set_archive_loading_failed(); return false; } +void SharedPathsMiscInfo::print_path(int type, const char* path) { + ResourceMark rm; + outputStream* out = LogHandle(classpath)::info_stream(); + switch (type) { + case BOOT: + out->print("Expecting -Dsun.boot.class.path=%s", path); + break; + case NON_EXIST: + out->print("Expecting that %s does not exist", path); + break; + case REQUIRED: + out->print("Expecting that file %s must exist and is not altered", path); + break; + default: + ShouldNotReachHere(); + } +} + bool SharedPathsMiscInfo::check() { // The whole buffer must be 0 terminated so that we can use strlen and strcmp // without fear. @@ -90,17 +108,14 @@ if (!read_jint(&type)) { return fail("Corrupted archive file header"); } - if (TraceClassPaths) { - tty->print("[type=%s ", type_name(type)); - print_path(tty, type, path); - tty->print_cr("]"); - } + log_info(classpath)("type=%s ", type_name(type)); + print_path(type, path); if (!check(type, path)) { if (!PrintSharedArchiveAndExit) { return false; } } else { - trace_class_path("[ok"); + ClassLoader::trace_class_path("ok"); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -64,9 +64,6 @@ void write(const void* ptr, size_t size); bool read(void* ptr, size_t size); - static void trace_class_path(const char* msg, const char* name = NULL) { - ClassLoader::trace_class_path(tty, msg, name); - } protected: static bool fail(const char* msg, const char* name = NULL); virtual bool check(jint type, const char* path); @@ -144,21 +141,7 @@ } } - virtual void print_path(outputStream* out, int type, const char* path) { - switch (type) { - case BOOT: - out->print("Expecting -Dsun.boot.class.path=%s", path); - break; - case NON_EXIST: - out->print("Expecting that %s does not exist", path); - break; - case REQUIRED: - out->print("Expecting that file %s must exist and is not altered", path); - break; - default: - ShouldNotReachHere(); - } - } + virtual void print_path(int type, const char* path); bool check(); bool read_jint(jint *ptr) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -430,12 +430,15 @@ // Now we have to call back to java to check if the initating class has access JavaValue result(T_VOID); - if (TraceProtectionDomainVerification) { + if (log_is_enabled(Debug, protectiondomain)) { + ResourceMark rm; // Print out trace information - tty->print_cr("Checking package access"); - tty->print(" - class loader: "); class_loader()->print_value_on(tty); tty->cr(); - tty->print(" - protection domain: "); protection_domain()->print_value_on(tty); tty->cr(); - tty->print(" - loading: "); klass()->print_value_on(tty); tty->cr(); + outputStream* log = LogHandle(protectiondomain)::debug_stream(); + log->print_cr("Checking package access"); + log->print("class loader: "); class_loader()->print_value_on(log); + log->print(" protection domain: "); protection_domain()->print_value_on(log); + log->print(" loading: "); klass()->print_value_on(log); + log->cr(); } KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass()); @@ -448,13 +451,10 @@ protection_domain, THREAD); - if (TraceProtectionDomainVerification) { - if (HAS_PENDING_EXCEPTION) { - tty->print_cr(" -> DENIED !!!!!!!!!!!!!!!!!!!!!"); - } else { - tty->print_cr(" -> granted"); - } - tty->cr(); + if (HAS_PENDING_EXCEPTION) { + log_debug(protectiondomain)("DENIED !!!!!!!!!!!!!!!!!!!!!"); + } else { + log_debug(protectiondomain)("granted"); } if (HAS_PENDING_EXCEPTION) return; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/vmSymbols.cpp --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -328,8 +328,6 @@ assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); switch(id) { #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_currentTimeMillis: @@ -544,6 +542,42 @@ case vmIntrinsics::_putLongVolatile: case vmIntrinsics::_putFloatVolatile: case vmIntrinsics::_putDoubleVolatile: + case vmIntrinsics::_getObjectAcquire: + case vmIntrinsics::_getBooleanAcquire: + case vmIntrinsics::_getByteAcquire: + case vmIntrinsics::_getShortAcquire: + case vmIntrinsics::_getCharAcquire: + case vmIntrinsics::_getIntAcquire: + case vmIntrinsics::_getLongAcquire: + case vmIntrinsics::_getFloatAcquire: + case vmIntrinsics::_getDoubleAcquire: + case vmIntrinsics::_putObjectRelease: + case vmIntrinsics::_putBooleanRelease: + case vmIntrinsics::_putByteRelease: + case vmIntrinsics::_putShortRelease: + case vmIntrinsics::_putCharRelease: + case vmIntrinsics::_putIntRelease: + case vmIntrinsics::_putLongRelease: + case vmIntrinsics::_putFloatRelease: + case vmIntrinsics::_putDoubleRelease: + case vmIntrinsics::_getObjectOpaque: + case vmIntrinsics::_getBooleanOpaque: + case vmIntrinsics::_getByteOpaque: + case vmIntrinsics::_getShortOpaque: + case vmIntrinsics::_getCharOpaque: + case vmIntrinsics::_getIntOpaque: + case vmIntrinsics::_getLongOpaque: + case vmIntrinsics::_getFloatOpaque: + case vmIntrinsics::_getDoubleOpaque: + case vmIntrinsics::_putObjectOpaque: + case vmIntrinsics::_putBooleanOpaque: + case vmIntrinsics::_putByteOpaque: + case vmIntrinsics::_putShortOpaque: + case vmIntrinsics::_putCharOpaque: + case vmIntrinsics::_putIntOpaque: + case vmIntrinsics::_putLongOpaque: + case vmIntrinsics::_putFloatOpaque: + case vmIntrinsics::_putDoubleOpaque: case vmIntrinsics::_getByte_raw: case vmIntrinsics::_getShort_raw: case vmIntrinsics::_getChar_raw: @@ -569,9 +603,27 @@ case vmIntrinsics::_loadFence: case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: + case vmIntrinsics::_compareAndSwapLong: + case vmIntrinsics::_weakCompareAndSwapLong: + case vmIntrinsics::_weakCompareAndSwapLongAcquire: + case vmIntrinsics::_weakCompareAndSwapLongRelease: + case vmIntrinsics::_compareAndSwapInt: + case vmIntrinsics::_weakCompareAndSwapInt: + case vmIntrinsics::_weakCompareAndSwapIntAcquire: + case vmIntrinsics::_weakCompareAndSwapIntRelease: case vmIntrinsics::_compareAndSwapObject: - case vmIntrinsics::_compareAndSwapLong: - case vmIntrinsics::_compareAndSwapInt: + case vmIntrinsics::_weakCompareAndSwapObject: + case vmIntrinsics::_weakCompareAndSwapObjectAcquire: + case vmIntrinsics::_weakCompareAndSwapObjectRelease: + case vmIntrinsics::_compareAndExchangeIntVolatile: + case vmIntrinsics::_compareAndExchangeIntAcquire: + case vmIntrinsics::_compareAndExchangeIntRelease: + case vmIntrinsics::_compareAndExchangeLongVolatile: + case vmIntrinsics::_compareAndExchangeLongAcquire: + case vmIntrinsics::_compareAndExchangeLongRelease: + case vmIntrinsics::_compareAndExchangeObjectVolatile: + case vmIntrinsics::_compareAndExchangeObjectAcquire: + case vmIntrinsics::_compareAndExchangeObjectRelease: if (!InlineUnsafeOps) return true; break; case vmIntrinsics::_getShortUnaligned: diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1146,6 +1146,64 @@ do_intrinsic(_putFloatVolatile, jdk_internal_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \ do_intrinsic(_putDoubleVolatile, jdk_internal_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \ \ + do_name(getObjectOpaque_name,"getObjectOpaque") do_name(putObjectOpaque_name,"putObjectOpaque") \ + do_name(getBooleanOpaque_name,"getBooleanOpaque") do_name(putBooleanOpaque_name,"putBooleanOpaque") \ + do_name(getByteOpaque_name,"getByteOpaque") do_name(putByteOpaque_name,"putByteOpaque") \ + do_name(getShortOpaque_name,"getShortOpaque") do_name(putShortOpaque_name,"putShortOpaque") \ + do_name(getCharOpaque_name,"getCharOpaque") do_name(putCharOpaque_name,"putCharOpaque") \ + do_name(getIntOpaque_name,"getIntOpaque") do_name(putIntOpaque_name,"putIntOpaque") \ + do_name(getLongOpaque_name,"getLongOpaque") do_name(putLongOpaque_name,"putLongOpaque") \ + do_name(getFloatOpaque_name,"getFloatOpaque") do_name(putFloatOpaque_name,"putFloatOpaque") \ + do_name(getDoubleOpaque_name,"getDoubleOpaque") do_name(putDoubleOpaque_name,"putDoubleOpaque") \ + \ + do_intrinsic(_getObjectOpaque, jdk_internal_misc_Unsafe, getObjectOpaque_name, getObject_signature, F_R) \ + do_intrinsic(_getBooleanOpaque, jdk_internal_misc_Unsafe, getBooleanOpaque_name, getBoolean_signature, F_R) \ + do_intrinsic(_getByteOpaque, jdk_internal_misc_Unsafe, getByteOpaque_name, getByte_signature, F_R) \ + do_intrinsic(_getShortOpaque, jdk_internal_misc_Unsafe, getShortOpaque_name, getShort_signature, F_R) \ + do_intrinsic(_getCharOpaque, jdk_internal_misc_Unsafe, getCharOpaque_name, getChar_signature, F_R) \ + do_intrinsic(_getIntOpaque, jdk_internal_misc_Unsafe, getIntOpaque_name, getInt_signature, F_R) \ + do_intrinsic(_getLongOpaque, jdk_internal_misc_Unsafe, getLongOpaque_name, getLong_signature, F_R) \ + do_intrinsic(_getFloatOpaque, jdk_internal_misc_Unsafe, getFloatOpaque_name, getFloat_signature, F_R) \ + do_intrinsic(_getDoubleOpaque, jdk_internal_misc_Unsafe, getDoubleOpaque_name, getDouble_signature, F_R) \ + do_intrinsic(_putObjectOpaque, jdk_internal_misc_Unsafe, putObjectOpaque_name, putObject_signature, F_R) \ + do_intrinsic(_putBooleanOpaque, jdk_internal_misc_Unsafe, putBooleanOpaque_name, putBoolean_signature, F_R) \ + do_intrinsic(_putByteOpaque, jdk_internal_misc_Unsafe, putByteOpaque_name, putByte_signature, F_R) \ + do_intrinsic(_putShortOpaque, jdk_internal_misc_Unsafe, putShortOpaque_name, putShort_signature, F_R) \ + do_intrinsic(_putCharOpaque, jdk_internal_misc_Unsafe, putCharOpaque_name, putChar_signature, F_R) \ + do_intrinsic(_putIntOpaque, jdk_internal_misc_Unsafe, putIntOpaque_name, putInt_signature, F_R) \ + do_intrinsic(_putLongOpaque, jdk_internal_misc_Unsafe, putLongOpaque_name, putLong_signature, F_R) \ + do_intrinsic(_putFloatOpaque, jdk_internal_misc_Unsafe, putFloatOpaque_name, putFloat_signature, F_R) \ + do_intrinsic(_putDoubleOpaque, jdk_internal_misc_Unsafe, putDoubleOpaque_name, putDouble_signature, F_R) \ + \ + do_name(getObjectAcquire_name, "getObjectAcquire") do_name(putObjectRelease_name, "putObjectRelease") \ + do_name(getBooleanAcquire_name, "getBooleanAcquire") do_name(putBooleanRelease_name, "putBooleanRelease") \ + do_name(getByteAcquire_name, "getByteAcquire") do_name(putByteRelease_name, "putByteRelease") \ + do_name(getShortAcquire_name, "getShortAcquire") do_name(putShortRelease_name, "putShortRelease") \ + do_name(getCharAcquire_name, "getCharAcquire") do_name(putCharRelease_name, "putCharRelease") \ + do_name(getIntAcquire_name, "getIntAcquire") do_name(putIntRelease_name, "putIntRelease") \ + do_name(getLongAcquire_name, "getLongAcquire") do_name(putLongRelease_name, "putLongRelease") \ + do_name(getFloatAcquire_name, "getFloatAcquire") do_name(putFloatRelease_name, "putFloatRelease") \ + do_name(getDoubleAcquire_name, "getDoubleAcquire") do_name(putDoubleRelease_name, "putDoubleRelease") \ + \ + do_intrinsic(_getObjectAcquire, jdk_internal_misc_Unsafe, getObjectAcquire_name, getObject_signature, F_R) \ + do_intrinsic(_getBooleanAcquire, jdk_internal_misc_Unsafe, getBooleanAcquire_name, getBoolean_signature, F_R) \ + do_intrinsic(_getByteAcquire, jdk_internal_misc_Unsafe, getByteAcquire_name, getByte_signature, F_R) \ + do_intrinsic(_getShortAcquire, jdk_internal_misc_Unsafe, getShortAcquire_name, getShort_signature, F_R) \ + do_intrinsic(_getCharAcquire, jdk_internal_misc_Unsafe, getCharAcquire_name, getChar_signature, F_R) \ + do_intrinsic(_getIntAcquire, jdk_internal_misc_Unsafe, getIntAcquire_name, getInt_signature, F_R) \ + do_intrinsic(_getLongAcquire, jdk_internal_misc_Unsafe, getLongAcquire_name, getLong_signature, F_R) \ + do_intrinsic(_getFloatAcquire, jdk_internal_misc_Unsafe, getFloatAcquire_name, getFloat_signature, F_R) \ + do_intrinsic(_getDoubleAcquire, jdk_internal_misc_Unsafe, getDoubleAcquire_name, getDouble_signature, F_R) \ + do_intrinsic(_putObjectRelease, jdk_internal_misc_Unsafe, putObjectRelease_name, putObject_signature, F_R) \ + do_intrinsic(_putBooleanRelease, jdk_internal_misc_Unsafe, putBooleanRelease_name, putBoolean_signature, F_R) \ + do_intrinsic(_putByteRelease, jdk_internal_misc_Unsafe, putByteRelease_name, putByte_signature, F_R) \ + do_intrinsic(_putShortRelease, jdk_internal_misc_Unsafe, putShortRelease_name, putShort_signature, F_R) \ + do_intrinsic(_putCharRelease, jdk_internal_misc_Unsafe, putCharRelease_name, putChar_signature, F_R) \ + do_intrinsic(_putIntRelease, jdk_internal_misc_Unsafe, putIntRelease_name, putInt_signature, F_R) \ + do_intrinsic(_putLongRelease, jdk_internal_misc_Unsafe, putLongRelease_name, putLong_signature, F_R) \ + do_intrinsic(_putFloatRelease, jdk_internal_misc_Unsafe, putFloatRelease_name, putFloat_signature, F_R) \ + do_intrinsic(_putDoubleRelease, jdk_internal_misc_Unsafe, putDoubleRelease_name, putDouble_signature, F_R) \ + \ do_name(getShortUnaligned_name,"getShortUnaligned") do_name(putShortUnaligned_name,"putShortUnaligned") \ do_name(getCharUnaligned_name,"getCharUnaligned") do_name(putCharUnaligned_name,"putCharUnaligned") \ do_name(getIntUnaligned_name,"getIntUnaligned") do_name(putIntUnaligned_name,"putIntUnaligned") \ @@ -1197,24 +1255,68 @@ do_intrinsic(_putDouble_raw, jdk_internal_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_R) \ do_intrinsic(_putAddress_raw, jdk_internal_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_R) \ \ - do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_R) \ - do_name( compareAndSwapObject_name, "compareAndSwapObject") \ - do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ - do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_R) \ - do_name( compareAndSwapLong_name, "compareAndSwapLong") \ - do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \ - do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_R) \ - do_name( compareAndSwapInt_name, "compareAndSwapInt") \ - do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \ - do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_R) \ - do_name( putOrderedObject_name, "putOrderedObject") \ - do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \ - do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_R) \ - do_name( putOrderedLong_name, "putOrderedLong") \ - do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \ - do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_R) \ - do_name( putOrderedInt_name, "putOrderedInt") \ - do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \ + do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \ + do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \ + do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \ + do_signature(compareAndExchangeLong_signature, "(Ljava/lang/Object;JJJ)J") \ + do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \ + do_signature(compareAndExchangeInt_signature, "(Ljava/lang/Object;JII)I") \ + \ + do_name(compareAndSwapObject_name, "compareAndSwapObject") \ + do_name(compareAndExchangeObjectVolatile_name, "compareAndExchangeObjectVolatile") \ + do_name(compareAndExchangeObjectAcquire_name, "compareAndExchangeObjectAcquire") \ + do_name(compareAndExchangeObjectRelease_name, "compareAndExchangeObjectRelease") \ + do_name(compareAndSwapLong_name, "compareAndSwapLong") \ + do_name(compareAndExchangeLongVolatile_name, "compareAndExchangeLongVolatile") \ + do_name(compareAndExchangeLongAcquire_name, "compareAndExchangeLongAcquire") \ + do_name(compareAndExchangeLongRelease_name, "compareAndExchangeLongRelease") \ + do_name(compareAndSwapInt_name, "compareAndSwapInt") \ + do_name(compareAndExchangeIntVolatile_name, "compareAndExchangeIntVolatile") \ + do_name(compareAndExchangeIntAcquire_name, "compareAndExchangeIntAcquire") \ + do_name(compareAndExchangeIntRelease_name, "compareAndExchangeIntRelease") \ + \ + do_name(weakCompareAndSwapObject_name, "weakCompareAndSwapObject") \ + do_name(weakCompareAndSwapObjectAcquire_name, "weakCompareAndSwapObjectAcquire") \ + do_name(weakCompareAndSwapObjectRelease_name, "weakCompareAndSwapObjectRelease") \ + do_name(weakCompareAndSwapLong_name, "weakCompareAndSwapLong") \ + do_name(weakCompareAndSwapLongAcquire_name, "weakCompareAndSwapLongAcquire") \ + do_name(weakCompareAndSwapLongRelease_name, "weakCompareAndSwapLongRelease") \ + do_name(weakCompareAndSwapInt_name, "weakCompareAndSwapInt") \ + do_name(weakCompareAndSwapIntAcquire_name, "weakCompareAndSwapIntAcquire") \ + do_name(weakCompareAndSwapIntRelease_name, "weakCompareAndSwapIntRelease") \ + \ + do_intrinsic(_compareAndSwapObject, jdk_internal_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_RN) \ + do_intrinsic(_compareAndExchangeObjectVolatile, jdk_internal_misc_Unsafe, compareAndExchangeObjectVolatile_name, compareAndExchangeObject_signature, F_RN) \ + do_intrinsic(_compareAndExchangeObjectAcquire, jdk_internal_misc_Unsafe, compareAndExchangeObjectAcquire_name, compareAndExchangeObject_signature, F_R) \ + do_intrinsic(_compareAndExchangeObjectRelease, jdk_internal_misc_Unsafe, compareAndExchangeObjectRelease_name, compareAndExchangeObject_signature, F_R) \ + do_intrinsic(_compareAndSwapLong, jdk_internal_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_RN) \ + do_intrinsic(_compareAndExchangeLongVolatile, jdk_internal_misc_Unsafe, compareAndExchangeLongVolatile_name, compareAndExchangeLong_signature, F_RN) \ + do_intrinsic(_compareAndExchangeLongAcquire, jdk_internal_misc_Unsafe, compareAndExchangeLongAcquire_name, compareAndExchangeLong_signature, F_R) \ + do_intrinsic(_compareAndExchangeLongRelease, jdk_internal_misc_Unsafe, compareAndExchangeLongRelease_name, compareAndExchangeLong_signature, F_R) \ + do_intrinsic(_compareAndSwapInt, jdk_internal_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \ + do_intrinsic(_compareAndExchangeIntVolatile, jdk_internal_misc_Unsafe, compareAndExchangeIntVolatile_name, compareAndExchangeInt_signature, F_RN) \ + do_intrinsic(_compareAndExchangeIntAcquire, jdk_internal_misc_Unsafe, compareAndExchangeIntAcquire_name, compareAndExchangeInt_signature, F_R) \ + do_intrinsic(_compareAndExchangeIntRelease, jdk_internal_misc_Unsafe, compareAndExchangeIntRelease_name, compareAndExchangeInt_signature, F_R) \ + \ + do_intrinsic(_weakCompareAndSwapObject, jdk_internal_misc_Unsafe, weakCompareAndSwapObject_name, compareAndSwapObject_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapObjectAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapObjectAcquire_name, compareAndSwapObject_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapObjectRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapObjectRelease_name, compareAndSwapObject_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapLong, jdk_internal_misc_Unsafe, weakCompareAndSwapLong_name, compareAndSwapLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapLongAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapLongAcquire_name, compareAndSwapLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapLongRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapLongRelease_name, compareAndSwapLong_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapInt, jdk_internal_misc_Unsafe, weakCompareAndSwapInt_name, compareAndSwapInt_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapIntAcquire, jdk_internal_misc_Unsafe, weakCompareAndSwapIntAcquire_name, compareAndSwapInt_signature, F_R) \ + do_intrinsic(_weakCompareAndSwapIntRelease, jdk_internal_misc_Unsafe, weakCompareAndSwapIntRelease_name, compareAndSwapInt_signature, F_R) \ + \ + do_intrinsic(_putOrderedObject, jdk_internal_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_RN) \ + do_name( putOrderedObject_name, "putOrderedObject") \ + do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \ + do_intrinsic(_putOrderedLong, jdk_internal_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_RN) \ + do_name( putOrderedLong_name, "putOrderedLong") \ + do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \ + do_intrinsic(_putOrderedInt, jdk_internal_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_RN) \ + do_name( putOrderedInt_name, "putOrderedInt") \ + do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \ \ do_intrinsic(_getAndAddInt, jdk_internal_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \ do_name( getAndAddInt_name, "getAndAddInt") \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/codeCache.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1023,7 +1023,7 @@ // Keeps track of time spent for checking dependencies NOT_PRODUCT(static elapsedTimer dependentCheckTime;) -int CodeCache::mark_for_deoptimization(DepChange& changes) { +int CodeCache::mark_for_deoptimization(KlassDepChange& changes) { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); int number_of_marked_CodeBlobs = 0; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/codeCache.hpp --- a/hotspot/src/share/vm/code/codeCache.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/codeCache.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -72,7 +72,7 @@ // Solaris and BSD. class OopClosure; -class DepChange; +class KlassDepChange; class CodeCache : AllStatic { friend class VMStructs; @@ -223,7 +223,7 @@ // Deoptimization private: - static int mark_for_deoptimization(DepChange& changes); + static int mark_for_deoptimization(KlassDepChange& changes); #ifdef HOTSWAP static int mark_for_evol_deoptimization(instanceKlassHandle dependee); #endif // HOTSWAP diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/dependencies.hpp --- a/hotspot/src/share/vm/code/dependencies.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/dependencies.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -664,6 +664,8 @@ virtual bool is_klass_change() const { return false; } virtual bool is_call_site_change() const { return false; } + virtual void mark_for_deoptimization(nmethod* nm) = 0; + // Subclass casting with assertions. KlassDepChange* as_klass_change() { assert(is_klass_change(), "bad cast"); @@ -753,6 +755,10 @@ // What kind of DepChange is this? virtual bool is_klass_change() const { return true; } + virtual void mark_for_deoptimization(nmethod* nm) { + nm->mark_for_deoptimization(/*inc_recompile_counts=*/true); + } + Klass* new_type() { return _new_type(); } // involves_context(k) is true if k is new_type or any of the super types @@ -772,6 +778,10 @@ // What kind of DepChange is this? virtual bool is_call_site_change() const { return true; } + virtual void mark_for_deoptimization(nmethod* nm) { + nm->mark_for_deoptimization(/*inc_recompile_counts=*/false); + } + oop call_site() const { return _call_site(); } oop method_handle() const { return _method_handle(); } }; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/dependencyContext.cpp --- a/hotspot/src/share/vm/code/dependencyContext.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/dependencyContext.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -73,7 +73,7 @@ nm->print(); nm->print_dependencies(); } - nm->mark_for_deoptimization(); + changes.mark_for_deoptimization(nm); found++; } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -536,7 +536,7 @@ _has_method_handle_invokes = 0; _lazy_critical_native = 0; _has_wide_vectors = 0; - _marked_for_deoptimization = 0; + _mark_for_deoptimization_status = not_marked; _lock_count = 0; _stack_traversal_mark = 0; _unload_reported = false; // jvmti state @@ -1459,7 +1459,7 @@ SharedRuntime::get_handle_wrong_method_stub()); } - if (is_in_use()) { + if (is_in_use() && update_recompile_counts()) { // It's a true state change, so mark the method as decompiled. // Do it only for transition from alive. inc_decompile_count(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/nmethod.hpp --- a/hotspot/src/share/vm/code/nmethod.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/nmethod.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -107,6 +107,7 @@ // [Implicit Null Pointer exception table] // - implicit null table array +class DepChange; class Dependencies; class ExceptionHandlerTable; class ImplicitExceptionTable; @@ -188,7 +189,13 @@ bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock) bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper) - bool _marked_for_deoptimization; // Used for stack deoptimization + + enum MarkForDeoptimizationStatus { + not_marked, + deoptimize, + deoptimize_noupdate }; + + MarkForDeoptimizationStatus _mark_for_deoptimization_status; // Used for stack deoptimization // used by jvmti to track if an unload event has been posted for this nmethod. bool _unload_reported; @@ -462,8 +469,16 @@ void set_unloading_clock(unsigned char unloading_clock); unsigned char unloading_clock(); - bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; } - void mark_for_deoptimization() { _marked_for_deoptimization = true; } + bool is_marked_for_deoptimization() const { return _mark_for_deoptimization_status != not_marked; } + void mark_for_deoptimization(bool inc_recompile_counts = true) { + _mark_for_deoptimization_status = (inc_recompile_counts ? deoptimize : deoptimize_noupdate); + } + bool update_recompile_counts() const { + // Update recompile counts when either the update is explicitly requested (deoptimize) + // or the nmethod is not marked for deoptimization at all (not_marked). + // The latter happens during uncommon traps when deoptimized nmethod is made not entrant. + return _mark_for_deoptimization_status != deoptimize_noupdate; + } void make_unloaded(BoolObjectClosure* is_alive, oop cause); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/relocInfo.cpp --- a/hotspot/src/share/vm/code/relocInfo.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/relocInfo.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -457,49 +457,6 @@ return itr._rh; } -int32_t Relocation::runtime_address_to_index(address runtime_address) { - assert(!is_reloc_index((intptr_t)runtime_address), "must not look like an index"); - - if (runtime_address == NULL) return 0; - - StubCodeDesc* p = StubCodeDesc::desc_for(runtime_address); - if (p != NULL && p->begin() == runtime_address) { - assert(is_reloc_index(p->index()), "there must not be too many stubs"); - return (int32_t)p->index(); - } else { - // Known "miscellaneous" non-stub pointers: - // os::get_polling_page(), SafepointSynchronize::address_of_state() - if (PrintRelocations) { - tty->print_cr("random unregistered address in relocInfo: " INTPTR_FORMAT, p2i(runtime_address)); - } -#ifndef _LP64 - return (int32_t) (intptr_t)runtime_address; -#else - // didn't fit return non-index - return -1; -#endif /* _LP64 */ - } -} - - -address Relocation::index_to_runtime_address(int32_t index) { - if (index == 0) return NULL; - - if (is_reloc_index(index)) { - StubCodeDesc* p = StubCodeDesc::desc_for_index(index); - assert(p != NULL, "there must be a stub for this index"); - return p->begin(); - } else { -#ifndef _LP64 - // this only works on 32bit machines - return (address) ((intptr_t) index); -#else - fatal("Relocation::index_to_runtime_address, int32_t not pointer sized"); - return NULL; -#endif /* _LP64 */ - } -} - address Relocation::old_addr_for(address newa, const CodeBuffer* src, CodeBuffer* dest) { int sect = dest->section_index_of(newa); @@ -623,20 +580,13 @@ void external_word_Relocation::pack_data_to(CodeSection* dest) { short* p = (short*) dest->locs_end(); - int32_t index = runtime_address_to_index(_target); #ifndef _LP64 - p = pack_1_int_to(p, index); + p = pack_1_int_to(p, (int32_t) (intptr_t)_target); #else - if (is_reloc_index(index)) { - p = pack_2_ints_to(p, index, 0); - } else { - jlong t = (jlong) _target; - int32_t lo = low(t); - int32_t hi = high(t); - p = pack_2_ints_to(p, lo, hi); - DEBUG_ONLY(jlong t1 = jlong_from(hi, lo)); - assert(!is_reloc_index(t1) && (address) t1 == _target, "not symmetric"); - } + jlong t = (jlong) _target; + int32_t lo = low(t); + int32_t hi = high(t); + p = pack_2_ints_to(p, lo, hi); #endif /* _LP64 */ dest->set_locs_end((relocInfo*) p); } @@ -644,16 +594,12 @@ void external_word_Relocation::unpack_data() { #ifndef _LP64 - _target = index_to_runtime_address(unpack_1_int()); + _target = (address) (intptr_t)unpack_1_int(); #else int32_t lo, hi; unpack_2_ints(lo, hi); jlong t = jlong_from(hi, lo);; - if (is_reloc_index(t)) { - _target = index_to_runtime_address(t); - } else { - _target = (address) t; - } + _target = (address) t; #endif /* _LP64 */ } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/code/relocInfo.hpp --- a/hotspot/src/share/vm/code/relocInfo.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/code/relocInfo.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -707,10 +707,6 @@ assert(datalen()==0 || type()==relocInfo::none, "no data here"); } - static bool is_reloc_index(intptr_t index) { - return 0 < index && index < os::vm_page_size(); - } - protected: // Helper functions for pack_data_to() and unpack_data(). @@ -806,10 +802,6 @@ return base + byte_offset; } - // these convert between indexes and addresses in the runtime system - static int32_t runtime_address_to_index(address runtime_address); - static address index_to_runtime_address(int32_t index); - // helpers for mapping between old and new addresses after a move or resize address old_addr_for(address newa, const CodeBuffer* src, CodeBuffer* dest); address new_addr_for(address olda, const CodeBuffer* src, CodeBuffer* dest); @@ -1253,7 +1245,8 @@ // Some address looking values aren't safe to treat as relocations // and should just be treated as constants. static bool can_be_relocated(address target) { - return target != NULL && !is_reloc_index((intptr_t)target); + assert(target == NULL || (uintptr_t)target >= (uintptr_t)os::vm_page_size(), INTPTR_FORMAT, (intptr_t)target); + return target != NULL; } private: diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/compiler/compileBroker.cpp --- a/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -469,7 +469,6 @@ void CompileBroker::print_compile_queues(outputStream* st) { st->print_cr("Current compiles: "); MutexLocker locker(MethodCompileQueue_lock); - MutexLocker locker2(Threads_lock); char buf[2000]; int buflen = sizeof(buf); @@ -2152,18 +2151,33 @@ if (CITime) { int bytes_compiled = method->code_size() + task->num_inlined_bytecodes(); - JVMCI_ONLY(CompilerStatistics* stats = compiler(task->comp_level())->stats();) if (is_osr) { _t_osr_compilation.add(time); _sum_osr_bytes_compiled += bytes_compiled; - JVMCI_ONLY(stats->_osr.update(time, bytes_compiled);) } else { _t_standard_compilation.add(time); _sum_standard_bytes_compiled += method->code_size() + task->num_inlined_bytecodes(); - JVMCI_ONLY(stats->_standard.update(time, bytes_compiled);) } - JVMCI_ONLY(stats->_nmethods_size += code->total_size();) - JVMCI_ONLY(stats->_nmethods_code_size += code->insts_size();) + +#if INCLUDE_JVMCI + AbstractCompiler* comp = compiler(task->comp_level()); + if (comp) { + CompilerStatistics* stats = comp->stats(); + if (stats) { + if (is_osr) { + stats->_osr.update(time, bytes_compiled); + } else { + stats->_standard.update(time, bytes_compiled); + } + stats->_nmethods_size += code->total_size(); + stats->_nmethods_code_size += code->insts_size(); + } else { // if (!stats) + assert(false, "Compiler statistics object must exist"); + } + } else { // if (!comp) + assert(false, "Compiler object must exist"); + } +#endif // INCLUDE_JVMCI } if (UsePerfData) { @@ -2222,11 +2236,15 @@ #if INCLUDE_JVMCI void CompileBroker::print_times(AbstractCompiler* comp) { CompilerStatistics* stats = comp->stats(); - tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}", + if (stats) { + tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}", comp->name(), stats->bytes_per_second(), stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count, stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count, stats->_nmethods_size, stats->_nmethods_code_size); + } else { // if (!stats) + assert(false, "Compiler statistics object must exist"); + } comp->print_timers(); } #endif // INCLUDE_JVMCI @@ -2260,17 +2278,21 @@ } CompilerStatistics* stats = comp->stats(); - standard_compilation.add(stats->_standard._time); - osr_compilation.add(stats->_osr._time); + if (stats) { + standard_compilation.add(stats->_standard._time); + osr_compilation.add(stats->_osr._time); - standard_bytes_compiled += stats->_standard._bytes; - osr_bytes_compiled += stats->_osr._bytes; + standard_bytes_compiled += stats->_standard._bytes; + osr_bytes_compiled += stats->_osr._bytes; - standard_compile_count += stats->_standard._count; - osr_compile_count += stats->_osr._count; + standard_compile_count += stats->_standard._count; + osr_compile_count += stats->_osr._count; - nmethods_size += stats->_nmethods_size; - nmethods_code_size += stats->_nmethods_code_size; + nmethods_size += stats->_nmethods_size; + nmethods_code_size += stats->_nmethods_code_size; + } else { // if (!stats) + assert(false, "Compiler statistics object must exist"); + } if (per_compiler) { print_times(comp); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/cms/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -615,7 +615,7 @@ : DefNewGeneration(rs, initial_byte_size, "PCopy"), _overflow_list(NULL), _is_alive_closure(this), - _plab_stats(YoungPLABSize, PLABWeight) + _plab_stats("Young", YoungPLABSize, PLABWeight) { NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) NOT_PRODUCT(_num_par_pushes = 0;) @@ -1008,9 +1008,7 @@ from()->set_concurrent_iteration_safe_limit(from()->top()); to()->set_concurrent_iteration_safe_limit(to()->top()); - if (ResizePLAB) { - plab_stats()->adjust_desired_plab_sz(); - } + plab_stats()->adjust_desired_plab_sz(); TASKQUEUE_STATS_ONLY(thread_state_set.print_termination_stats()); TASKQUEUE_STATS_ONLY(thread_state_set.print_taskqueue_stats()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,19 +36,19 @@ { // Ergonomically select initial concurrent refinement parameters if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, (intx)ParallelGCThreads); + FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, ParallelGCThreads); } set_green_zone(G1ConcRefinementGreenZone); if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); } - set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); + set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); } - set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); + set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); } ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,11 +61,11 @@ * 2) green = 0. Means no caching. Can be a good way to minimize the * amount of time spent updating rsets during a collection. */ - int _green_zone; - int _yellow_zone; - int _red_zone; + size_t _green_zone; + size_t _yellow_zone; + size_t _red_zone; - int _thread_threshold_step; + size_t _thread_threshold_step; // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; @@ -100,17 +100,17 @@ void print_worker_threads_on(outputStream* st) const; - void set_green_zone(int x) { _green_zone = x; } - void set_yellow_zone(int x) { _yellow_zone = x; } - void set_red_zone(int x) { _red_zone = x; } + void set_green_zone(size_t x) { _green_zone = x; } + void set_yellow_zone(size_t x) { _yellow_zone = x; } + void set_red_zone(size_t x) { _red_zone = x; } - int green_zone() const { return _green_zone; } - int yellow_zone() const { return _yellow_zone; } - int red_zone() const { return _red_zone; } + size_t green_zone() const { return _green_zone; } + size_t yellow_zone() const { return _yellow_zone; } + size_t red_zone() const { return _red_zone; } uint worker_thread_num() const { return _n_worker_threads; } - int thread_threshold_step() const { return _thread_threshold_step; } + size_t thread_threshold_step() const { return _thread_threshold_step; } G1HotCardCache* hot_card_cache() { return &_hot_card_cache; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -67,10 +67,12 @@ void ConcurrentG1RefineThread::initialize() { // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); + _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), + cg1r()->yellow_zone()); // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = MAX2(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); + _deactivation_threshold = + MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), + cg1r()->green_zone()); } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -127,14 +129,14 @@ } DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - log_debug(gc, refine)("Activated %d, on threshold: %d, current: %d", + log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, _worker_id, _threshold, dcqs.completed_buffers_num()); { SuspendibleThreadSetJoiner sts_join; do { - int curr_buffer_num = (int)dcqs.completed_buffers_num(); + size_t curr_buffer_num = dcqs.completed_buffers_num(); // If the number of the buffers falls down into the yellow zone, // that means that the transition period after the evacuation pause has ended. if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { @@ -151,7 +153,7 @@ false /* during_pause */)); deactivate(); - log_debug(gc, refine)("Deactivated %d, off threshold: %d, current: %d", + log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, _worker_id, _deactivation_threshold, dcqs.completed_buffers_num()); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,11 +53,11 @@ // The closure applied to completed log buffers. CardTableEntryClosure* _refine_closure; - int _thread_threshold_step; + size_t _thread_threshold_step; // This thread activation threshold - int _threshold; + size_t _threshold; // This thread deactivation threshold - int _deactivation_threshold; + size_t _deactivation_threshold; void wait_for_completed_buffers(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -207,22 +207,24 @@ } -BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { +BufferNode* DirtyCardQueueSet::get_completed_buffer(size_t stop_at) { BufferNode* nd = NULL; MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - if ((int)_n_completed_buffers <= stop_at) { + if (_n_completed_buffers <= stop_at) { _process_completed = false; return NULL; } if (_completed_buffers_head != NULL) { nd = _completed_buffers_head; + assert(_n_completed_buffers > 0, "Invariant"); _completed_buffers_head = nd->next(); - if (_completed_buffers_head == NULL) + _n_completed_buffers--; + if (_completed_buffers_head == NULL) { + assert(_n_completed_buffers == 0, "Invariant"); _completed_buffers_tail = NULL; - _n_completed_buffers--; - assert(_n_completed_buffers >= 0, "Invariant"); + } } DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); return nd; @@ -230,7 +232,7 @@ bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, - int stop_at, + size_t stop_at, bool during_pause) { assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); BufferNode* nd = get_completed_buffer(stop_at); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -134,10 +134,10 @@ // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, - int stop_at, + size_t stop_at, bool during_pause); - BufferNode* get_completed_buffer(int stop_at); + BufferNode* get_completed_buffer(size_t stop_at); // Applies the current closure to all completed buffers, // non-consumptively. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1400,7 +1400,6 @@ JavaThread::dirty_card_queue_set().abandon_logs(); assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty"); - _young_list->reset_sampled_info(); // At this point there should be no regions in the // entire heap tagged as young. assert(check_young_list_empty(true /* check_heap */), @@ -1761,8 +1760,8 @@ _young_list(new YoungList(this)), _gc_time_stamp(0), _summary_bytes_used(0), - _survivor_evac_stats(YoungPLABSize, PLABWeight), - _old_evac_stats(OldPLABSize, PLABWeight), + _survivor_evac_stats("Young", YoungPLABSize, PLABWeight), + _old_evac_stats("Old", OldPLABSize, PLABWeight), _expand_heap_after_alloc_failure(true), _old_marking_cycles_started(0), _old_marking_cycles_completed(0), @@ -1985,8 +1984,8 @@ JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl, DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, - concurrent_g1_refine()->yellow_zone(), - concurrent_g1_refine()->red_zone(), + (int)concurrent_g1_refine()->yellow_zone(), + (int)concurrent_g1_refine()->red_zone(), Shared_DirtyCardQ_lock, NULL, // fl_owner true); // init_free_ids @@ -3385,13 +3384,15 @@ g1_policy()->clear_collection_set(); + record_obj_copy_mem_stats(); + _survivor_evac_stats.adjust_desired_plab_sz(); + _old_evac_stats.adjust_desired_plab_sz(); + // Start a new incremental collection set for the next pause. g1_policy()->start_incremental_cset_building(); clear_cset_fast_test(); - _young_list->reset_sampled_info(); - // Don't check the whole heap at this point as the // GC alloc regions from this pause have been tagged // as survivors and moved on to the survivor list. @@ -4398,6 +4399,8 @@ { } void work(uint worker_id) { + G1GCParPhaseTimesTracker x(_g1h->g1_policy()->phase_times(), G1GCPhaseTimes::PreserveCMReferents, worker_id); + ResourceMark rm; HandleMark hm; @@ -4461,13 +4464,8 @@ g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0); } -// Weak Reference processing during an evacuation pause (part 1). -void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { - double ref_proc_start = os::elapsedTime(); - - ReferenceProcessor* rp = _ref_processor_stw; - assert(rp->discovery_enabled(), "should have been enabled"); - +void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { + double preserve_cm_referents_start = os::elapsedTime(); // Any reference objects, in the collection set, that were 'discovered' // by the CM ref processor should have already been copied (either by // applying the external root copy closure to the discovered lists, or @@ -4495,9 +4493,18 @@ per_thread_states, no_of_gc_workers, _task_queues); - workers()->run_task(&keep_cm_referents); + g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0); +} + +// Weak Reference processing during an evacuation pause (part 1). +void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { + double ref_proc_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(rp->discovery_enabled(), "should have been enabled"); + // Closure to test whether a referent is alive. G1STWIsAliveClosure is_alive(this); @@ -4529,6 +4536,8 @@ NULL, _gc_timer_stw); } else { + uint no_of_gc_workers = workers()->active_workers(); + // Parallel reference processing assert(rp->num_q() == no_of_gc_workers, "sanity"); assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); @@ -4586,6 +4595,12 @@ g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } +void G1CollectedHeap::merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states) { + double merge_pss_time_start = os::elapsedTime(); + per_thread_states->flush(); + g1_policy()->phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0); +} + void G1CollectedHeap::pre_evacuate_collection_set() { _expand_heap_after_alloc_failure = true; _evacuation_failed = false; @@ -4644,6 +4659,7 @@ // objects (and their reachable sub-graphs) that were // not copied during the pause. if (g1_policy()->should_process_references()) { + preserve_cm_referents(per_thread_states); process_discovered_references(per_thread_states); } else { ref_processor_stw()->verify_no_references_recorded(); @@ -4687,12 +4703,7 @@ _allocator->release_gc_alloc_regions(evacuation_info); - per_thread_states->flush(); - - record_obj_copy_mem_stats(); - - _survivor_evac_stats.adjust_desired_plab_sz(); - _old_evac_stats.adjust_desired_plab_sz(); + merge_per_thread_state_info(per_thread_states); // Reset and re-enable the hot card cache. // Note the counts for the cards in the regions in the @@ -5188,8 +5199,8 @@ bool success() { return _success; } }; -bool G1CollectedHeap::check_young_list_empty(bool check_heap, bool check_sample) { - bool ret = _young_list->check_list_empty(check_sample); +bool G1CollectedHeap::check_young_list_empty(bool check_heap) { + bool ret = _young_list->check_list_empty(); if (check_heap) { NoYoungRegionsClosure closure; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -511,6 +511,9 @@ // allocated block, or else "NULL". HeapWord* expand_and_allocate(size_t word_size, AllocationContext_t context); + // Preserve any referents discovered by concurrent marking that have not yet been + // copied by the STW pause. + void preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states); // Process any reference objects discovered during // an incremental evacuation pause. void process_discovered_references(G1ParScanThreadStateSet* per_thread_states); @@ -519,6 +522,9 @@ // after processing. void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states); + // Merges the information gathered on a per-thread basis for all worker threads + // during GC into global variables. + void merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states); public: WorkGang* workers() const { return _workers; } @@ -1333,8 +1339,7 @@ return _young_list->check_list_well_formed(); } - bool check_young_list_empty(bool check_heap, - bool check_sample = true); + bool check_young_list_empty(bool check_heap); // *** Stuff related to concurrent marking. It's not clear to me that so // many of these need to be public. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -787,10 +787,9 @@ return survivor_regions_evac_time; } -void G1CollectorPolicy::revise_young_list_target_length_if_necessary() { +void G1CollectorPolicy::revise_young_list_target_length_if_necessary(size_t rs_lengths) { guarantee( adaptive_young_list_length(), "should not call this otherwise" ); - size_t rs_lengths = _g1->young_list()->sampled_rs_lengths(); if (rs_lengths > _rs_lengths_prediction) { // add 10% to avoid having to recalculate often size_t rs_lengths_prediction = rs_lengths * 1100 / 1000; @@ -1118,14 +1117,15 @@ _short_lived_surv_rate_group->start_adding_regions(); // Do that for any other surv rate groups + double scan_hcc_time_ms = ConcurrentG1Refine::hot_card_cache_enabled() ? average_time_ms(G1GCPhaseTimes::ScanHCC) : 0.0; + if (update_stats) { double cost_per_card_ms = 0.0; - double cost_scan_hcc = average_time_ms(G1GCPhaseTimes::ScanHCC); if (_pending_cards > 0) { - cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards; + cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms) / (double) _pending_cards; _cost_per_card_ms_seq->add(cost_per_card_ms); } - _cost_scan_hcc_seq->add(cost_scan_hcc); + _cost_scan_hcc_seq->add(scan_hcc_time_ms); double cost_per_entry_ms = 0.0; if (cards_scanned > 10) { @@ -1215,8 +1215,6 @@ // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; - double scan_hcc_time_ms = average_time_ms(G1GCPhaseTimes::ScanHCC); - if (update_rs_time_goal_ms < scan_hcc_time_ms) { log_debug(gc, ergo, refine)("Adjust concurrent refinement thresholds (scanning the HCC expected to take longer than Update RS time goal)." "Update RS time goal: %1.2fms Scan HCC time: %1.2fms", @@ -1302,12 +1300,12 @@ const int k_gy = 3, k_gr = 6; const double inc_k = 1.1, dec_k = 0.9; - int g = cg1r->green_zone(); + size_t g = cg1r->green_zone(); if (update_rs_time > goal_ms) { - g = (int)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. + g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. } else { if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { - g = (int)MAX2(g * inc_k, g + 1.0); + g = (size_t)MAX2(g * inc_k, g + 1.0); } } // Change the refinement threads params @@ -1316,15 +1314,15 @@ cg1r->set_red_zone(g * k_gr); cg1r->reinitialize_threads(); - int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * _predictor.sigma()), 1); - int processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, + size_t processing_threshold_delta = MAX2(cg1r->green_zone() * _predictor.sigma(), 1); + size_t processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, cg1r->yellow_zone()); // Change the barrier params - dcqs.set_process_completed_threshold(processing_threshold); - dcqs.set_max_completed_queue(cg1r->red_zone()); + dcqs.set_process_completed_threshold((int)processing_threshold); + dcqs.set_max_completed_queue((int)cg1r->red_zone()); } - int curr_queue_size = dcqs.completed_buffers_num(); + size_t curr_queue_size = dcqs.completed_buffers_num(); if (curr_queue_size >= cg1r->yellow_zone()) { dcqs.set_completed_queue_padding(curr_queue_size); } else { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -471,7 +471,7 @@ // Check the current value of the young list RSet lengths and // compare it against the last prediction. If the current value is // higher, recalculate the young list target length prediction. - void revise_young_list_target_length_if_necessary(); + void revise_young_list_target_length_if_necessary(size_t rs_lengths); // This should be called after the heap is resized. void record_new_heap_size(uint new_number_of_regions); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1097,7 +1097,7 @@ reset_marking_state(); } else { { - GCTraceTime(Debug, gc) trace("GC Aggregate Data", g1h->gc_timer_cm()); + GCTraceTime(Debug, gc) trace("Aggregate Data", g1h->gc_timer_cm()); // Aggregate the per-task counting data that we have accumulated // while marking. @@ -2018,7 +2018,7 @@ // Inner scope to exclude the cleaning of the string and symbol // tables from the displayed time. { - GCTraceTime(Debug, gc) trace("GC Ref Proc", g1h->gc_timer_cm()); + GCTraceTime(Debug, gc) trace("Reference Processing", g1h->gc_timer_cm()); ReferenceProcessor* rp = g1h->ref_processor_cm(); @@ -2271,7 +2271,7 @@ SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); guarantee(has_overflown() || satb_mq_set.completed_buffers_num() == 0, - "Invariant: has_overflown = %s, num buffers = %d", + "Invariant: has_overflown = %s, num buffers = " SIZE_FORMAT, BOOL_TO_STR(has_overflown()), satb_mq_set.completed_buffers_num()); @@ -2702,11 +2702,8 @@ }; static ReferenceProcessor* get_cm_oop_closure_ref_processor(G1CollectedHeap* g1h) { - ReferenceProcessor* result = NULL; - if (G1UseConcMarkReferenceProcessing) { - result = g1h->ref_processor_cm(); - assert(result != NULL, "should not be NULL"); - } + ReferenceProcessor* result = g1h->ref_processor_cm(); + assert(result != NULL, "CM reference processor should not be NULL"); return result; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1EvacStats.cpp --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,15 +29,26 @@ #include "logging/log.hpp" #include "trace/tracing.hpp" +void G1EvacStats::log_plab_allocation() { + PLABStats::log_plab_allocation(); + log_debug(gc, plab)("%s other allocation: " + "region end waste: " SIZE_FORMAT "B, " + "regions filled: %u, " + "direct allocated: " SIZE_FORMAT "B, " + "failure used: " SIZE_FORMAT "B, " + "failure wasted: " SIZE_FORMAT "B", + _description, + _region_end_waste * HeapWordSize, + _regions_filled, + _direct_allocated * HeapWordSize, + _failure_used * HeapWordSize, + _failure_waste * HeapWordSize); +} + void G1EvacStats::adjust_desired_plab_sz() { + log_plab_allocation(); + if (!ResizePLAB) { - log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " - "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " - "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " - "regions filled = %u direct_allocated = " SIZE_FORMAT " " - "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") ", - _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, - _regions_filled, _direct_allocated, _failure_used, _failure_waste); // Clear accumulators for next round. reset(); return; @@ -107,18 +118,19 @@ // Latch the result _desired_net_plab_sz = plab_sz; - log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " - "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " - "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " - "regions filled = %u direct_allocated = " SIZE_FORMAT " " - "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") " - " (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ")", - _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, - _regions_filled, _direct_allocated, _failure_used, _failure_waste, - cur_plab_sz, plab_sz); - + log_sizing(cur_plab_sz, plab_sz); // Clear accumulators for next round. reset(); } +G1EvacStats::G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt) : + PLABStats(description, desired_plab_sz_, wt), + _region_end_waste(0), + _regions_filled(0), + _direct_allocated(0), + _failure_used(0), + _failure_waste(0) { +} + + G1EvacStats::~G1EvacStats() { } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1EvacStats.hpp --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,20 +51,15 @@ _failure_waste = 0; } + virtual void log_plab_allocation(); + public: - G1EvacStats(size_t desired_plab_sz_, unsigned wt) : PLABStats(desired_plab_sz_, wt), - _region_end_waste(0), _regions_filled(0), _direct_allocated(0), - _failure_used(0), _failure_waste(0) { - } + G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt); + + ~G1EvacStats(); virtual void adjust_desired_plab_sz(); - size_t allocated() const { return _allocated; } - size_t wasted() const { return _wasted; } - size_t unused() const { return _unused; } - size_t used() const { return allocated() - (wasted() + unused()); } - size_t undo_wasted() const { return _undo_wasted; } - uint regions_filled() const { return _regions_filled; } size_t region_end_waste() const { return _region_end_waste; } size_t direct_allocated() const { return _direct_allocated; } @@ -77,8 +72,6 @@ inline void add_direct_allocated(size_t value); inline void add_region_end_waste(size_t value); inline void add_failure_used_and_waste(size_t used, size_t waste); - - ~G1EvacStats(); }; #endif // SHARE_VM_GC_G1_G1EVACSTATS_HPP diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,107 +28,70 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/workerDataArray.inline.hpp" -#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" #include "runtime/os.hpp" -// Helper class for avoiding interleaved logging -class LineBuffer: public StackObj { - -private: - static const int BUFFER_LEN = 1024; - static const int INDENT_CHARS = 3; - char _buffer[BUFFER_LEN]; - int _indent_level; - int _cur; - - void vappend(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) { - int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); - if (res != -1) { - _cur += res; - } else { - DEBUG_ONLY(warning("buffer too small in LineBuffer");) - _buffer[BUFFER_LEN -1] = 0; - _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again - } - } - -public: - explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { - for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { - _buffer[_cur] = ' '; - } - } - -#ifndef PRODUCT - ~LineBuffer() { - assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); - } -#endif - - void append(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) { - va_list ap; - va_start(ap, format); - vappend(format, ap); - va_end(ap); - } - - const char* to_string() { - _cur = _indent_level * INDENT_CHARS; - return _buffer; - } -}; - -static const char* Indents[4] = {"", " ", " ", " "}; +static const char* Indents[5] = {"", " ", " ", " ", " "}; G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads) { assert(max_gc_threads > 0, "Must have some GC threads"); - _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start:", false, 2); - _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning:", true, 2); + _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start (ms):"); + _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning (ms):"); // Root scanning phases - _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots:", true, 3); - _gc_par_phases[StringTableRoots] = new WorkerDataArray(max_gc_threads, "StringTable Roots:", true, 3); - _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots:", true, 3); - _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots:", true, 3); - _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots:", true, 3); - _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray(max_gc_threads, "FlatProfiler Roots:", true, 3); - _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots:", true, 3); - _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots:", true, 3); - _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots:", true, 3); - _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots:", true, 3); - _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots:", true, 3); - _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD:", true, 3); - _gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots:", true, 3); - _gc_par_phases[SATBFiltering] = new WorkerDataArray(max_gc_threads, "SATB Filtering:", true, 3); + _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots (ms):"); + _gc_par_phases[StringTableRoots] = new WorkerDataArray(max_gc_threads, "StringTable Roots (ms):"); + _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots (ms):"); + _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots (ms):"); + _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots (ms):"); + _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray(max_gc_threads, "FlatProfiler Roots (ms):"); + _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots (ms):"); + _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots (ms):"); + _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots (ms):"); + _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots (ms):"); + _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots (ms):"); + _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD (ms):"); + _gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots (ms):"); + _gc_par_phases[SATBFiltering] = new WorkerDataArray(max_gc_threads, "SATB Filtering (ms):"); - _gc_par_phases[UpdateRS] = new WorkerDataArray(max_gc_threads, "Update RS:", true, 2); - _gc_par_phases[ScanHCC] = new WorkerDataArray(max_gc_threads, "Scan HCC:", true, 3); - _gc_par_phases[ScanHCC]->set_enabled(ConcurrentG1Refine::hot_card_cache_enabled()); - _gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS:", true, 2); - _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning:", true, 2); - _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy:", true, 2); - _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination:", true, 2); - _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total:", true, 2); - _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End:", false, 2); - _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other:", true, 2); + _gc_par_phases[UpdateRS] = new WorkerDataArray(max_gc_threads, "Update RS (ms):"); + if (ConcurrentG1Refine::hot_card_cache_enabled()) { + _gc_par_phases[ScanHCC] = new WorkerDataArray(max_gc_threads, "Scan HCC (ms):"); + } else { + _gc_par_phases[ScanHCC] = NULL; + } + _gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS (ms):"); + _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning (ms):"); + _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy (ms):"); + _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination (ms):"); + _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total (ms):"); + _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End (ms):"); + _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other (ms):"); - _update_rs_processed_buffers = new WorkerDataArray(max_gc_threads, "Processed Buffers:", true, 3); + _update_rs_processed_buffers = new WorkerDataArray(max_gc_threads, "Processed Buffers:"); _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers); - _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:", true, 3); + _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:"); _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts); - _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup:", true, 2); - _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup:", true, 2); + if (UseStringDeduplication) { + _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup (ms):"); + _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup (ms):"); + } else { + _gc_par_phases[StringDedupQueueFixup] = NULL; + _gc_par_phases[StringDedupTableFixup] = NULL; + } - _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty:", true, 3); - _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:", true, 3); + _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty (ms):"); + _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:"); _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); + + _gc_par_phases[PreserveCMReferents] = new WorkerDataArray(max_gc_threads, "Parallel Preserve CM Refs (ms):"); } void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { @@ -140,11 +103,10 @@ _external_accounted_time_ms = 0.0; for (int i = 0; i < GCParPhasesSentinel; i++) { - _gc_par_phases[i]->reset(); + if (_gc_par_phases[i] != NULL) { + _gc_par_phases[i]->reset(); + } } - - _gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled()); - _gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled()); } void G1GCPhaseTimes::note_gc_end() { @@ -166,45 +128,12 @@ } for (int i = 0; i < GCParPhasesSentinel; i++) { - _gc_par_phases[i]->verify(_active_gc_threads); + if (_gc_par_phases[i] != NULL) { + _gc_par_phases[i]->verify(_active_gc_threads); + } } } -void G1GCPhaseTimes::print_stats(const char* indent, const char* str, double value) { - log_debug(gc, phases)("%s%s: %.1lf ms", indent, str, value); -} - -double G1GCPhaseTimes::accounted_time_ms() { - // First subtract any externally accounted time - double misc_time_ms = _external_accounted_time_ms; - - // Subtract the root region scanning wait time. It's initialized to - // zero at the start of the pause. - misc_time_ms += _root_region_scan_wait_time_ms; - - misc_time_ms += _cur_collection_par_time_ms; - - // Now subtract the time taken to fix up roots in generated code - misc_time_ms += _cur_collection_code_root_fixup_time_ms; - - // Strong code root purge time - misc_time_ms += _cur_strong_code_root_purge_time_ms; - - if (G1StringDedup::is_enabled()) { - // String dedup fixup time - misc_time_ms += _cur_string_dedup_fixup_time_ms; - } - - // Subtract the time taken to clean the card table from the - // current value of "other time" - misc_time_ms += _cur_clear_ct_time_ms; - - // Remove expand heap time from "other time" - misc_time_ms += _cur_expand_heap_time_ms; - - return misc_time_ms; -} - // record the time a phase took in seconds void G1GCPhaseTimes::record_time_secs(GCParPhases phase, uint worker_i, double secs) { _gc_par_phases[phase]->set(worker_i, secs); @@ -224,193 +153,144 @@ return _gc_par_phases[phase]->average(_active_gc_threads) * 1000.0; } -double G1GCPhaseTimes::get_time_ms(GCParPhases phase, uint worker_i) { - return _gc_par_phases[phase]->get(worker_i) * 1000.0; -} - -double G1GCPhaseTimes::sum_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->sum(_active_gc_threads) * 1000.0; -} - -double G1GCPhaseTimes::min_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->minimum(_active_gc_threads) * 1000.0; -} - -double G1GCPhaseTimes::max_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->maximum(_active_gc_threads) * 1000.0; -} - -size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_i) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->get(worker_i); -} - size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) { assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); return _gc_par_phases[phase]->thread_work_items()->sum(_active_gc_threads); } -double G1GCPhaseTimes::average_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->average(_active_gc_threads); +template +void G1GCPhaseTimes::details(T* phase, const char* indent) { + LogHandle(gc, phases, task) log; + if (log.is_level(LogLevel::Trace)) { + outputStream* trace_out = log.trace_stream(); + trace_out->print("%s", indent); + phase->print_details_on(trace_out, _active_gc_threads); + } } -size_t G1GCPhaseTimes::min_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->minimum(_active_gc_threads); -} +void G1GCPhaseTimes::log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum) { + out->print("%s", Indents[indent]); + phase->print_summary_on(out, _active_gc_threads, print_sum); + details(phase, Indents[indent]); -size_t G1GCPhaseTimes::max_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->maximum(_active_gc_threads); + WorkerDataArray* work_items = phase->thread_work_items(); + if (work_items != NULL) { + out->print("%s", Indents[indent + 1]); + work_items->print_summary_on(out, _active_gc_threads, true); + details(work_items, Indents[indent + 1]); + } } -class G1GCParPhasePrinter : public StackObj { - G1GCPhaseTimes* _phase_times; - public: - G1GCParPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {} - - void print(G1GCPhaseTimes::GCParPhases phase_id) { - WorkerDataArray* phase = _phase_times->_gc_par_phases[phase_id]; - - if (phase->_length == 1) { - print_single_length(phase_id, phase); - } else { - print_multi_length(phase_id, phase); - } +void G1GCPhaseTimes::debug_phase(WorkerDataArray* phase) { + LogHandle(gc, phases) log; + if (log.is_level(LogLevel::Debug)) { + ResourceMark rm; + log_phase(phase, 2, log.debug_stream(), true); } - +} - private: - void print_single_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* phase) { - // No need for min, max, average and sum for only one worker - log_debug(gc, phases)("%s%s: %.1lf", Indents[phase->_indent_level], phase->_title, _phase_times->get_time_ms(phase_id, 0)); - - WorkerDataArray* work_items = phase->_thread_work_items; - if (work_items != NULL) { - log_debug(gc, phases)("%s%s: " SIZE_FORMAT, Indents[work_items->_indent_level], work_items->_title, _phase_times->sum_thread_work_items(phase_id)); - } +void G1GCPhaseTimes::trace_phase(WorkerDataArray* phase, bool print_sum) { + LogHandle(gc, phases) log; + if (log.is_level(LogLevel::Trace)) { + ResourceMark rm; + log_phase(phase, 3, log.trace_stream(), print_sum); } +} - void print_time_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id) { - if (log_is_enabled(Trace, gc)) { - LineBuffer buf(0); - uint active_length = _phase_times->_active_gc_threads; - for (uint i = 0; i < active_length; ++i) { - buf.append(" %4.1lf", _phase_times->get_time_ms(phase_id, i)); - } - const char* line = buf.to_string(); - log_trace(gc, phases)("%s%-25s%s", indent, "", line); - } - } +#define PHASE_DOUBLE_FORMAT "%s%s: %.1lfms" +#define PHASE_SIZE_FORMAT "%s%s: " SIZE_FORMAT - void print_count_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* thread_work_items) { - if (log_is_enabled(Trace, gc)) { - LineBuffer buf(0); - uint active_length = _phase_times->_active_gc_threads; - for (uint i = 0; i < active_length; ++i) { - buf.append(" " SIZE_FORMAT, _phase_times->get_thread_work_item(phase_id, i)); - } - const char* line = buf.to_string(); - log_trace(gc, phases)("%s%-25s%s", indent, "", line); - } - } +#define info_line(str, value) \ + log_info(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[1], str, value); - void print_thread_work_items(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* thread_work_items) { - const char* indent = Indents[thread_work_items->_indent_level]; - - assert(thread_work_items->_print_sum, "%s does not have print sum true even though it is a count", thread_work_items->_title); +#define debug_line(str, value) \ + log_debug(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[2], str, value); - log_debug(gc, phases)("%s%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT, - indent, thread_work_items->_title, - _phase_times->min_thread_work_items(phase_id), _phase_times->average_thread_work_items(phase_id), _phase_times->max_thread_work_items(phase_id), - _phase_times->max_thread_work_items(phase_id) - _phase_times->min_thread_work_items(phase_id), _phase_times->sum_thread_work_items(phase_id)); +#define trace_line(str, value) \ + log_trace(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[3], str, value); - print_count_values(indent, phase_id, thread_work_items); - } - - void print_multi_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* phase) { - const char* indent = Indents[phase->_indent_level]; +#define trace_line_sz(str, value) \ + log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); - if (phase->_print_sum) { - log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf, Sum: %4.1lf", - indent, phase->_title, - _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), - _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id), _phase_times->sum_time_ms(phase_id)); - } else { - log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", - indent, phase->_title, - _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), - _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id)); - } +#define trace_line_ms(str, value) \ + log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); - print_time_values(indent, phase_id); - - if (phase->_thread_work_items != NULL) { - print_thread_work_items(phase_id, phase->_thread_work_items); - } - } -}; +#define info_line_and_account(str, value) \ + info_line(str, value); \ + accounted_time_ms += value; void G1GCPhaseTimes::print() { note_gc_end(); - G1GCParPhasePrinter par_phase_printer(this); - + double accounted_time_ms = _external_accounted_time_ms; if (_root_region_scan_wait_time_ms > 0.0) { - print_stats(Indents[1], "Root Region Scan Waiting", _root_region_scan_wait_time_ms); - } - - print_stats(Indents[1], "Parallel Time", _cur_collection_par_time_ms); - for (int i = 0; i <= GCMainParPhasesLast; i++) { - par_phase_printer.print((GCParPhases) i); + info_line_and_account("Root Region Scan Waiting", _root_region_scan_wait_time_ms); } - print_stats(Indents[1], "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); - print_stats(Indents[1], "Code Root Purge", _cur_strong_code_root_purge_time_ms); + info_line_and_account("Evacuate Collection Set", _cur_collection_par_time_ms); + trace_phase(_gc_par_phases[GCWorkerStart], false); + debug_phase(_gc_par_phases[ExtRootScan]); + for (int i = ThreadRoots; i <= SATBFiltering; i++) { + trace_phase(_gc_par_phases[i]); + } + debug_phase(_gc_par_phases[UpdateRS]); + if (ConcurrentG1Refine::hot_card_cache_enabled()) { + trace_phase(_gc_par_phases[ScanHCC]); + } + debug_phase(_gc_par_phases[ScanRS]); + debug_phase(_gc_par_phases[CodeRoots]); + debug_phase(_gc_par_phases[ObjCopy]); + debug_phase(_gc_par_phases[Termination]); + debug_phase(_gc_par_phases[Other]); + debug_phase(_gc_par_phases[GCWorkerTotal]); + trace_phase(_gc_par_phases[GCWorkerEnd], false); + + info_line_and_account("Code Roots", _cur_collection_code_root_fixup_time_ms + _cur_strong_code_root_purge_time_ms); + debug_line("Code Roots Fixup", _cur_collection_code_root_fixup_time_ms); + debug_line("Code Roots Purge", _cur_strong_code_root_purge_time_ms); + if (G1StringDedup::is_enabled()) { - print_stats(Indents[1], "String Dedup Fixup", _cur_string_dedup_fixup_time_ms); - for (int i = StringDedupPhasesFirst; i <= StringDedupPhasesLast; i++) { - par_phase_printer.print((GCParPhases) i); - } + info_line_and_account("String Dedup Fixup", _cur_string_dedup_fixup_time_ms); + debug_phase(_gc_par_phases[StringDedupQueueFixup]); + debug_phase(_gc_par_phases[StringDedupTableFixup]); } - print_stats(Indents[1], "Clear CT", _cur_clear_ct_time_ms); - print_stats(Indents[1], "Expand Heap After Collection", _cur_expand_heap_time_ms); - double misc_time_ms = _gc_pause_time_ms - accounted_time_ms(); - print_stats(Indents[1], "Other", misc_time_ms); + info_line_and_account("Clear Card Table", _cur_clear_ct_time_ms); + info_line_and_account("Expand Heap After Collection", _cur_expand_heap_time_ms); + + double free_cset_time = _recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms; + info_line_and_account("Free Collection Set", free_cset_time); + debug_line("Young Free Collection Set", _recorded_young_free_cset_time_ms); + debug_line("Non-Young Free Collection Set", _recorded_non_young_free_cset_time_ms); + info_line_and_account("Merge Per-Thread State", _recorded_merge_pss_time_ms); + + info_line("Other", _gc_pause_time_ms - accounted_time_ms); if (_cur_verify_before_time_ms > 0.0) { - print_stats(Indents[2], "Verify Before", _cur_verify_before_time_ms); + debug_line("Verify Before", _cur_verify_before_time_ms); } if (G1CollectedHeap::heap()->evacuation_failed()) { double evac_fail_handling = _cur_evac_fail_recalc_used + _cur_evac_fail_remove_self_forwards + _cur_evac_fail_restore_remsets; - print_stats(Indents[2], "Evacuation Failure", evac_fail_handling); - log_trace(gc, phases)("%sRecalculate Used: %.1lf ms", Indents[3], _cur_evac_fail_recalc_used); - log_trace(gc, phases)("%sRemove Self Forwards: %.1lf ms", Indents[3], _cur_evac_fail_remove_self_forwards); - log_trace(gc, phases)("%sRestore RemSet: %.1lf ms", Indents[3], _cur_evac_fail_restore_remsets); + debug_line("Evacuation Failure", evac_fail_handling); + trace_line("Recalculate Used", _cur_evac_fail_recalc_used); + trace_line("Remove Self Forwards",_cur_evac_fail_remove_self_forwards); + trace_line("Restore RemSet", _cur_evac_fail_restore_remsets); } - print_stats(Indents[2], "Choose CSet", - (_recorded_young_cset_choice_time_ms + - _recorded_non_young_cset_choice_time_ms)); - print_stats(Indents[2], "Ref Proc", _cur_ref_proc_time_ms); - print_stats(Indents[2], "Ref Enq", _cur_ref_enq_time_ms); - print_stats(Indents[2], "Redirty Cards", _recorded_redirty_logged_cards_time_ms); - par_phase_printer.print(RedirtyCards); + debug_line("Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); + debug_line("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); + debug_line("Reference Processing", _cur_ref_proc_time_ms); + debug_line("Reference Enqueuing", _cur_ref_enq_time_ms); + debug_line("Redirty Cards", _recorded_redirty_logged_cards_time_ms); + trace_phase(_gc_par_phases[RedirtyCards]); + trace_phase(_gc_par_phases[PreserveCMReferents]); if (G1EagerReclaimHumongousObjects) { - print_stats(Indents[2], "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); - - log_trace(gc, phases)("%sHumongous Total: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_total); - log_trace(gc, phases)("%sHumongous Candidate: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_candidates); - print_stats(Indents[2], "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); - log_trace(gc, phases)("%sHumongous Reclaimed: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_reclaimed); + debug_line("Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); + trace_line_sz("Humongous Total", _cur_fast_reclaim_humongous_total); + trace_line_sz("Humongous Candidate", _cur_fast_reclaim_humongous_candidates); + debug_line("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); + trace_line_sz("Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); } - print_stats(Indents[2], "Free CSet", - (_recorded_young_free_cset_time_ms + - _recorded_non_young_free_cset_time_ms)); - log_trace(gc, phases)("%sYoung Free CSet: %.1lf ms", Indents[3], _recorded_young_free_cset_time_ms); - log_trace(gc, phases)("%sNon-Young Free CSet: %.1lf ms", Indents[3], _recorded_non_young_free_cset_time_ms); if (_cur_verify_after_time_ms > 0.0) { - print_stats(Indents[2], "Verify After", _cur_verify_after_time_ms); + debug_line("Verify After", _cur_verify_after_time_ms); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ template class WorkerDataArray; class G1GCPhaseTimes : public CHeapObj { - friend class G1GCParPhasePrinter; - uint _active_gc_threads; uint _max_gc_threads; jlong _gc_start_counter; @@ -69,6 +67,7 @@ StringDedupQueueFixup, StringDedupTableFixup, RedirtyCards, + PreserveCMReferents, GCParPhasesSentinel }; @@ -108,6 +107,10 @@ double _recorded_redirty_logged_cards_time_ms; + double _recorded_preserve_cm_referents_time_ms; + + double _recorded_merge_pss_time_ms; + double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; @@ -120,10 +123,13 @@ double _cur_verify_before_time_ms; double _cur_verify_after_time_ms; - // Helper methods for detailed logging - void print_stats(const char*, const char* str, double value); + void note_gc_end(); - void note_gc_end(); + template + void details(T* phase, const char* indent); + void log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum); + void debug_phase(WorkerDataArray* phase); + void trace_phase(WorkerDataArray* phase, bool print_sum = true); public: G1GCPhaseTimes(uint max_gc_threads); @@ -143,16 +149,6 @@ size_t sum_thread_work_items(GCParPhases phase); - private: - double get_time_ms(GCParPhases phase, uint worker_i); - double sum_time_ms(GCParPhases phase); - double min_time_ms(GCParPhases phase); - double max_time_ms(GCParPhases phase); - size_t get_thread_work_item(GCParPhases phase, uint worker_i); - double average_thread_work_items(GCParPhases phase); - size_t min_thread_work_items(GCParPhases phase); - size_t max_thread_work_items(GCParPhases phase); - public: void record_clear_ct_time(double ms) { @@ -234,6 +230,14 @@ _recorded_redirty_logged_cards_time_ms = time_ms; } + void record_preserve_cm_referents_time_ms(double time_ms) { + _recorded_preserve_cm_referents_time_ms = time_ms; + } + + void record_merge_pss_time_ms(double time_ms) { + _recorded_merge_pss_time_ms = time_ms; + } + void record_cur_collection_start_sec(double time_ms) { _cur_collection_start_sec = time_ms; } @@ -250,8 +254,6 @@ _external_accounted_time_ms += time_ms; } - double accounted_time_ms(); - double cur_collection_start_sec() { return _cur_collection_start_sec; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp --- a/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -81,10 +81,7 @@ } void G1HotCardCache::drain(CardTableEntryClosure* cl, uint worker_i) { - if (!default_use_cache()) { - assert(_hot_cache == NULL, "Logic"); - return; - } + assert(default_use_cache(), "Drain only necessary if we use the hot card cache."); assert(_hot_cache != NULL, "Logic"); assert(!use_cache(), "cache should be disabled"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp --- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,14 +47,16 @@ void G1IHOPControl::print() { size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); - log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B," - " recent old gen allocation rate: %1.2f, recent marking phase length: %1.2f", + log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B, " + "recent allocation size: " SIZE_FORMAT "B, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", cur_conc_mark_start_threshold, cur_conc_mark_start_threshold * 100.0 / _target_occupancy, _target_occupancy, G1CollectedHeap::heap()->used(), + _last_allocated_bytes, + _last_allocation_time_s * 1000.0, _last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0, - last_marking_length_s()); + last_marking_length_s() * 1000.0); } void G1IHOPControl::send_trace_event(G1NewTracer* tracer) { @@ -191,13 +193,16 @@ void G1AdaptiveIHOPControl::print() { G1IHOPControl::print(); size_t actual_target = actual_target_threshold(); - log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: " SIZE_FORMAT "B (%1.2f), internal target occupancy: " SIZE_FORMAT "B," - " predicted old gen allocation rate: %1.2f, predicted marking phase length: %1.2f, prediction active: %s", + log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: " SIZE_FORMAT "B (%1.2f), internal target occupancy: " SIZE_FORMAT "B, " + "occupancy: " SIZE_FORMAT "B, additional buffer size: " SIZE_FORMAT "B, predicted old gen allocation rate: %1.2fB/s, " + "predicted marking phase length: %1.2fms, prediction active: %s", get_conc_mark_start_threshold(), percent_of(get_conc_mark_start_threshold(), actual_target), actual_target, + G1CollectedHeap::heap()->used(), + _last_unrestrained_young_size, _predictor->get_new_prediction(&_allocation_rate_s), - _predictor->get_new_prediction(&_marking_times_s), + _predictor->get_new_prediction(&_marking_times_s) * 1000.0, have_enough_data_for_prediction() ? "true" : "false"); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,6 +327,9 @@ G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) { assert(worker_id < _n_workers, "out of bounds access"); + if (_states[worker_id] == NULL) { + _states[worker_id] = new_par_scan_state(worker_id, _young_cset_length); + } return _states[worker_id]; } @@ -352,6 +355,10 @@ for (uint worker_index = 0; worker_index < _n_workers; ++worker_index) { G1ParScanThreadState* pss = _states[worker_index]; + if (pss == NULL) { + continue; + } + _total_cards_scanned += _cards_scanned[worker_index]; pss->flush(_surviving_young_words_total); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -200,6 +200,7 @@ size_t* _surviving_young_words_total; size_t* _cards_scanned; size_t _total_cards_scanned; + size_t _young_cset_length; uint _n_workers; bool _flushed; @@ -210,10 +211,11 @@ _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)), _cards_scanned(NEW_C_HEAP_ARRAY(size_t, n_workers, mtGC)), _total_cards_scanned(0), + _young_cset_length(young_cset_length), _n_workers(n_workers), _flushed(false) { for (uint i = 0; i < n_workers; ++i) { - _states[i] = new_par_scan_state(i, young_cset_length); + _states[i] = NULL; } memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t)); memset(_cards_scanned, 0, n_workers * sizeof(size_t)); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -238,7 +238,7 @@ RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i); - { + if (ConcurrentG1Refine::hot_card_cache_enabled()) { // Apply the closure to the entries of the hot card cache. G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i); _g1->iterate_hcc_closure(&into_cset_update_rs_cl, worker_i); @@ -291,7 +291,6 @@ _g1->cleanUpCardTable(); DirtyCardQueueSet& into_cset_dcqs = _into_cset_dirty_card_queue_set; - int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num(); if (_g1->evacuation_failed()) { double restore_remembered_set_start = os::elapsedTime(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -26,6 +26,8 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1YoungRemSetSamplingThread.hpp" +#include "gc/g1/heapRegion.inline.hpp" +#include "gc/g1/heapRegionRemSet.hpp" #include "gc/g1/suspendibleThreadSet.hpp" #include "runtime/mutexLocker.hpp" @@ -55,21 +57,21 @@ } } -G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread() { - _monitor = new Monitor(Mutex::nonleaf, - "G1YoungRemSetSamplingThread monitor", - true, - Monitor::_safepoint_check_never); - +G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : + ConcurrentGCThread(), + _monitor(Mutex::nonleaf, + "G1YoungRemSetSamplingThread monitor", + true, + Monitor::_safepoint_check_never) { set_name("G1 Young RemSet Sampling"); create_and_start(); } void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); if (!_should_terminate) { - intx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? - _monitor->wait(Mutex::_no_safepoint_check_flag, waitms); + uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? + _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); } } @@ -90,8 +92,8 @@ } void G1YoungRemSetSamplingThread::stop_service() { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - _monitor->notify(); + MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); + _monitor.notify(); } void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() { @@ -100,22 +102,35 @@ G1CollectorPolicy* g1p = g1h->g1_policy(); if (g1p->adaptive_young_list_length()) { int regions_visited = 0; - g1h->young_list()->rs_length_sampling_init(); - while (g1h->young_list()->rs_length_sampling_more()) { - g1h->young_list()->rs_length_sampling_next(); + HeapRegion* hr = g1h->young_list()->first_region(); + size_t sampled_rs_lengths = 0; + + while (hr != NULL) { + size_t rs_length = hr->rem_set()->occupied(); + sampled_rs_lengths += rs_length; + + // The current region may not yet have been added to the + // incremental collection set (it gets added when it is + // retired as the current allocation region). + if (hr->in_collection_set()) { + // Update the collection set policy information for this region + g1p->update_incremental_cset_info(hr, rs_length); + } + ++regions_visited; // we try to yield every time we visit 10 regions if (regions_visited == 10) { if (sts.should_yield()) { sts.yield(); - // we just abandon the iteration - break; + // A gc may have occurred and our sampling data is stale and further + // traversal of the young list is unsafe + return; } regions_visited = 0; } + hr = hr->get_next_young_region(); } - - g1p->revise_young_list_target_length_if_necessary(); + g1p->revise_young_list_target_length_if_necessary(sampled_rs_lengths); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ // increase the young gen size to keep pause time length goal. class G1YoungRemSetSamplingThread: public ConcurrentGCThread { private: - Monitor* _monitor; + Monitor _monitor; void sample_young_list_rs_lengths(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/g1_globals.hpp --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,10 +71,6 @@ "draining concurrent marking work queues.") \ range(1, max_intx) \ \ - experimental(bool, G1UseConcMarkReferenceProcessing, true, \ - "If true, enable reference discovery during concurrent " \ - "marking and reference processing at the end of remark.") \ - \ experimental(double, G1LastPLABAverageOccupancy, 50.0, \ "The expected average occupancy of the last PLAB in " \ "percent.") \ @@ -107,35 +103,35 @@ "Size of an update buffer") \ range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \ \ - product(intx, G1ConcRefinementYellowZone, 0, \ + product(size_t, G1ConcRefinementYellowZone, 0, \ "Number of enqueued update buffers that will " \ "trigger concurrent processing. Will be selected ergonomically " \ "by default.") \ range(0, max_intx) \ \ - product(intx, G1ConcRefinementRedZone, 0, \ + product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ "Will be selected ergonomically by default. Zero will disable " \ "concurrent processing.") \ range(0, max_intx) \ \ - product(intx, G1ConcRefinementGreenZone, 0, \ + product(size_t, G1ConcRefinementGreenZone, 0, \ "The number of update buffers that are left in the queue by the " \ "concurrent processing threads. Will be selected ergonomically " \ "by default.") \ range(0, max_intx) \ \ - product(intx, G1ConcRefinementServiceIntervalMillis, 300, \ + product(uintx, G1ConcRefinementServiceIntervalMillis, 300, \ "The last concurrent refinement thread wakes up every " \ "specified number of milliseconds to do miscellaneous work.") \ range(0, max_jint) \ \ - product(intx, G1ConcRefinementThresholdStep, 0, \ + product(size_t, G1ConcRefinementThresholdStep, 0, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ "Will be selected ergonomically by default.") \ - range(0, max_jint) \ + range(0, SIZE_MAX) \ \ product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/heapRegion.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -781,7 +781,9 @@ ResourceMark rm; _containing_obj->print_on(log.error_stream()); log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to)); - obj->print_on(log.error_stream()); + if (obj->is_oop()) { + obj->print_on(log.error_stream()); + } log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field); log.error("----------"); _failures = true; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/ptrQueue.cpp --- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ #include "runtime/mutexLocker.hpp" #include "runtime/thread.inline.hpp" +#include + PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) : _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), _permanent(permanent), _lock(NULL) @@ -87,6 +89,19 @@ } +BufferNode* BufferNode::allocate(size_t byte_size) { + assert(byte_size > 0, "precondition"); + assert(is_size_aligned(byte_size, sizeof(void**)), + "Invalid buffer size " SIZE_FORMAT, byte_size); + void* data = NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC); + return new (data) BufferNode; +} + +void BufferNode::deallocate(BufferNode* node) { + node->~BufferNode(); + FREE_C_HEAP_ARRAY(char, node); +} + PtrQueueSet::PtrQueueSet(bool notify_when_complete) : _max_completed_queue(0), _cbl_mon(NULL), _fl_lock(NULL), @@ -123,17 +138,23 @@ void** PtrQueueSet::allocate_buffer() { assert(_sz > 0, "Didn't set a buffer size."); - MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); - if (_fl_owner->_buf_free_list != NULL) { - void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list); - _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next(); - _fl_owner->_buf_free_list_sz--; - return res; + BufferNode* node = NULL; + { + MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); + node = _fl_owner->_buf_free_list; + if (node != NULL) { + _fl_owner->_buf_free_list = node->next(); + _fl_owner->_buf_free_list_sz--; + } + } + if (node == NULL) { + node = BufferNode::allocate(_sz); } else { - // Allocate space for the BufferNode in front of the buffer. - char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size(), mtGC); - return BufferNode::make_buffer_from_block(b); + // Reinitialize buffer obtained from free list. + node->set_index(0); + node->set_next(NULL); } + return BufferNode::make_buffer_from_node(node); } void PtrQueueSet::deallocate_buffer(void** buf) { @@ -150,13 +171,13 @@ // For now we'll adopt the strategy of deleting half. MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag); size_t n = _buf_free_list_sz / 2; - while (n > 0) { - assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong."); - void* b = BufferNode::make_block_from_node(_buf_free_list); - _buf_free_list = _buf_free_list->next(); - FREE_C_HEAP_ARRAY(char, b); - _buf_free_list_sz --; - n--; + for (size_t i = 0; i < n; ++i) { + assert(_buf_free_list != NULL, + "_buf_free_list_sz is wrong: " SIZE_FORMAT, _buf_free_list_sz); + BufferNode* node = _buf_free_list; + _buf_free_list = node->next(); + _buf_free_list_sz--; + BufferNode::deallocate(node); } } @@ -236,8 +257,9 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - BufferNode* cbn = BufferNode::new_from_buffer(buf); + BufferNode* cbn = BufferNode::make_node_from_buffer(buf); cbn->set_index(index); + cbn->set_next(NULL); if (_completed_buffers_tail == NULL) { assert(_completed_buffers_head == NULL, "Well-formedness"); _completed_buffers_head = cbn; @@ -249,16 +271,17 @@ _n_completed_buffers++; if (!_process_completed && _process_completed_threshold >= 0 && - _n_completed_buffers >= _process_completed_threshold) { + _n_completed_buffers >= (size_t)_process_completed_threshold) { _process_completed = true; - if (_notify_when_complete) + if (_notify_when_complete) { _cbl_mon->notify(); + } } DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); } -int PtrQueueSet::completed_buffers_list_length() { - int n = 0; +size_t PtrQueueSet::completed_buffers_list_length() { + size_t n = 0; BufferNode* cbn = _completed_buffers_head; while (cbn != NULL) { n++; @@ -312,7 +335,8 @@ void PtrQueueSet::notify_if_necessary() { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) { + assert(_process_completed_threshold >= 0, "_process_completed is negative"); + if (_n_completed_buffers >= (size_t)_process_completed_threshold || _max_completed_queue == 0) { _process_completed = true; if (_notify_when_complete) _cbl_mon->notify(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/ptrQueue.hpp --- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,9 +33,6 @@ // the addresses of modified old-generation objects. This type supports // this operation. -// The definition of placement operator new(size_t, void*) in the . -#include - class PtrQueueSet; class PtrQueue VALUE_OBJ_CLASS_SPEC { friend class VMStructs; @@ -168,42 +165,38 @@ class BufferNode { size_t _index; BufferNode* _next; + void* _buffer[1]; // Pseudo flexible array member. + + BufferNode() : _index(0), _next(NULL) { } + ~BufferNode() { } + + static size_t buffer_offset() { + return offset_of(BufferNode, _buffer); + } + public: - BufferNode() : _index(0), _next(NULL) { } BufferNode* next() const { return _next; } void set_next(BufferNode* n) { _next = n; } size_t index() const { return _index; } void set_index(size_t i) { _index = i; } - // Align the size of the structure to the size of the pointer - static size_t aligned_size() { - static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*)); - return alignment; - } + // Allocate a new BufferNode with the "buffer" having size bytes. + static BufferNode* allocate(size_t byte_size); - // BufferNode is allocated before the buffer. - // The chunk of memory that holds both of them is a block. + // Free a BufferNode. + static void deallocate(BufferNode* node); - // Produce a new BufferNode given a buffer. - static BufferNode* new_from_buffer(void** buf) { - return new (make_block_from_buffer(buf)) BufferNode; + // Return the BufferNode containing the buffer. + static BufferNode* make_node_from_buffer(void** buffer) { + return reinterpret_cast( + reinterpret_cast(buffer) - buffer_offset()); } - // The following are the required conversion routines: - static BufferNode* make_node_from_buffer(void** buf) { - return (BufferNode*)make_block_from_buffer(buf); - } + // Return the buffer for node. static void** make_buffer_from_node(BufferNode *node) { - return make_buffer_from_block(node); - } - static void* make_block_from_node(BufferNode *node) { - return (void*)node; - } - static void** make_buffer_from_block(void* p) { - return (void**)((char*)p + aligned_size()); - } - static void* make_block_from_buffer(void** p) { - return (void*)((char*)p - aligned_size()); + // &_buffer[0] might lead to index out of bounds warnings. + return reinterpret_cast( + reinterpret_cast(node) + buffer_offset()); } }; @@ -216,7 +209,7 @@ Monitor* _cbl_mon; // Protects the fields below. BufferNode* _completed_buffers_head; BufferNode* _completed_buffers_tail; - int _n_completed_buffers; + size_t _n_completed_buffers; int _process_completed_threshold; volatile bool _process_completed; @@ -240,9 +233,9 @@ // Maximum number of elements allowed on completed queue: after that, // enqueuer does the work itself. Zero indicates no maximum. int _max_completed_queue; - int _completed_queue_padding; + size_t _completed_queue_padding; - int completed_buffers_list_length(); + size_t completed_buffers_list_length(); void assert_completed_buffer_list_len_correct_locked(); void assert_completed_buffer_list_len_correct(); @@ -306,15 +299,15 @@ // list size may be reduced, if that is deemed desirable. void reduce_free_list(); - int completed_buffers_num() { return _n_completed_buffers; } + size_t completed_buffers_num() { return _n_completed_buffers; } void merge_bufferlists(PtrQueueSet* src); void set_max_completed_queue(int m) { _max_completed_queue = m; } int max_completed_queue() { return _max_completed_queue; } - void set_completed_queue_padding(int padding) { _completed_queue_padding = padding; } - int completed_queue_padding() { return _completed_queue_padding; } + void set_completed_queue_padding(size_t padding) { _completed_queue_padding = padding; } + size_t completed_queue_padding() { return _completed_queue_padding; } // Notify the consumer if the number of buffers crossed the threshold void notify_if_necessary(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/workerDataArray.cpp --- a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -24,18 +24,53 @@ #include "precompiled.hpp" #include "gc/g1/workerDataArray.inline.hpp" +#include "utilities/ostream.hpp" + +template <> +void WorkerDataArray::WDAPrinter::summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum) { + out->print("%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", title, min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS); + if (print_sum) { + out->print_cr(", Sum: %4.1lf", sum * MILLIUNITS); + } else { + out->cr(); + } +} + +template <> +void WorkerDataArray::WDAPrinter::summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) { + out->print("%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, title, min, avg, max, diff); + if (print_sum) { + out->print_cr(", Sum: " SIZE_FORMAT, sum); + } else { + out->cr(); + } +} + +template <> +void WorkerDataArray::WDAPrinter::details(const WorkerDataArray* phase, outputStream* out, uint active_threads) { + out->print("%-25s", ""); + for (uint i = 0; i < active_threads; ++i) { + out->print(" %4.1lf", phase->get(i) * 1000.0); + } + out->cr(); +} + +template <> +void WorkerDataArray::WDAPrinter::details(const WorkerDataArray* phase, outputStream* out, uint active_threads) { + out->print("%-25s", ""); + for (uint i = 0; i < active_threads; ++i) { + out->print(" " SIZE_FORMAT, phase->get(i)); + } + out->cr(); +} #ifndef PRODUCT void WorkerDataArray_test() { const uint length = 3; const char* title = "Test array"; - const bool print_sum = false; - const uint indent_level = 2; - WorkerDataArray array(length, title, print_sum, indent_level); + WorkerDataArray array(length, title); assert(strncmp(array.title(), title, strlen(title)) == 0 , "Expected titles to match"); - assert(array.should_print_sum() == print_sum, "Expected should_print_sum to match print_sum"); - assert(array.indentation() == indent_level, "Expected indentation to match"); const size_t expected[length] = {5, 3, 7}; for (uint i = 0; i < length; i++) { @@ -46,10 +81,7 @@ } assert(array.sum(length) == (5 + 3 + 7), "Expected sums to match"); - assert(array.minimum(length) == 3, "Expected mininum to match"); - assert(array.maximum(length) == 7, "Expected maximum to match"); - assert(array.diff(length) == (7 - 3), "Expected diffs to match"); - assert(array.average(length) == 5, "Expected averages to match"); + assert(array.average(length) == 5.0, "Expected averages to match"); for (uint i = 0; i < length; i++) { array.add(i, 1); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/workerDataArray.hpp --- a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -22,18 +22,19 @@ * */ +#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_HPP +#define SHARE_VM_GC_G1_WORKERDATAARRAY_HPP + #include "memory/allocation.hpp" #include "utilities/debug.hpp" +class outputStream; + template class WorkerDataArray : public CHeapObj { - friend class G1GCParPhasePrinter; T* _data; uint _length; const char* _title; - bool _print_sum; - uint _indent_level; - bool _enabled; WorkerDataArray* _thread_work_items; @@ -42,11 +43,7 @@ void set_all(T value); public: - WorkerDataArray(uint length, - const char* title, - bool print_sum, - uint indent_level); - + WorkerDataArray(uint length, const char* title); ~WorkerDataArray(); void link_thread_work_items(WorkerDataArray* thread_work_items); @@ -62,27 +59,30 @@ double average(uint active_threads) const; T sum(uint active_threads) const; - T minimum(uint active_threads) const; - T maximum(uint active_threads) const; - T diff(uint active_threads) const; - - uint indentation() const { - return _indent_level; - } const char* title() const { return _title; } - bool should_print_sum() const { - return _print_sum; - } - void clear(); - void set_enabled(bool enabled) { - _enabled = enabled; - } void reset() PRODUCT_RETURN; void verify(uint active_threads) const PRODUCT_RETURN; + + + private: + class WDAPrinter { + public: + static void summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum); + static void summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum); + + static void details(const WorkerDataArray* phase, outputStream* out, uint active_threads); + static void details(const WorkerDataArray* phase, outputStream* out, uint active_threads); + }; + + public: + void print_summary_on(outputStream* out, uint active_threads, bool print_sum = true) const; + void print_details_on(outputStream* out, uint active_threads) const; }; + +#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_HPP diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp --- a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -22,20 +22,18 @@ * */ +#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP +#define SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP + #include "gc/g1/workerDataArray.hpp" #include "memory/allocation.inline.hpp" +#include "utilities/ostream.hpp" template -WorkerDataArray::WorkerDataArray(uint length, - const char* title, - bool print_sum, - uint indent_level) : +WorkerDataArray::WorkerDataArray(uint length, const char* title) : _title(title), _length(0), - _print_sum(print_sum), - _indent_level(indent_level), - _thread_work_items(NULL), - _enabled(true) { + _thread_work_items(NULL) { assert(length > 0, "Must have some workers to store data for"); _length = length; _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); @@ -94,29 +92,6 @@ } template -T WorkerDataArray::minimum(uint active_threads) const { - T min = get(0); - for (uint i = 1; i < active_threads; ++i) { - min = MIN2(min, get(i)); - } - return min; -} - -template -T WorkerDataArray::maximum(uint active_threads) const { - T max = get(0); - for (uint i = 1; i < active_threads; ++i) { - max = MAX2(max, get(i)); - } - return max; -} - -template -T WorkerDataArray::diff(uint active_threads) const { - return maximum(active_threads) - minimum(active_threads); -} - -template void WorkerDataArray::clear() { set_all(0); } @@ -128,6 +103,27 @@ } } +template +void WorkerDataArray::print_summary_on(outputStream* out, uint active_threads, bool print_sum) const { + T max = get(0); + T min = max; + T sum = 0; + for (uint i = 1; i < active_threads; ++i) { + T value = get(i); + max = MAX2(max, value); + min = MIN2(min, value); + sum += value; + } + T diff = max - min; + double avg = sum / (double) active_threads; + WDAPrinter::summary(out, title(), min, avg, max, diff, sum, print_sum); +} + +template +void WorkerDataArray::print_details_on(outputStream* out, uint active_threads) const { + WDAPrinter::details(this, out, active_threads); +} + #ifndef PRODUCT template void WorkerDataArray::reset() { @@ -139,10 +135,6 @@ template void WorkerDataArray::verify(uint active_threads) const { - if (!_enabled) { - return; - } - assert(active_threads <= _length, "Wrong number of active threads"); for (uint i = 0; i < active_threads; i++) { assert(_data[i] != uninitialized(), @@ -163,3 +155,5 @@ return -1.0; } #endif + +#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/youngList.cpp --- a/hotspot/src/share/vm/gc/g1/youngList.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/youngList.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -33,9 +33,9 @@ #include "utilities/ostream.hpp" YoungList::YoungList(G1CollectedHeap* g1h) : - _g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0), + _g1h(g1h), _head(NULL), _length(0), _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) { - guarantee(check_list_empty(false), "just making sure..."); + guarantee(check_list_empty(), "just making sure..."); } void YoungList::push_region(HeapRegion *hr) { @@ -86,9 +86,7 @@ _survivor_tail = NULL; _survivor_length = 0; - _last_sampled_rs_lengths = 0; - - assert(check_list_empty(false), "just making sure..."); + assert(check_list_empty(), "just making sure..."); } bool YoungList::check_list_well_formed() { @@ -119,17 +117,13 @@ return ret; } -bool YoungList::check_list_empty(bool check_sample) { +bool YoungList::check_list_empty() { bool ret = true; if (_length != 0) { log_error(gc, verify)("### YOUNG LIST should have 0 length, not %u", _length); ret = false; } - if (check_sample && _last_sampled_rs_lengths != 0) { - log_error(gc, verify)("### YOUNG LIST has non-zero last sampled RS lengths"); - ret = false; - } if (_head != NULL) { log_error(gc, verify)("### YOUNG LIST does not have a NULL head"); ret = false; @@ -142,38 +136,6 @@ } void -YoungList::rs_length_sampling_init() { - _sampled_rs_lengths = 0; - _curr = _head; -} - -bool -YoungList::rs_length_sampling_more() { - return _curr != NULL; -} - -void -YoungList::rs_length_sampling_next() { - assert( _curr != NULL, "invariant" ); - size_t rs_length = _curr->rem_set()->occupied(); - - _sampled_rs_lengths += rs_length; - - // The current region may not yet have been added to the - // incremental collection set (it gets added when it is - // retired as the current allocation region). - if (_curr->in_collection_set()) { - // Update the collection set policy information for this region - _g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length); - } - - _curr = _curr->get_next_young_region(); - if (_curr == NULL) { - _last_sampled_rs_lengths = _sampled_rs_lengths; - } -} - -void YoungList::reset_auxilary_lists() { guarantee( is_empty(), "young list should be empty" ); assert(check_list_well_formed(), "young list should be well formed"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/g1/youngList.hpp --- a/hotspot/src/share/vm/gc/g1/youngList.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/g1/youngList.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -37,14 +37,9 @@ HeapRegion* _survivor_head; HeapRegion* _survivor_tail; - HeapRegion* _curr; - uint _length; uint _survivor_length; - size_t _last_sampled_rs_lengths; - size_t _sampled_rs_lengths; - void empty_list(HeapRegion* list); public: @@ -72,15 +67,6 @@ return (size_t) survivor_length() * HeapRegion::GrainBytes; } - void rs_length_sampling_init(); - bool rs_length_sampling_more(); - void rs_length_sampling_next(); - - void reset_sampled_info() { - _last_sampled_rs_lengths = 0; - } - size_t sampled_rs_lengths() { return _last_sampled_rs_lengths; } - // for development purposes void reset_auxilary_lists(); void clear() { _head = NULL; _length = 0; } @@ -97,7 +83,7 @@ // debugging bool check_list_well_formed(); - bool check_list_empty(bool check_sample = true); + bool check_list_empty(); void print(); }; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/shared/collectedHeap.cpp --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -405,7 +405,9 @@ oop CollectedHeap::new_store_pre_barrier(JavaThread* thread, oop new_obj) { // If a previous card-mark was deferred, flush it now. flush_deferred_store_barrier(thread); - if (can_elide_initializing_store_barrier(new_obj)) { + if (can_elide_initializing_store_barrier(new_obj) || + new_obj->is_typeArray()) { + // Arrays of non-references don't need a pre-barrier. // The deferred_card_mark region should be empty // following the flush above. assert(thread->deferred_card_mark().is_empty(), "Error"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp --- a/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_VM_GC_SHARED_COPYFAILEDINFO_HPP #include "runtime/thread.hpp" +#include "trace/traceMacros.hpp" #include "utilities/globalDefinitions.hpp" class CopyFailedInfo : public CHeapObj { @@ -63,26 +64,28 @@ }; class PromotionFailedInfo : public CopyFailedInfo { - OSThread* _thread; + traceid _thread_trace_id; public: - PromotionFailedInfo() : CopyFailedInfo(), _thread(NULL) {} + PromotionFailedInfo() : CopyFailedInfo(), _thread_trace_id(0) {} void register_copy_failure(size_t size) { CopyFailedInfo::register_copy_failure(size); - if (_thread == NULL) { - _thread = Thread::current()->osthread(); + if (_thread_trace_id == 0) { + _thread_trace_id = THREAD_TRACE_ID(Thread::current()); } else { - assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local."); + assert(THREAD_TRACE_ID(Thread::current()) == _thread_trace_id, + "The PromotionFailedInfo should be thread local."); } } void reset() { CopyFailedInfo::reset(); - _thread = NULL; + _thread_trace_id = 0; } - OSThread* thread() const { return _thread; } + traceid thread_trace_id() const { return _thread_trace_id; } + }; class EvacuationFailedInfo : public CopyFailedInfo {}; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/shared/gcTraceSend.cpp --- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,7 +174,7 @@ if (e.should_commit()) { e.set_gcId(GCId::current()); e.set_data(to_trace_struct(pf_info)); - e.set_thread(pf_info.thread()->thread_id()); + e.set_thread(pf_info.thread_trace_id()); e.commit(); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/shared/plab.cpp --- a/hotspot/src/share/vm/gc/shared/plab.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/shared/plab.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,6 +110,30 @@ } } +void PLABStats::log_plab_allocation() { + log_debug(gc, plab)("%s PLAB allocation: " + "allocated: " SIZE_FORMAT "B, " + "wasted: " SIZE_FORMAT "B, " + "unused: " SIZE_FORMAT "B, " + "used: " SIZE_FORMAT "B, " + "undo waste: " SIZE_FORMAT "B, ", + _description, + _allocated * HeapWordSize, + _wasted * HeapWordSize, + _unused * HeapWordSize, + used() * HeapWordSize, + _undo_wasted * HeapWordSize); +} + +void PLABStats::log_sizing(size_t calculated_words, size_t net_desired_words) { + log_debug(gc, plab)("%s sizing: " + "calculated: " SIZE_FORMAT "B, " + "actual: " SIZE_FORMAT "B", + _description, + calculated_words * HeapWordSize, + net_desired_words * HeapWordSize); +} + // Calculates plab size for current number of gc worker threads. size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) { return MAX2(min_size(), (size_t)align_object_size(_desired_net_plab_sz / no_of_gc_workers)); @@ -119,7 +143,13 @@ // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators. void PLABStats::adjust_desired_plab_sz() { - assert(ResizePLAB, "Not set"); + log_plab_allocation(); + + if (!ResizePLAB) { + // Clear accumulators for next round. + reset(); + return; + } assert(is_object_aligned(max_size()) && min_size() <= max_size(), "PLAB clipping computation may be incorrect"); @@ -150,8 +180,9 @@ new_plab_sz = MIN2(max_size(), new_plab_sz); new_plab_sz = align_object_size(new_plab_sz); // Latch the result - log_trace(gc, plab)("plab_size = " SIZE_FORMAT " desired_net_plab_sz = " SIZE_FORMAT ") ", recent_plab_sz, new_plab_sz); _desired_net_plab_sz = new_plab_sz; + log_sizing(recent_plab_sz, new_plab_sz); + reset(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/gc/shared/plab.hpp --- a/hotspot/src/share/vm/gc/shared/plab.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/gc/shared/plab.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,6 +146,8 @@ // PLAB book-keeping. class PLABStats : public CHeapObj { protected: + const char* _description; // Identifying string. + size_t _allocated; // Total allocated size_t _wasted; // of which wasted (internal fragmentation) size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size) @@ -160,8 +162,12 @@ _undo_wasted = 0; _unused = 0; } + + virtual void log_plab_allocation(); + virtual void log_sizing(size_t calculated, size_t net_desired); public: - PLABStats(size_t desired_net_plab_sz_, unsigned wt) : + PLABStats(const char* description, size_t desired_net_plab_sz_, unsigned wt) : + _description(description), _allocated(0), _wasted(0), _undo_wasted(0), @@ -172,6 +178,12 @@ virtual ~PLABStats() { } + size_t allocated() const { return _allocated; } + size_t wasted() const { return _wasted; } + size_t unused() const { return _unused; } + size_t used() const { return allocated() - (wasted() + unused()); } + size_t undo_wasted() const { return _undo_wasted; } + static const size_t min_size() { return PLAB::min_size(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -762,14 +762,6 @@ ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread); if (cp_cache_entry->is_resolved(bytecode)) return; - if (bytecode == Bytecodes::_invokeinterface) { - if (log_develop_is_enabled(Trace, itables)) { - ResourceMark rm(thread); - log_develop_trace(itables)("Resolving: klass: %s to method: %s", - info.resolved_klass()->name()->as_C_string(), - info.resolved_method()->name()->as_C_string()); - } - } #ifdef ASSERT if (bytecode == Bytecodes::_invokeinterface) { if (info.resolved_method()->method_holder() == diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.cpp --- a/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.cpp Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +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. - * - */ - -#include "precompiled.hpp" -#include "jvmci/commandLineFlagConstraintsJVMCI.hpp" -#include "runtime/arguments.hpp" -#include "runtime/globals.hpp" -#include "utilities/defaultStream.hpp" - -Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose) { - if (!EnableJVMCI) { - if (verbose == true) { - jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n"); - } - return Flag::VIOLATES_CONSTRAINT; - } else { - return Flag::SUCCESS; - } -} - -Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose) { - if (!EnableJVMCI) { - if (verbose == true) { - jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n"); - } - return Flag::VIOLATES_CONSTRAINT; - } else { - return Flag::SUCCESS; - } -} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.hpp --- a/hotspot/src/share/vm/jvmci/commandLineFlagConstraintsJVMCI.hpp Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +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. - * - */ - -#ifndef SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP -#define SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP - -#include "runtime/globals.hpp" -#include "utilities/globalDefinitions.hpp" - -/* - * Here we have JVMCI arguments constraints functions, which are called automatically - * whenever flag's value changes. If the constraint fails the function should return - * an appropriate error value. - */ - -Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(bool value, bool verbose); -Flag::Error EnableJVMCIMustBeEnabledConstraintFunc(intx value, bool verbose); - -#endif /* SHARE_VM_JVMCI_COMMANDLINEFLAGCONSTRAINTSJVMCI_HPP */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -551,6 +551,14 @@ compiler, _debug_recorder, _dependencies, env, id, has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log); cb = nm; + if (nm != NULL && env == NULL) { + DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler); + bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption; + if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) { + nm->print_nmethod(printnmethods); + } + DirectivesStack::release(directive); + } } if (cb != NULL) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/jvmciRuntime.cpp --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -293,13 +293,11 @@ // tracing if (log_is_enabled(Info, exceptions)) { ResourceMark rm; - log_info(exceptions)("Exception <%s> (" INTPTR_FORMAT ") thrown in" - " compiled method <%s> at PC " INTPTR_FORMAT - " for thread " INTPTR_FORMAT, - exception->print_value_string(), - p2i((address)exception()), - nm->method()->print_value_string(), p2i(pc), - p2i(thread)); + stringStream tempst; + tempst.print("compiled method <%s>\n" + " at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT, + nm->method()->print_value_string(), p2i(pc), p2i(thread)); + Exceptions::log_exception(exception, tempst); } // for AbortVMOnException flag NOT_PRODUCT(Exceptions::debug_check_abort(exception)); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/jvmci_globals.cpp --- a/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/jvmci/jvmci_globals.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "jvmci/jvmci_globals.hpp" +#include "utilities/defaultStream.hpp" +#include "runtime/globals_extension.hpp" JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \ MATERIALIZE_PD_DEVELOPER_FLAG, \ @@ -34,3 +36,185 @@ MATERIALIZE_NOTPRODUCT_FLAG, IGNORE_RANGE, \ IGNORE_CONSTRAINT) + +#define JVMCI_IGNORE_FLAG_FOUR_PARAM(type, name, value, doc) +#define JVMCI_IGNORE_FLAG_THREE_PARAM(type, name, doc) + +// Return true if jvmci flags are consistent. +bool JVMCIGlobals::check_jvmci_flags_are_consistent() { + if (EnableJVMCI) { + return true; + } + + // "FLAG_IS_DEFAULT" fail count. + int fail_count = 0; + // Number of "FLAG_IS_DEFAULT" fails that should be skipped before code + // detect real consistency failure. + int skip_fail_count; + + // EnableJVMCI flag is false here. + // If any other flag is changed, consistency check should fail. + // JVMCI_FLAGS macros added below can handle all JVMCI flags automatically. + // But it contains check for EnableJVMCI flag too, which is required to be + // skipped. This can't be handled easily! + // So the code looks for at-least two flag changes to detect consistency + // failure when EnableJVMCI flag is changed. + // Otherwise one flag change is sufficient to detect consistency failure. + // Set skip_fail_count to 0 if EnableJVMCI flag is default. + // Set skip_fail_count to 1 if EnableJVMCI flag is changed. + // This value will be used to skip fails in macro expanded code later. + if (!FLAG_IS_DEFAULT(EnableJVMCI)) { + skip_fail_count = 1; + } else { + skip_fail_count = 0; + } + +#define EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(FLAG) \ + if (!FLAG_IS_DEFAULT(FLAG)) { \ + fail_count++; \ + if (fail_count > skip_fail_count) { \ + return false; \ + } \ + } + +#define JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) +#define JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) + + // Check consistency of diagnostic flags if UnlockDiagnosticVMOptions is true + // or not default. UnlockDiagnosticVMOptions is default true in debug builds. + if (UnlockDiagnosticVMOptions || !FLAG_IS_DEFAULT(UnlockDiagnosticVMOptions)) { + JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + } + + // Check consistency of experimental flags if UnlockExperimentalVMOptions is + // true or not default. + if (UnlockExperimentalVMOptions || !FLAG_IS_DEFAULT(UnlockExperimentalVMOptions)) { + JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + } + +#ifndef PRODUCT +#define JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) +#define JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) +#define JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) +#else +#define JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) +#define JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) +#define JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) +#endif + +#define JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) +#define JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE(type, name, value, doc) EMIT_FLAG_VALUE_CHANGED_CHECK_CODE(name) + + JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE, \ + JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE, \ + JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \ + JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + +#undef EMIT_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_PD_DEVELOP_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_NOTPRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_DIAGNOSTIC_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_PD_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_PRODUCT_FLAG_VALUE_CHANGED_CHECK_CODE +#undef JVMCI_EXPERIMENTAL_FLAG_VALUE_CHANGED_CHECK_CODE + + return true; +} + +// Print jvmci arguments inconsistency error message. +void JVMCIGlobals::print_jvmci_args_inconsistency_error_message() { + const char* error_msg = "Improperly specified VM option '%s'\n"; + jio_fprintf(defaultStream::error_stream(), "EnableJVMCI must be enabled\n"); + +#define EMIT_CHECK_PRINT_ERR_MSG_CODE(FLAG) \ + if (!FLAG_IS_DEFAULT(FLAG)) { \ + if (strcmp(#FLAG, "EnableJVMCI")) { \ + jio_fprintf(defaultStream::error_stream(), error_msg, #FLAG); \ + } \ + } + +#define JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) +#define JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) + + if (UnlockDiagnosticVMOptions || !FLAG_IS_DEFAULT(UnlockDiagnosticVMOptions)) { + JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + } + + if (UnlockExperimentalVMOptions || !FLAG_IS_DEFAULT(UnlockExperimentalVMOptions)) { + JVMCI_FLAGS(JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_THREE_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + } + +#ifndef PRODUCT +#define JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) +#define JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) +#define JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) +#else +#define JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) +#define JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) +#define JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) +#endif + +#define JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) +#define JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE(type, name, value, doc) EMIT_CHECK_PRINT_ERR_MSG_CODE(name) + + JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_IGNORE_FLAG_FOUR_PARAM, \ + JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE, \ + IGNORE_RANGE, \ + IGNORE_CONSTRAINT) + +#undef EMIT_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_PD_DEVELOP_FLAG_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_NOTPRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_PD_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_PRODUCT_FLAG_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_DIAGNOSTIC_FLAG_CHECK_PRINT_ERR_MSG_CODE +#undef JVMCI_EXPERIMENTAL_FLAG_CHECK_PRINT_ERR_MSG_CODE + +} + +#undef JVMCI_IGNORE_FLAG_FOUR_PARAM +#undef JVMCI_IGNORE_FLAG_THREE_PARAM diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/jvmci_globals.hpp --- a/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/jvmci/jvmci_globals.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -39,29 +39,23 @@ \ experimental(bool, UseJVMCICompiler, false, \ "Use JVMCI as the default compiler") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(bool, BootstrapJVMCI, false, \ "Bootstrap JVMCI before running Java main method") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(bool, PrintBootstrap, true, \ "Print JVMCI bootstrap progress and summary") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(intx, JVMCIThreads, 1, \ "Force number of JVMCI compiler threads to use") \ range(1, max_jint) \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(intx, JVMCIHostThreads, 1, \ "Force number of compiler threads for JVMCI host compiler") \ range(1, max_jint) \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(bool, CodeInstallSafepointChecks, true, \ "Perform explicit safepoint checks while installing code") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ NOT_COMPILER2(product(intx, MaxVectorSize, 64, \ "Max vector size in bytes, " \ @@ -74,28 +68,22 @@ "Trace level for JVMCI: " \ "1 means emit a message for each CompilerToVM call," \ "levels greater than 1 provide progressively greater detail") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(intx, JVMCICounterSize, 0, \ "Reserved size for benchmark counters") \ range(0, max_jint) \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(bool, JVMCICountersExcludeCompiler, true, \ "Exclude JVMCI compiler threads from benchmark counters") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ develop(bool, JVMCIUseFastLocking, true, \ "Use fast inlined locking code") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ experimental(intx, JVMCINMethodSizeLimit, (80*K)*wordSize, \ "Maximum size of a compiled method.") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ \ develop(bool, TraceUncollectedSpeculations, false, \ - "Print message when a failed speculation was not collected") \ - constraint(EnableJVMCIMustBeEnabledConstraintFunc,AtParse) \ + "Print message when a failed speculation was not collected") // Read default values for JVMCI globals @@ -110,4 +98,11 @@ IGNORE_RANGE, \ IGNORE_CONSTRAINT) +class JVMCIGlobals { + public: + // Return true if jvmci flags are consistent. + static bool check_jvmci_flags_are_consistent(); + // Print jvmci arguments inconsistency error message. + static void print_jvmci_args_inconsistency_error_message(); +}; #endif // SHARE_VM_JVMCI_JVMCIGLOBALS_HPP diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -592,6 +592,14 @@ #endif // TARGET_OS_FAMILY_bsd +#ifdef TARGET_ARCH_aarch64 + +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) + +#endif // TARGET_ARCH_aarch64 + + #ifdef TARGET_ARCH_x86 #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/logging/logPrefix.hpp --- a/hotspot/src/share/vm/logging/logPrefix.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/logging/logPrefix.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -58,6 +58,7 @@ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, metaspace)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, start)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, task)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, plab)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, region)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, remset)) \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/logging/logTag.hpp --- a/hotspot/src/share/vm/logging/logTag.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/logging/logTag.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -43,6 +43,7 @@ LOG_TAG(classload) /* Trace all classes loaded */ \ LOG_TAG(classloaderdata) /* class loader loader_data lifetime */ \ LOG_TAG(classunload) /* Trace unloading of classes */ \ + LOG_TAG(classpath) \ LOG_TAG(compaction) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ @@ -66,6 +67,7 @@ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ + LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \ LOG_TAG(ref) \ LOG_TAG(refine) \ LOG_TAG(region) \ @@ -81,6 +83,7 @@ LOG_TAG(survivor) \ LOG_TAG(sweep) \ LOG_TAG(task) \ + LOG_TAG(thread) \ LOG_TAG(tlab) \ LOG_TAG(time) \ LOG_TAG(verify) \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/memory/filemap.cpp --- a/hotspot/src/share/vm/memory/filemap.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/memory/filemap.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -208,9 +208,7 @@ count ++; bytes += (int)entry_size; bytes += name_bytes; - if (TraceClassPaths) { - tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); - } + log_info(classpath)("add main shared path (%s) %s", (cpe->is_jar_file() ? "jar" : "dir"), name); } else { SharedClassPathEntry* ent = shared_classpath(cur_entry); if (cpe->is_jar_file()) { @@ -275,9 +273,7 @@ struct stat st; const char* name = ent->_name; bool ok = true; - if (TraceClassPaths) { - tty->print_cr("[Checking shared classpath entry: %s]", name); - } + log_info(classpath)("checking shared classpath entry: %s", name); if (os::stat(name, &st) != 0) { fail_continue("Required classpath entry does not exist: %s", name); ok = false; @@ -301,9 +297,7 @@ } } if (ok) { - if (TraceClassPaths) { - tty->print_cr("[ok]"); - } + log_info(classpath)("ok"); } else if (!PrintSharedArchiveAndExit) { _validating_classpath_entry_table = false; return false; @@ -888,10 +882,8 @@ char header_version[JVM_IDENT_MAX]; get_header_version(header_version); if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { - if (TraceClassPaths) { - tty->print_cr("Expected: %s", header_version); - tty->print_cr("Actual: %s", _jvm_ident); - } + log_info(classpath)("expected: %s", header_version); + log_info(classpath)("actual: %s", _jvm_ident); FileMapInfo::fail_continue("The shared archive file was created by a different" " version or build of HotSpot"); return false; @@ -919,7 +911,7 @@ if (status) { if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) { if (!PrintSharedArchiveAndExit) { - fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)"); + fail_continue("shared class paths mismatch (hint: enable -Xlog:classpath=info to diagnose the failure)"); status = false; } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/arrayKlass.cpp --- a/hotspot/src/share/vm/oops/arrayKlass.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -89,7 +89,7 @@ set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass()); set_layout_helper(Klass::_lh_neutral_value); set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5) - TRACE_INIT_ID(this); + TRACE_INIT_KLASS_ID(this); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1879,7 +1879,7 @@ return dep_context; } -int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { +int InstanceKlass::mark_dependent_nmethods(KlassDepChange& changes) { return dependencies().mark_dependent_nmethods(changes); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ // forward declaration for class -- see below for definition class BreakpointInfo; class ClassFileParser; -class DepChange; +class KlassDepChange; class DependencyContext; class fieldDescriptor; class jniIdMapBase; @@ -821,7 +821,7 @@ // maintenance of deoptimization dependencies inline DependencyContext dependencies(); - int mark_dependent_nmethods(DepChange& changes); + int mark_dependent_nmethods(KlassDepChange& changes); void add_dependent_nmethod(nmethod* nm); void remove_dependent_nmethod(nmethod* nm, bool delete_immediately); @@ -839,7 +839,7 @@ // support for stub routines static ByteSize init_state_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_state)); } - TRACE_DEFINE_OFFSET; + TRACE_DEFINE_KLASS_TRACE_ID_OFFSET; static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); } // subclass/subinterface checks diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/klass.cpp --- a/hotspot/src/share/vm/oops/klass.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/oops/klass.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -494,7 +494,7 @@ } void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { - TRACE_INIT_ID(this); + TRACE_INIT_KLASS_ID(this); // If an exception happened during CDS restore, some of these fields may already be // set. We leave the class on the CLD list, even if incomplete so that we don't // modify the CLD list outside a safepoint. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/klass.hpp --- a/hotspot/src/share/vm/oops/klass.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/oops/klass.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -132,7 +132,7 @@ jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. - TRACE_DEFINE_KLASS_TRACE_ID; + TRACE_DEFINE_TRACE_ID_FIELD; // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) @@ -569,7 +569,7 @@ jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; } void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; } - TRACE_DEFINE_KLASS_METHODS; + TRACE_DEFINE_TRACE_ID_METHODS; // garbage collection support void oops_do(OopClosure* cl); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/method.cpp diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/method.hpp diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/oops/typeArrayOop.hpp --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -129,7 +129,7 @@ Metadata* metadata_at(int which) const { return (Metadata*)*long_at_addr(which); } void metadata_at_put(int which, Metadata* contents) { - *long_at_addr(which) = (long)contents; + *long_at_addr(which) = (jlong)contents; } #else Metadata* metadata_at(int which) const { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/c2compiler.cpp --- a/hotspot/src/share/vm/opto/c2compiler.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/c2compiler.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -243,14 +243,72 @@ case vmIntrinsics::_reverseBytes_l: if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false; break; + + /* CompareAndSwap, Object: */ case vmIntrinsics::_compareAndSwapObject: #ifdef _LP64 + if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapN)) return false; if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndSwapP)) return false; +#else + if (!Matcher::match_rule_supported(Op_CompareAndSwapP)) return false; #endif break; + case vmIntrinsics::_weakCompareAndSwapObject: + case vmIntrinsics::_weakCompareAndSwapObjectAcquire: + case vmIntrinsics::_weakCompareAndSwapObjectRelease: +#ifdef _LP64 + if ( UseCompressedOops && !Matcher::match_rule_supported(Op_WeakCompareAndSwapN)) return false; + if (!UseCompressedOops && !Matcher::match_rule_supported(Op_WeakCompareAndSwapP)) return false; +#else + if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapP)) return false; +#endif + break; + /* CompareAndSwap, Long: */ case vmIntrinsics::_compareAndSwapLong: if (!Matcher::match_rule_supported(Op_CompareAndSwapL)) return false; break; + case vmIntrinsics::_weakCompareAndSwapLong: + case vmIntrinsics::_weakCompareAndSwapLongAcquire: + case vmIntrinsics::_weakCompareAndSwapLongRelease: + if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapL)) return false; + break; + + /* CompareAndSwap, Int: */ + case vmIntrinsics::_compareAndSwapInt: + if (!Matcher::match_rule_supported(Op_CompareAndSwapI)) return false; + break; + case vmIntrinsics::_weakCompareAndSwapInt: + case vmIntrinsics::_weakCompareAndSwapIntAcquire: + case vmIntrinsics::_weakCompareAndSwapIntRelease: + if (!Matcher::match_rule_supported(Op_WeakCompareAndSwapL)) return false; + break; + + /* CompareAndExchange, Object: */ + case vmIntrinsics::_compareAndExchangeObjectVolatile: + case vmIntrinsics::_compareAndExchangeObjectAcquire: + case vmIntrinsics::_compareAndExchangeObjectRelease: +#ifdef _LP64 + if ( UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndExchangeN)) return false; + if (!UseCompressedOops && !Matcher::match_rule_supported(Op_CompareAndExchangeP)) return false; +#else + if (!Matcher::match_rule_supported(Op_CompareAndExchangeP)) return false; +#endif + break; + + /* CompareAndExchange, Long: */ + case vmIntrinsics::_compareAndExchangeLongVolatile: + case vmIntrinsics::_compareAndExchangeLongAcquire: + case vmIntrinsics::_compareAndExchangeLongRelease: + if (!Matcher::match_rule_supported(Op_CompareAndExchangeL)) return false; + break; + + /* CompareAndExchange, Int: */ + case vmIntrinsics::_compareAndExchangeIntVolatile: + case vmIntrinsics::_compareAndExchangeIntAcquire: + case vmIntrinsics::_compareAndExchangeIntRelease: + if (!Matcher::match_rule_supported(Op_CompareAndExchangeI)) return false; + break; + case vmIntrinsics::_getAndAddInt: if (!Matcher::match_rule_supported(Op_GetAndAddI)) return false; break; @@ -382,6 +440,42 @@ case vmIntrinsics::_putLongVolatile: case vmIntrinsics::_putFloatVolatile: case vmIntrinsics::_putDoubleVolatile: + case vmIntrinsics::_getObjectAcquire: + case vmIntrinsics::_getBooleanAcquire: + case vmIntrinsics::_getByteAcquire: + case vmIntrinsics::_getShortAcquire: + case vmIntrinsics::_getCharAcquire: + case vmIntrinsics::_getIntAcquire: + case vmIntrinsics::_getLongAcquire: + case vmIntrinsics::_getFloatAcquire: + case vmIntrinsics::_getDoubleAcquire: + case vmIntrinsics::_putObjectRelease: + case vmIntrinsics::_putBooleanRelease: + case vmIntrinsics::_putByteRelease: + case vmIntrinsics::_putShortRelease: + case vmIntrinsics::_putCharRelease: + case vmIntrinsics::_putIntRelease: + case vmIntrinsics::_putLongRelease: + case vmIntrinsics::_putFloatRelease: + case vmIntrinsics::_putDoubleRelease: + case vmIntrinsics::_getObjectOpaque: + case vmIntrinsics::_getBooleanOpaque: + case vmIntrinsics::_getByteOpaque: + case vmIntrinsics::_getShortOpaque: + case vmIntrinsics::_getCharOpaque: + case vmIntrinsics::_getIntOpaque: + case vmIntrinsics::_getLongOpaque: + case vmIntrinsics::_getFloatOpaque: + case vmIntrinsics::_getDoubleOpaque: + case vmIntrinsics::_putObjectOpaque: + case vmIntrinsics::_putBooleanOpaque: + case vmIntrinsics::_putByteOpaque: + case vmIntrinsics::_putShortOpaque: + case vmIntrinsics::_putCharOpaque: + case vmIntrinsics::_putIntOpaque: + case vmIntrinsics::_putLongOpaque: + case vmIntrinsics::_putFloatOpaque: + case vmIntrinsics::_putDoubleOpaque: case vmIntrinsics::_getShortUnaligned: case vmIntrinsics::_getCharUnaligned: case vmIntrinsics::_getIntUnaligned: @@ -390,7 +484,6 @@ case vmIntrinsics::_putCharUnaligned: case vmIntrinsics::_putIntUnaligned: case vmIntrinsics::_putLongUnaligned: - case vmIntrinsics::_compareAndSwapInt: case vmIntrinsics::_putOrderedObject: case vmIntrinsics::_putOrderedInt: case vmIntrinsics::_putOrderedLong: @@ -400,8 +493,6 @@ case vmIntrinsics::_currentThread: case vmIntrinsics::_isInterrupted: #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_currentTimeMillis: diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/classes.hpp --- a/hotspot/src/share/vm/opto/classes.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/classes.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -85,6 +85,14 @@ macro(CompareAndSwapL) macro(CompareAndSwapP) macro(CompareAndSwapN) +macro(WeakCompareAndSwapI) +macro(WeakCompareAndSwapL) +macro(WeakCompareAndSwapP) +macro(WeakCompareAndSwapN) +macro(CompareAndExchangeI) +macro(CompareAndExchangeL) +macro(CompareAndExchangeP) +macro(CompareAndExchangeN) macro(GetAndAddI) macro(GetAndAddL) macro(GetAndSetI) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/compile.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -88,7 +88,27 @@ // Return the index at which m must be inserted (or already exists). // The sort order is by the address of the ciMethod, with is_virtual as minor key. -int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual) { +class IntrinsicDescPair { + private: + ciMethod* _m; + bool _is_virtual; + public: + IntrinsicDescPair(ciMethod* m, bool is_virtual) : _m(m), _is_virtual(is_virtual) {} + static int compare(IntrinsicDescPair* const& key, CallGenerator* const& elt) { + ciMethod* m= elt->method(); + ciMethod* key_m = key->_m; + if (key_m < m) return -1; + else if (key_m > m) return 1; + else { + bool is_virtual = elt->is_virtual(); + bool key_virtual = key->_is_virtual; + if (key_virtual < is_virtual) return -1; + else if (key_virtual > is_virtual) return 1; + else return 0; + } + } +}; +int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found) { #ifdef ASSERT for (int i = 1; i < _intrinsics->length(); i++) { CallGenerator* cg1 = _intrinsics->at(i-1); @@ -99,63 +119,28 @@ "compiler intrinsics list must stay sorted"); } #endif - // Binary search sorted list, in decreasing intervals [lo, hi]. - int lo = 0, hi = _intrinsics->length()-1; - while (lo <= hi) { - int mid = (uint)(hi + lo) / 2; - ciMethod* mid_m = _intrinsics->at(mid)->method(); - if (m < mid_m) { - hi = mid-1; - } else if (m > mid_m) { - lo = mid+1; - } else { - // look at minor sort key - bool mid_virt = _intrinsics->at(mid)->is_virtual(); - if (is_virtual < mid_virt) { - hi = mid-1; - } else if (is_virtual > mid_virt) { - lo = mid+1; - } else { - return mid; // exact match - } - } - } - return lo; // inexact match + IntrinsicDescPair pair(m, is_virtual); + return _intrinsics->find_sorted(&pair, found); } void Compile::register_intrinsic(CallGenerator* cg) { if (_intrinsics == NULL) { _intrinsics = new (comp_arena())GrowableArray(comp_arena(), 60, 0, NULL); } - // This code is stolen from ciObjectFactory::insert. - // Really, GrowableArray should have methods for - // insert_at, remove_at, and binary_search. int len = _intrinsics->length(); - int index = intrinsic_insertion_index(cg->method(), cg->is_virtual()); - if (index == len) { - _intrinsics->append(cg); - } else { -#ifdef ASSERT - CallGenerator* oldcg = _intrinsics->at(index); - assert(oldcg->method() != cg->method() || oldcg->is_virtual() != cg->is_virtual(), "don't register twice"); -#endif - _intrinsics->append(_intrinsics->at(len-1)); - int pos; - for (pos = len-2; pos >= index; pos--) { - _intrinsics->at_put(pos+1,_intrinsics->at(pos)); - } - _intrinsics->at_put(index, cg); - } + bool found = false; + int index = intrinsic_insertion_index(cg->method(), cg->is_virtual(), found); + assert(!found, "registering twice"); + _intrinsics->insert_before(index, cg); assert(find_intrinsic(cg->method(), cg->is_virtual()) == cg, "registration worked"); } CallGenerator* Compile::find_intrinsic(ciMethod* m, bool is_virtual) { assert(m->is_loaded(), "don't try this on unloaded methods"); if (_intrinsics != NULL) { - int index = intrinsic_insertion_index(m, is_virtual); - if (index < _intrinsics->length() - && _intrinsics->at(index)->method() == m - && _intrinsics->at(index)->is_virtual() == is_virtual) { + bool found = false; + int index = intrinsic_insertion_index(m, is_virtual, found); + if (found) { return _intrinsics->at(index); } } @@ -2801,6 +2786,14 @@ case Op_CompareAndSwapL: case Op_CompareAndSwapP: case Op_CompareAndSwapN: + case Op_WeakCompareAndSwapI: + case Op_WeakCompareAndSwapL: + case Op_WeakCompareAndSwapP: + case Op_WeakCompareAndSwapN: + case Op_CompareAndExchangeI: + case Op_CompareAndExchangeL: + case Op_CompareAndExchangeP: + case Op_CompareAndExchangeN: case Op_GetAndAddI: case Op_GetAndAddL: case Op_GetAndSetI: diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/compile.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1250,7 +1250,7 @@ // Intrinsic setup. void register_library_intrinsics(); // initializer CallGenerator* make_vm_intrinsic(ciMethod* m, bool is_virtual); // constructor - int intrinsic_insertion_index(ciMethod* m, bool is_virtual); // helper + int intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found); // helper CallGenerator* find_intrinsic(ciMethod* m, bool is_virtual); // query fn void register_intrinsic(CallGenerator* cg); // update fn diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/escape.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -490,6 +490,8 @@ } break; } + case Op_CompareAndExchangeP: + case Op_CompareAndExchangeN: case Op_GetAndSetP: case Op_GetAndSetN: { add_objload_to_connection_graph(n, delayed_worklist); @@ -499,6 +501,8 @@ case Op_StoreN: case Op_StoreNKlass: case Op_StorePConditional: + case Op_WeakCompareAndSwapP: + case Op_WeakCompareAndSwapN: case Op_CompareAndSwapP: case Op_CompareAndSwapN: { Node* adr = n->in(MemNode::Address); @@ -698,8 +702,12 @@ case Op_StoreN: case Op_StoreNKlass: case Op_StorePConditional: + case Op_CompareAndExchangeP: + case Op_CompareAndExchangeN: case Op_CompareAndSwapP: case Op_CompareAndSwapN: + case Op_WeakCompareAndSwapP: + case Op_WeakCompareAndSwapN: case Op_GetAndSetP: case Op_GetAndSetN: { Node* adr = n->in(MemNode::Address); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1179,8 +1179,10 @@ // Helper function to do a NULL pointer check. Returned value is // the incoming address with NULL casted away. You are allowed to use the // not-null value only if you are control dependent on the test. +#ifndef PRODUCT extern int explicit_null_checks_inserted, explicit_null_checks_elided; +#endif Node* GraphKit::null_check_common(Node* value, BasicType type, // optional arguments for variations: bool assert_null, @@ -1193,7 +1195,7 @@ value = cast_not_null(value); // Make it appear to be non-null (4962416). return value; } - explicit_null_checks_inserted++; + NOT_PRODUCT(explicit_null_checks_inserted++); // Construct NULL check Node *chk = NULL; @@ -1233,7 +1235,7 @@ // See if the type is contained in NULL_PTR. // If so, then the value is already null. if (t->higher_equal(TypePtr::NULL_PTR)) { - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return value; // Elided null assert quickly! } } else { @@ -1242,7 +1244,7 @@ // type. In other words, "value" was not-null. if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) { // same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ... - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return value; // Elided null check quickly! } } @@ -1282,7 +1284,7 @@ set_control(cfg); Node *res = cast_not_null(value); set_control(oldcontrol); - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return res; } cfg = IfNode::up_one_dom(cfg, /*linear_only=*/ true); @@ -1326,15 +1328,18 @@ IfNode* iff = create_and_map_if(control(), tst, ok_prob, COUNT_UNKNOWN); Node* null_true = _gvn.transform( new IfFalseNode(iff)); set_control( _gvn.transform( new IfTrueNode(iff))); - if (null_true == top()) +#ifndef PRODUCT + if (null_true == top()) { explicit_null_checks_elided++; + } +#endif (*null_control) = null_true; } else { BuildCutout unless(this, tst, ok_prob); // Check for optimizer eliding test at parse time if (stopped()) { // Failure not possible; do not bother making uncommon trap. - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); } else if (assert_null) { uncommon_trap(reason, Deoptimization::Action_make_not_entrant, @@ -3149,6 +3154,19 @@ return membar; } +void GraphKit::insert_store_load_for_barrier() { + Node* mem = reset_memory(); + MemBarNode* mb = MemBarNode::make(C, Op_MemBarVolatile, Compile::AliasIdxBot); + mb->init_req(TypeFunc::Control, control()); + mb->init_req(TypeFunc::Memory, mem); + Node* membar = _gvn.transform(mb); + set_control(_gvn.transform(new ProjNode(membar, TypeFunc::Control))); + Node* newmem = _gvn.transform(new ProjNode(membar, TypeFunc::Memory)); + set_all_memory(mem); + set_memory(newmem, Compile::AliasIdxRaw); +} + + //------------------------------shared_lock------------------------------------ // Emit locking code. FastLockNode* GraphKit::shared_lock(Node* obj) { @@ -3840,7 +3858,7 @@ BasicType bt = T_BYTE; if (UseConcMarkSweepGC && UseCondCardMark) { - insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier + insert_store_load_for_barrier(); __ sync_kit(this); } @@ -4280,8 +4298,7 @@ __ if_then(card_val, BoolTest::ne, young_card); { sync_kit(ideal); - // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier. - insert_mem_bar(Op_MemBarVolatile, oop_store); + insert_store_load_for_barrier(); __ sync_kit(this); Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/graphKit.hpp --- a/hotspot/src/share/vm/opto/graphKit.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/graphKit.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -834,6 +834,7 @@ int next_monitor(); Node* insert_mem_bar(int opcode, Node* precedent = NULL); Node* insert_mem_bar_volatile(int opcode, int alias_idx, Node* precedent = NULL); + void insert_store_load_for_barrier(); // Optional 'precedent' is appended as an extra edge, to force ordering. FastLockNode* shared_lock(Node* obj); void shared_unlock(Node* box, Node* obj); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/ifnode.cpp --- a/hotspot/src/share/vm/opto/ifnode.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/ifnode.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -40,7 +40,9 @@ // Optimization - Graph Style +#ifndef PRODUCT extern int explicit_null_checks_elided; +#endif //============================================================================= //------------------------------Value------------------------------------------ @@ -1504,24 +1506,28 @@ Node* prev_dom = this; int op = Opcode(); // Search up the dominator tree for an If with an identical test - while( dom->Opcode() != op || // Not same opcode? + while (dom->Opcode() != op || // Not same opcode? dom->in(1) != in(1) || // Not same input 1? (req() == 3 && dom->in(2) != in(2)) || // Not same input 2? - prev_dom->in(0) != dom ) { // One path of test does not dominate? - if( dist < 0 ) return NULL; + prev_dom->in(0) != dom) { // One path of test does not dominate? + if (dist < 0) return NULL; dist--; prev_dom = dom; - dom = up_one_dom( dom ); - if( !dom ) return NULL; + dom = up_one_dom(dom); + if (!dom) return NULL; } // Check that we did not follow a loop back to ourselves - if( this == dom ) + if (this == dom) { return NULL; + } - if( dist > 2 ) // Add to count of NULL checks elided +#ifndef PRODUCT + if (dist > 2) { // Add to count of NULL checks elided explicit_null_checks_elided++; + } +#endif return prev_dom; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/lcm.cpp --- a/hotspot/src/share/vm/opto/lcm.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/lcm.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -348,8 +348,10 @@ } // ---- Found an implicit null check +#ifndef PRODUCT extern int implicit_null_checks; implicit_null_checks++; +#endif if( is_decoden ) { // Check if we need to hoist decodeHeapOop_not_null first. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -49,7 +49,9 @@ #include "opto/subnode.hpp" #include "prims/nativeLookup.hpp" #include "runtime/sharedRuntime.hpp" +#ifdef TRACE_HAVE_INTRINSICS #include "trace/traceMacros.hpp" +#endif class LibraryIntrinsic : public InlineCallGenerator { // Extend the set of intrinsics known to the runtime: @@ -241,15 +243,14 @@ // Generates the guards that check whether the result of // Unsafe.getObject should be recorded in an SATB log buffer. void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar); - bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool is_unaligned); + + typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind; + bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned); static bool klass_needs_init_guard(Node* kls); bool inline_unsafe_allocate(); bool inline_unsafe_copyMemory(); bool inline_native_currentThread(); -#ifdef TRACE_HAVE_INTRINSICS - bool inline_native_classID(); - bool inline_native_threadID(); -#endif + bool inline_native_time_funcs(address method, const char* funcName); bool inline_native_isInterrupted(); bool inline_native_Class_query(vmIntrinsics::ID id); @@ -274,9 +275,10 @@ JVMState* arraycopy_restore_alloc_state(AllocateArrayNode* alloc, int& saved_reexecute_sp); void arraycopy_move_allocation_here(AllocateArrayNode* alloc, Node* dest, JVMState* saved_jvms, int saved_reexecute_sp); - typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind; - bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); - bool inline_unsafe_ordered_store(BasicType type); + typedef enum { LS_get_add, LS_get_set, LS_cmp_swap, LS_cmp_swap_weak, LS_cmp_exchange } LoadStoreKind; + MemNode::MemOrd access_kind_to_memord_LS(AccessKind access_kind, bool is_store); + MemNode::MemOrd access_kind_to_memord(AccessKind access_kind); + bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind, AccessKind access_kind); bool inline_unsafe_fence(vmIntrinsics::ID id); bool inline_fp_conversions(vmIntrinsics::ID id); bool inline_number_methods(vmIntrinsics::ID id); @@ -553,86 +555,147 @@ case vmIntrinsics::_inflateStringC: case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress); - case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile, false); - case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile, false); - case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile, false); - case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile, false); - case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, false); - case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, false); - case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, false); - case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, !is_volatile, false); - case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false); - case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, !is_volatile, false); - case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, !is_volatile, false); - case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, !is_volatile, false); - case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, false); - case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile, false); - case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile, false); - case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile, false); - case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, !is_volatile, false); - case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, !is_volatile, false); - - case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, !is_volatile, false); - case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, !is_volatile, false); - case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, !is_volatile, false); - case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, !is_volatile, false); - case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, !is_volatile, false); - case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, !is_volatile, false); - case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, !is_volatile, false); - case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, !is_volatile, false); - - case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, !is_volatile, false); - case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, !is_volatile, false); - case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, !is_volatile, false); - case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, !is_volatile, false); - case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, !is_volatile, false); - case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, !is_volatile, false); - case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, !is_volatile, false); - case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, !is_volatile, false); - - case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, is_volatile, false); - case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, is_volatile, false); - case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, is_volatile, false); - case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, is_volatile, false); - case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, is_volatile, false); - case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, is_volatile, false); - case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, is_volatile, false); - case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, is_volatile, false); - case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, is_volatile, false); - - case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, is_volatile, false); - case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, is_volatile, false); - case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, is_volatile, false); - case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, is_volatile, false); - case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, is_volatile, false); - case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, is_volatile, false); - case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, is_volatile, false); - case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, is_volatile, false); - case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, is_volatile, false); - - case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile, true); - case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile, true); - case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile, true); - case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile, true); - - case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile, true); - case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile, true); - case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile, true); - case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile, true); - - case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg); - case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmpxchg); - case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmpxchg); - - case vmIntrinsics::_putOrderedObject: return inline_unsafe_ordered_store(T_OBJECT); - case vmIntrinsics::_putOrderedInt: return inline_unsafe_ordered_store(T_INT); - case vmIntrinsics::_putOrderedLong: return inline_unsafe_ordered_store(T_LONG); - - case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_xadd); - case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_xadd); - case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_xchg); - case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg); - case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg); + case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Relaxed, false); + case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Relaxed, false); + case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Relaxed, false); + case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, false); + case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, false); + case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, false); + case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, false); + case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Relaxed, false); + case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Relaxed, false); + + case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Relaxed, false); + case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Relaxed, false); + case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Relaxed, false); + case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, false); + case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, false); + case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, false); + case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, false); + case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Relaxed, false); + case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Relaxed, false); + + case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, Relaxed, false); + case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, Relaxed, false); + case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, Relaxed, false); + case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, Relaxed, false); + case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, Relaxed, false); + case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, Relaxed, false); + case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, Relaxed, false); + case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, Relaxed, false); + + case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, Relaxed, false); + case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, Relaxed, false); + case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, Relaxed, false); + case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, Relaxed, false); + case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, Relaxed, false); + case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, Relaxed, false); + case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, Relaxed, false); + case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, Relaxed, false); + + case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Volatile, false); + case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Volatile, false); + case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Volatile, false); + case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Volatile, false); + case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Volatile, false); + case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Volatile, false); + case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Volatile, false); + case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Volatile, false); + case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Volatile, false); + + case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Volatile, false); + case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Volatile, false); + case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Volatile, false); + case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Volatile, false); + case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Volatile, false); + case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Volatile, false); + case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Volatile, false); + case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Volatile, false); + case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Volatile, false); + + case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, true); + case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, true); + case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, true); + case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, true); + + case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, true); + case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, true); + case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, true); + case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, true); + + case vmIntrinsics::_putOrderedObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false); + case vmIntrinsics::_putOrderedInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false); + case vmIntrinsics::_putOrderedLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false); + + case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Acquire, false); + case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Acquire, false); + case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Acquire, false); + case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Acquire, false); + case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Acquire, false); + case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Acquire, false); + case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Acquire, false); + case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Acquire, false); + case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Acquire, false); + + case vmIntrinsics::_putObjectRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false); + case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Release, false); + case vmIntrinsics::_putByteRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Release, false); + case vmIntrinsics::_putShortRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Release, false); + case vmIntrinsics::_putCharRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Release, false); + case vmIntrinsics::_putIntRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false); + case vmIntrinsics::_putLongRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false); + case vmIntrinsics::_putFloatRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Release, false); + case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Release, false); + + case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Opaque, false); + case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Opaque, false); + case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Opaque, false); + case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Opaque, false); + case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Opaque, false); + case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Opaque, false); + case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Opaque, false); + case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Opaque, false); + case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Opaque, false); + + case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Opaque, false); + case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Opaque, false); + case vmIntrinsics::_putByteOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Opaque, false); + case vmIntrinsics::_putShortOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Opaque, false); + case vmIntrinsics::_putCharOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Opaque, false); + case vmIntrinsics::_putIntOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Opaque, false); + case vmIntrinsics::_putLongOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Opaque, false); + case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Opaque, false); + case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Opaque, false); + + case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile); + case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile); + case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap, Volatile); + + case vmIntrinsics::_weakCompareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Relaxed); + case vmIntrinsics::_weakCompareAndSwapObjectAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Acquire); + case vmIntrinsics::_weakCompareAndSwapObjectRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Release); + case vmIntrinsics::_weakCompareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Relaxed); + case vmIntrinsics::_weakCompareAndSwapIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Acquire); + case vmIntrinsics::_weakCompareAndSwapIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Release); + case vmIntrinsics::_weakCompareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Relaxed); + case vmIntrinsics::_weakCompareAndSwapLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Acquire); + case vmIntrinsics::_weakCompareAndSwapLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Release); + + case vmIntrinsics::_compareAndExchangeObjectVolatile: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Volatile); + case vmIntrinsics::_compareAndExchangeObjectAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Acquire); + case vmIntrinsics::_compareAndExchangeObjectRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Release); + case vmIntrinsics::_compareAndExchangeIntVolatile: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Volatile); + case vmIntrinsics::_compareAndExchangeIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Acquire); + case vmIntrinsics::_compareAndExchangeIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Release); + case vmIntrinsics::_compareAndExchangeLongVolatile: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Volatile); + case vmIntrinsics::_compareAndExchangeLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Acquire); + case vmIntrinsics::_compareAndExchangeLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Release); + + case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_get_add, Volatile); + case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_get_add, Volatile); + case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_get_set, Volatile); + case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_get_set, Volatile); + case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_get_set, Volatile); case vmIntrinsics::_loadFence: case vmIntrinsics::_storeFence: @@ -642,8 +705,6 @@ case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: return inline_native_classID(); - case vmIntrinsics::_threadID: return inline_native_threadID(); case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); #endif case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); @@ -1584,6 +1645,13 @@ assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2, "sanity: byte[] and char[] scales agree"); + // Bail when getChar over constants is requested: constant folding would + // reject folding mismatched char access over byte[]. A normal inlining for getChar + // Java method would constant fold nicely instead. + if (!is_store && value->is_Con() && index->is_Con()) { + return false; + } + Node* adr = array_element_address(value, index, T_CHAR); if (is_store) { (void) store_to_memory(control(), adr, ch, T_CHAR, TypeAryPtr::BYTES, MemNode::unordered, @@ -2277,8 +2345,10 @@ return NULL; } -bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile, bool unaligned) { +bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) { if (callee()->is_static()) return false; // caller must have the capability! + guarantee(!is_store || kind != Acquire, "Acquire accesses can be produced only for loads"); + guarantee( is_store || kind != Release, "Release accesses can be produced only for stores"); #ifndef PRODUCT { @@ -2367,7 +2437,42 @@ // the barriers get omitted and the unsafe reference begins to "pollute" // the alias analysis of the rest of the graph, either Compile::can_alias // or Compile::must_alias will throw a diagnostic assert.) - bool need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); + bool need_mem_bar; + switch (kind) { + case Relaxed: + need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM); + break; + case Opaque: + // Opaque uses CPUOrder membars for protection against code movement. + case Acquire: + case Release: + case Volatile: + need_mem_bar = true; + break; + default: + ShouldNotReachHere(); + } + + // Some accesses require access atomicity for all types, notably longs and doubles. + // When AlwaysAtomicAccesses is enabled, all accesses are atomic. + bool requires_atomic_access = false; + switch (kind) { + case Relaxed: + case Opaque: + requires_atomic_access = AlwaysAtomicAccesses; + break; + case Acquire: + case Release: + case Volatile: + requires_atomic_access = true; + break; + default: + ShouldNotReachHere(); + } + + // Figure out the memory ordering. + // Acquire/Release/Volatile accesses require marking the loads/stores with MemOrd + MemNode::MemOrd mo = access_kind_to_memord_LS(kind, is_store); // If we are reading the value of the referent field of a Reference // object (either by using Unsafe directly or through reflection) @@ -2394,22 +2499,30 @@ // and it is not possible to fully distinguish unintended nulls // from intended ones in this API. - if (is_volatile) { - // We need to emit leading and trailing CPU membars (see below) in - // addition to memory membars when is_volatile. This is a little - // too strong, but avoids the need to insert per-alias-type - // volatile membars (for stores; compare Parse::do_put_xxx), which - // we cannot do effectively here because we probably only have a - // rough approximation of type. - need_mem_bar = true; - // For Stores, place a memory ordering barrier now. - if (is_store) { - insert_mem_bar(Op_MemBarRelease); - } else { - if (support_IRIW_for_not_multiple_copy_atomic_cpu) { - insert_mem_bar(Op_MemBarVolatile); + // We need to emit leading and trailing CPU membars (see below) in + // addition to memory membars for special access modes. This is a little + // too strong, but avoids the need to insert per-alias-type + // volatile membars (for stores; compare Parse::do_put_xxx), which + // we cannot do effectively here because we probably only have a + // rough approximation of type. + + switch(kind) { + case Relaxed: + case Opaque: + case Acquire: + break; + case Release: + case Volatile: + if (is_store) { + insert_mem_bar(Op_MemBarRelease); + } else { + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { + insert_mem_bar(Op_MemBarVolatile); + } } - } + break; + default: + ShouldNotReachHere(); } // Memory barrier to prevent normal and 'unsafe' accesses from @@ -2425,10 +2538,12 @@ if (alias_type->element() != NULL || alias_type->field() != NULL) { BasicType bt; if (alias_type->element() != NULL) { - const Type* element = alias_type->element(); + // Use address type to get the element type. Alias type doesn't provide + // enough information (e.g., doesn't differentiate between byte[] and boolean[]). + const Type* element = adr_type->is_aryptr()->elem(); bt = element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type(); } else { - bt = alias_type->field()->type()->basic_type(); + bt = alias_type->field()->layout_type(); } if (bt == T_ARRAY) { // accessing an array field with getObject is not a mismatch @@ -2445,7 +2560,7 @@ // Try to constant fold a load from a constant field ciField* field = alias_type->field(); if (heap_base_oop != top() && - field != NULL && field->is_constant() && field->layout_type() == type) { + field != NULL && field->is_constant() && !mismatched) { // final or stable field const Type* con_type = Type::make_constant(alias_type->field(), heap_base_oop); if (con_type != NULL) { @@ -2453,10 +2568,9 @@ } } if (p == NULL) { - MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered; // To be valid, unsafe loads may depend on other conditions than // the one that guards them: pin the Load node - p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile, unaligned, mismatched); + p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, requires_atomic_access, unaligned, mismatched); // load value switch (type) { case T_BOOLEAN: @@ -2470,7 +2584,9 @@ break; case T_OBJECT: if (need_read_barrier) { - insert_pre_barrier(heap_base_oop, offset, p, !(is_volatile || need_mem_bar)); + // We do not require a mem bar inside pre_barrier if need_mem_bar + // is set: the barriers would be emitted by us. + insert_pre_barrier(heap_base_oop, offset, p, !need_mem_bar); } break; case T_ADDRESS: @@ -2501,9 +2617,8 @@ break; } - MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered; - if (type != T_OBJECT ) { - (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile, unaligned, mismatched); + if (type != T_OBJECT) { + (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, unaligned, mismatched); } else { // Possibly an oop being stored to Java heap or native memory if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { @@ -2524,7 +2639,7 @@ // Update IdealKit memory. __ sync_kit(this); } __ else_(); { - __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile, mismatched); + __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, requires_atomic_access, mismatched); } __ end_if(); // Final sync IdealKit and GraphKit. final_sync(ideal); @@ -2533,14 +2648,23 @@ } } - if (is_volatile) { - if (!is_store) { - insert_mem_bar(Op_MemBarAcquire); - } else { - if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { - insert_mem_bar(Op_MemBarVolatile); + switch(kind) { + case Relaxed: + case Opaque: + case Release: + break; + case Acquire: + case Volatile: + if (!is_store) { + insert_mem_bar(Op_MemBarAcquire); + } else { + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + insert_mem_bar(Op_MemBarVolatile); + } } - } + break; + default: + ShouldNotReachHere(); } if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); @@ -2551,21 +2675,52 @@ //----------------------------inline_unsafe_load_store---------------------------- // This method serves a couple of different customers (depending on LoadStoreKind): // -// LS_cmpxchg: -// public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x); -// public final native boolean compareAndSwapInt( Object o, long offset, int expected, int x); -// public final native boolean compareAndSwapLong( Object o, long offset, long expected, long x); +// LS_cmp_swap: +// +// boolean compareAndSwapObject(Object o, long offset, Object expected, Object x); +// boolean compareAndSwapInt( Object o, long offset, int expected, int x); +// boolean compareAndSwapLong( Object o, long offset, long expected, long x); +// +// LS_cmp_swap_weak: +// +// boolean weakCompareAndSwapObject( Object o, long offset, Object expected, Object x); +// boolean weakCompareAndSwapObjectAcquire(Object o, long offset, Object expected, Object x); +// boolean weakCompareAndSwapObjectRelease(Object o, long offset, Object expected, Object x); +// +// boolean weakCompareAndSwapInt( Object o, long offset, int expected, int x); +// boolean weakCompareAndSwapIntAcquire( Object o, long offset, int expected, int x); +// boolean weakCompareAndSwapIntRelease( Object o, long offset, int expected, int x); +// +// boolean weakCompareAndSwapLong( Object o, long offset, long expected, long x); +// boolean weakCompareAndSwapLongAcquire( Object o, long offset, long expected, long x); +// boolean weakCompareAndSwapLongRelease( Object o, long offset, long expected, long x); // -// LS_xadd: -// public int getAndAddInt( Object o, long offset, int delta) -// public long getAndAddLong(Object o, long offset, long delta) +// LS_cmp_exchange: +// +// Object compareAndExchangeObjectVolatile(Object o, long offset, Object expected, Object x); +// Object compareAndExchangeObjectAcquire( Object o, long offset, Object expected, Object x); +// Object compareAndExchangeObjectRelease( Object o, long offset, Object expected, Object x); +// +// Object compareAndExchangeIntVolatile( Object o, long offset, Object expected, Object x); +// Object compareAndExchangeIntAcquire( Object o, long offset, Object expected, Object x); +// Object compareAndExchangeIntRelease( Object o, long offset, Object expected, Object x); // -// LS_xchg: +// Object compareAndExchangeLongVolatile( Object o, long offset, Object expected, Object x); +// Object compareAndExchangeLongAcquire( Object o, long offset, Object expected, Object x); +// Object compareAndExchangeLongRelease( Object o, long offset, Object expected, Object x); +// +// LS_get_add: +// +// int getAndAddInt( Object o, long offset, int delta) +// long getAndAddLong(Object o, long offset, long delta) +// +// LS_get_set: +// // int getAndSet(Object o, long offset, int newValue) // long getAndSet(Object o, long offset, long newValue) // Object getAndSet(Object o, long offset, Object newValue) // -bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind) { +bool LibraryCallKit::inline_unsafe_load_store(const BasicType type, const LoadStoreKind kind, const AccessKind access_kind) { // This basic scheme here is the same as inline_unsafe_access, but // differs in enough details that combining them would make the code // overly confusing. (This is a true fact! I originally combined @@ -2582,7 +2737,9 @@ // Check the signatures. ciSignature* sig = callee()->signature(); rtype = sig->return_type()->basic_type(); - if (kind == LS_xadd || kind == LS_xchg) { + switch(kind) { + case LS_get_add: + case LS_get_set: { // Check the signatures. #ifdef ASSERT assert(rtype == type, "get and set must return the expected type"); @@ -2591,7 +2748,10 @@ assert(sig->type_at(1)->basic_type() == T_LONG, "get and set offset is long"); assert(sig->type_at(2)->basic_type() == type, "get and set must take expected type as new value/delta"); #endif // ASSERT - } else if (kind == LS_cmpxchg) { + break; + } + case LS_cmp_swap: + case LS_cmp_swap_weak: { // Check the signatures. #ifdef ASSERT assert(rtype == T_BOOLEAN, "CAS must return boolean"); @@ -2599,8 +2759,20 @@ assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object"); assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long"); #endif // ASSERT - } else { - ShouldNotReachHere(); + break; + } + case LS_cmp_exchange: { + // Check the signatures. +#ifdef ASSERT + assert(rtype == type, "CAS must return the expected type"); + assert(sig->count() == 4, "CAS has 4 arguments"); + assert(sig->type_at(0)->basic_type() == T_OBJECT, "CAS base is object"); + assert(sig->type_at(1)->basic_type() == T_LONG, "CAS offset is long"); +#endif // ASSERT + break; + } + default: + ShouldNotReachHere(); } } #endif //PRODUCT @@ -2613,19 +2785,29 @@ Node* offset = NULL; Node* oldval = NULL; Node* newval = NULL; - if (kind == LS_cmpxchg) { - const bool two_slot_type = type2size[type] == 2; - receiver = argument(0); // type: oop - base = argument(1); // type: oop - offset = argument(2); // type: long - oldval = argument(4); // type: oop, int, or long - newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long - } else if (kind == LS_xadd || kind == LS_xchg){ - receiver = argument(0); // type: oop - base = argument(1); // type: oop - offset = argument(2); // type: long - oldval = NULL; - newval = argument(4); // type: oop, int, or long + switch(kind) { + case LS_cmp_swap: + case LS_cmp_swap_weak: + case LS_cmp_exchange: { + const bool two_slot_type = type2size[type] == 2; + receiver = argument(0); // type: oop + base = argument(1); // type: oop + offset = argument(2); // type: long + oldval = argument(4); // type: oop, int, or long + newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long + break; + } + case LS_get_add: + case LS_get_set: { + receiver = argument(0); // type: oop + base = argument(1); // type: oop + offset = argument(2); // type: long + oldval = NULL; + newval = argument(4); // type: oop, int, or long + break; + } + default: + ShouldNotReachHere(); } // Null check receiver. @@ -2650,11 +2832,23 @@ Compile::AliasType* alias_type = C->alias_type(adr_type); assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); - if (kind == LS_xchg && type == T_OBJECT) { - const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type); - if (tjp != NULL) { - value_type = tjp; + switch (kind) { + case LS_get_set: + case LS_cmp_exchange: { + if (type == T_OBJECT) { + const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type); + if (tjp != NULL) { + value_type = tjp; + } + } + break; } + case LS_cmp_swap: + case LS_cmp_swap_weak: + case LS_get_add: + break; + default: + ShouldNotReachHere(); } int alias_idx = C->get_alias_index(adr_type); @@ -2664,9 +2858,22 @@ // into actual barriers on most machines, but we still need rest of // compiler to respect ordering. - insert_mem_bar(Op_MemBarRelease); + switch (access_kind) { + case Relaxed: + case Acquire: + break; + case Release: + case Volatile: + insert_mem_bar(Op_MemBarRelease); + break; + default: + ShouldNotReachHere(); + } insert_mem_bar(Op_MemBarCPUOrder); + // Figure out the memory ordering. + MemNode::MemOrd mo = access_kind_to_memord(access_kind); + // 4984716: MemBars must be inserted before this // memory node in order to avoid a false // dependency which will confuse the scheduler. @@ -2677,25 +2884,45 @@ Node* load_store = NULL; switch(type) { case T_INT: - if (kind == LS_xadd) { - load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type)); - } else if (kind == LS_xchg) { - load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type)); - } else if (kind == LS_cmpxchg) { - load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval)); - } else { - ShouldNotReachHere(); + switch(kind) { + case LS_get_add: + load_store = _gvn.transform(new GetAndAddINode(control(), mem, adr, newval, adr_type)); + break; + case LS_get_set: + load_store = _gvn.transform(new GetAndSetINode(control(), mem, adr, newval, adr_type)); + break; + case LS_cmp_swap_weak: + load_store = _gvn.transform(new WeakCompareAndSwapINode(control(), mem, adr, newval, oldval, mo)); + break; + case LS_cmp_swap: + load_store = _gvn.transform(new CompareAndSwapINode(control(), mem, adr, newval, oldval, mo)); + break; + case LS_cmp_exchange: + load_store = _gvn.transform(new CompareAndExchangeINode(control(), mem, adr, newval, oldval, adr_type, mo)); + break; + default: + ShouldNotReachHere(); } break; case T_LONG: - if (kind == LS_xadd) { - load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type)); - } else if (kind == LS_xchg) { - load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type)); - } else if (kind == LS_cmpxchg) { - load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval)); - } else { - ShouldNotReachHere(); + switch(kind) { + case LS_get_add: + load_store = _gvn.transform(new GetAndAddLNode(control(), mem, adr, newval, adr_type)); + break; + case LS_get_set: + load_store = _gvn.transform(new GetAndSetLNode(control(), mem, adr, newval, adr_type)); + break; + case LS_cmp_swap_weak: + load_store = _gvn.transform(new WeakCompareAndSwapLNode(control(), mem, adr, newval, oldval, mo)); + break; + case LS_cmp_swap: + load_store = _gvn.transform(new CompareAndSwapLNode(control(), mem, adr, newval, oldval, mo)); + break; + case LS_cmp_exchange: + load_store = _gvn.transform(new CompareAndExchangeLNode(control(), mem, adr, newval, oldval, adr_type, mo)); + break; + default: + ShouldNotReachHere(); } break; case T_OBJECT: @@ -2706,65 +2933,109 @@ newval = _gvn.makecon(TypePtr::NULL_PTR); // Reference stores need a store barrier. - if (kind == LS_xchg) { - // If pre-barrier must execute before the oop store, old value will require do_load here. - if (!can_move_pre_barrier()) { - pre_barrier(true /* do_load*/, - control(), base, adr, alias_idx, newval, value_type->make_oopptr(), - NULL /* pre_val*/, + switch(kind) { + case LS_get_set: { + // If pre-barrier must execute before the oop store, old value will require do_load here. + if (!can_move_pre_barrier()) { + pre_barrier(true /* do_load*/, + control(), base, adr, alias_idx, newval, value_type->make_oopptr(), + NULL /* pre_val*/, + T_OBJECT); + } // Else move pre_barrier to use load_store value, see below. + break; + } + case LS_cmp_swap_weak: + case LS_cmp_swap: + case LS_cmp_exchange: { + // Same as for newval above: + if (_gvn.type(oldval) == TypePtr::NULL_PTR) { + oldval = _gvn.makecon(TypePtr::NULL_PTR); + } + // The only known value which might get overwritten is oldval. + pre_barrier(false /* do_load */, + control(), NULL, NULL, max_juint, NULL, NULL, + oldval /* pre_val */, T_OBJECT); - } // Else move pre_barrier to use load_store value, see below. - } else if (kind == LS_cmpxchg) { - // Same as for newval above: - if (_gvn.type(oldval) == TypePtr::NULL_PTR) { - oldval = _gvn.makecon(TypePtr::NULL_PTR); + break; } - // The only known value which might get overwritten is oldval. - pre_barrier(false /* do_load */, - control(), NULL, NULL, max_juint, NULL, NULL, - oldval /* pre_val */, - T_OBJECT); - } else { - ShouldNotReachHere(); + default: + ShouldNotReachHere(); } #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { Node *newval_enc = _gvn.transform(new EncodePNode(newval, newval->bottom_type()->make_narrowoop())); - if (kind == LS_xchg) { - load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr, - newval_enc, adr_type, value_type->make_narrowoop())); - } else { - assert(kind == LS_cmpxchg, "wrong LoadStore operation"); - Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); - load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr, - newval_enc, oldval_enc)); + + switch(kind) { + case LS_get_set: + load_store = _gvn.transform(new GetAndSetNNode(control(), mem, adr, newval_enc, adr_type, value_type->make_narrowoop())); + break; + case LS_cmp_swap_weak: { + Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); + load_store = _gvn.transform(new WeakCompareAndSwapNNode(control(), mem, adr, newval_enc, oldval_enc, mo)); + break; + } + case LS_cmp_swap: { + Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); + load_store = _gvn.transform(new CompareAndSwapNNode(control(), mem, adr, newval_enc, oldval_enc, mo)); + break; + } + case LS_cmp_exchange: { + Node *oldval_enc = _gvn.transform(new EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); + load_store = _gvn.transform(new CompareAndExchangeNNode(control(), mem, adr, newval_enc, oldval_enc, adr_type, value_type->make_narrowoop(), mo)); + break; + } + default: + ShouldNotReachHere(); } } else #endif - { - if (kind == LS_xchg) { + switch (kind) { + case LS_get_set: load_store = _gvn.transform(new GetAndSetPNode(control(), mem, adr, newval, adr_type, value_type->is_oopptr())); - } else { - assert(kind == LS_cmpxchg, "wrong LoadStore operation"); - load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval)); - } + break; + case LS_cmp_swap_weak: + load_store = _gvn.transform(new WeakCompareAndSwapPNode(control(), mem, adr, newval, oldval, mo)); + break; + case LS_cmp_swap: + load_store = _gvn.transform(new CompareAndSwapPNode(control(), mem, adr, newval, oldval, mo)); + break; + case LS_cmp_exchange: + load_store = _gvn.transform(new CompareAndExchangePNode(control(), mem, adr, newval, oldval, adr_type, value_type->is_oopptr(), mo)); + break; + default: + ShouldNotReachHere(); } - if (kind == LS_cmpxchg) { - // Emit the post barrier only when the actual store happened. - // This makes sense to check only for compareAndSet that can fail to set the value. - // CAS success path is marked more likely since we anticipate this is a performance - // critical path, while CAS failure path can use the penalty for going through unlikely - // path as backoff. Which is still better than doing a store barrier there. - IdealKit ideal(this); - ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); { - sync_kit(ideal); - post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); - ideal.sync_kit(this); - } ideal.end_if(); - final_sync(ideal); - } else { - post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); + + // Emit the post barrier only when the actual store happened. This makes sense + // to check only for LS_cmp_* that can fail to set the value. + // LS_cmp_exchange does not produce any branches by default, so there is no + // boolean result to piggyback on. TODO: When we merge CompareAndSwap with + // CompareAndExchange and move branches here, it would make sense to conditionalize + // post_barriers for LS_cmp_exchange as well. + // + // CAS success path is marked more likely since we anticipate this is a performance + // critical path, while CAS failure path can use the penalty for going through unlikely + // path as backoff. Which is still better than doing a store barrier there. + switch (kind) { + case LS_get_set: + case LS_cmp_exchange: { + post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); + break; + } + case LS_cmp_swap_weak: + case LS_cmp_swap: { + IdealKit ideal(this); + ideal.if_then(load_store, BoolTest::ne, ideal.ConI(0), PROB_STATIC_FREQUENT); { + sync_kit(ideal); + post_barrier(ideal.ctrl(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); + ideal.sync_kit(this); + } ideal.end_if(); + final_sync(ideal); + break; + } + default: + ShouldNotReachHere(); } break; default: @@ -2778,7 +3049,7 @@ Node* proj = _gvn.transform(new SCMemProjNode(load_store)); set_memory(proj, alias_idx); - if (type == T_OBJECT && kind == LS_xchg) { + if (type == T_OBJECT && (kind == LS_get_set || kind == LS_cmp_exchange)) { #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { load_store = _gvn.transform(new DecodeNNode(load_store, load_store->get_ptr_type())); @@ -2797,74 +3068,52 @@ // Add the trailing membar surrounding the access insert_mem_bar(Op_MemBarCPUOrder); - insert_mem_bar(Op_MemBarAcquire); + + switch (access_kind) { + case Relaxed: + case Release: + break; // do nothing + case Acquire: + case Volatile: + insert_mem_bar(Op_MemBarAcquire); + break; + default: + ShouldNotReachHere(); + } assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match"); set_result(load_store); return true; } -//----------------------------inline_unsafe_ordered_store---------------------- -// public native void Unsafe.putOrderedObject(Object o, long offset, Object x); -// public native void Unsafe.putOrderedInt(Object o, long offset, int x); -// public native void Unsafe.putOrderedLong(Object o, long offset, long x); -bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { - // This is another variant of inline_unsafe_access, differing in - // that it always issues store-store ("release") barrier and ensures - // store-atomicity (which only matters for "long"). - - if (callee()->is_static()) return false; // caller must have the capability! - -#ifndef PRODUCT - { - ResourceMark rm; - // Check the signatures. - ciSignature* sig = callee()->signature(); -#ifdef ASSERT - BasicType rtype = sig->return_type()->basic_type(); - assert(rtype == T_VOID, "must return void"); - assert(sig->count() == 3, "has 3 arguments"); - assert(sig->type_at(0)->basic_type() == T_OBJECT, "base is object"); - assert(sig->type_at(1)->basic_type() == T_LONG, "offset is long"); -#endif // ASSERT - } -#endif //PRODUCT - - C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". - - // Get arguments: - Node* receiver = argument(0); // type: oop - Node* base = argument(1); // type: oop - Node* offset = argument(2); // type: long - Node* val = argument(4); // type: oop, int, or long - - // Null check receiver. - receiver = null_check(receiver); - if (stopped()) { - return true; - } - - // Build field offset expression. - assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); - // 32-bit machines ignore the high half of long offsets - offset = ConvL2X(offset); - Node* adr = make_unsafe_address(base, offset); - const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); - const Type *value_type = Type::get_const_basic_type(type); - Compile::AliasType* alias_type = C->alias_type(adr_type); - - insert_mem_bar(Op_MemBarRelease); - insert_mem_bar(Op_MemBarCPUOrder); - // Ensure that the store is atomic for longs: - const bool require_atomic_access = true; - Node* store; - if (type == T_OBJECT) // reference stores need a store barrier. - store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release); - else { - store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access); - } - insert_mem_bar(Op_MemBarCPUOrder); - return true; +MemNode::MemOrd LibraryCallKit::access_kind_to_memord_LS(AccessKind kind, bool is_store) { + MemNode::MemOrd mo = MemNode::unset; + switch(kind) { + case Opaque: + case Relaxed: mo = MemNode::unordered; break; + case Acquire: mo = MemNode::acquire; break; + case Release: mo = MemNode::release; break; + case Volatile: mo = is_store ? MemNode::release : MemNode::acquire; break; + default: + ShouldNotReachHere(); + } + guarantee(mo != MemNode::unset, "Should select memory ordering"); + return mo; +} + +MemNode::MemOrd LibraryCallKit::access_kind_to_memord(AccessKind kind) { + MemNode::MemOrd mo = MemNode::unset; + switch(kind) { + case Opaque: + case Relaxed: mo = MemNode::unordered; break; + case Acquire: mo = MemNode::acquire; break; + case Release: mo = MemNode::release; break; + case Volatile: mo = MemNode::seqcst; break; + default: + ShouldNotReachHere(); + } + guarantee(mo != MemNode::unset, "Should select memory ordering"); + return mo; } bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) { @@ -2932,52 +3181,6 @@ return true; } -#ifdef TRACE_HAVE_INTRINSICS -/* - * oop -> myklass - * myklass->trace_id |= USED - * return myklass->trace_id & ~0x3 - */ -bool LibraryCallKit::inline_native_classID() { - null_check_receiver(); // null-check, then ignore - Node* cls = null_check(argument(1), T_OBJECT); - Node* kls = load_klass_from_mirror(cls, false, NULL, 0); - kls = null_check(kls, T_OBJECT); - ByteSize offset = TRACE_ID_OFFSET; - Node* insp = basic_plus_adr(kls, in_bytes(offset)); - Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); - Node* bits = longcon(~0x03l); // ignore bit 0 & 1 - Node* andl = _gvn.transform(new AndLNode(tvalue, bits)); - Node* clsused = longcon(0x01l); // set the class bit - Node* orl = _gvn.transform(new OrLNode(tvalue, clsused)); - - const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); - store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); - set_result(andl); - return true; -} - -bool LibraryCallKit::inline_native_threadID() { - Node* tls_ptr = NULL; - Node* cur_thr = generate_current_thread(tls_ptr); - Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); - p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); - - Node* threadid = NULL; - size_t thread_id_size = OSThread::thread_id_size(); - if (thread_id_size == (size_t) BytesPerLong) { - threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered)); - } else if (thread_id_size == (size_t) BytesPerInt) { - threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered); - } else { - ShouldNotReachHere(); - } - set_result(threadid); - return true; -} -#endif - //------------------------inline_native_time_funcs-------------- // inline code for System.currentTimeMillis() and System.nanoTime() // these have the same type and signature diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -2417,6 +2417,14 @@ ((bol->in(1)->Opcode() == Op_StorePConditional ) || (bol->in(1)->Opcode() == Op_StoreIConditional ) || (bol->in(1)->Opcode() == Op_StoreLConditional ) || + (bol->in(1)->Opcode() == Op_CompareAndExchangeI ) || + (bol->in(1)->Opcode() == Op_CompareAndExchangeL ) || + (bol->in(1)->Opcode() == Op_CompareAndExchangeP ) || + (bol->in(1)->Opcode() == Op_CompareAndExchangeN ) || + (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI ) || + (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL ) || + (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP ) || + (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN ) || (bol->in(1)->Opcode() == Op_CompareAndSwapI ) || (bol->in(1)->Opcode() == Op_CompareAndSwapL ) || (bol->in(1)->Opcode() == Op_CompareAndSwapP ) || diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/loopnode.hpp --- a/hotspot/src/share/vm/opto/loopnode.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/loopnode.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -285,20 +285,29 @@ Node *incr() const { Node *tmp = cmp_node(); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; } Node *limit() const { Node *tmp = cmp_node(); return (tmp && tmp->req()==3) ? tmp->in(2) : NULL; } Node *stride() const { Node *tmp = incr (); return (tmp && tmp->req()==3) ? tmp->in(2) : NULL; } - Node *phi() const { Node *tmp = incr (); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; } Node *init_trip() const { Node *tmp = phi (); return (tmp && tmp->req()==3) ? tmp->in(1) : NULL; } int stride_con() const; bool stride_is_con() const { Node *tmp = stride (); return (tmp != NULL && tmp->is_Con()); } BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; } + PhiNode *phi() const { + Node *tmp = incr(); + if (tmp && tmp->req() == 3) { + Node* phi = tmp->in(1); + if (phi->is_Phi()) { + return phi->as_Phi(); + } + } + return NULL; + } CountedLoopNode *loopnode() const { // The CountedLoopNode that goes with this CountedLoopEndNode may // have been optimized out by the IGVN so be cautious with the // pattern matching on the graph - if (phi() == NULL) { + PhiNode* iv_phi = phi(); + if (iv_phi == NULL) { return NULL; } - assert(phi()->is_Phi(), "should be PhiNode"); - Node *ln = phi()->in(0); + Node *ln = iv_phi->in(0); if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) { return (CountedLoopNode*)ln; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/macroArrayCopy.cpp --- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -880,8 +880,14 @@ Node* sptr = basic_plus_adr(src, src_off); Node* dptr = basic_plus_adr(dest, dest_off); uint alias_idx = C->get_alias_index(adr_type); - Node* sval = transform_later(LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, TypeInt::INT, T_INT, MemNode::unordered)); - Node* st = transform_later(StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, sval, T_INT, MemNode::unordered)); + bool is_mismatched = (basic_elem_type != T_INT); + Node* sval = transform_later( + LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, + TypeInt::INT, T_INT, MemNode::unordered, LoadNode::DependsOnlyOnTest, + false /*unaligned*/, is_mismatched)); + Node* st = transform_later( + StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, + sval, T_INT, MemNode::unordered)); (*mem)->set_memory_at(alias_idx, st); src_off += BytesPerInt; dest_off += BytesPerInt; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/matcher.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -2307,6 +2307,14 @@ case Op_StorePConditional: case Op_StoreIConditional: case Op_StoreLConditional: + case Op_CompareAndExchangeI: + case Op_CompareAndExchangeL: + case Op_CompareAndExchangeP: + case Op_CompareAndExchangeN: + case Op_WeakCompareAndSwapI: + case Op_WeakCompareAndSwapL: + case Op_WeakCompareAndSwapP: + case Op_WeakCompareAndSwapN: case Op_CompareAndSwapI: case Op_CompareAndSwapL: case Op_CompareAndSwapP: @@ -2407,8 +2415,10 @@ bool push_it = false; if( proj->Opcode() == Op_IfTrue ) { +#ifndef PRODUCT extern int all_null_checks_found; all_null_checks_found++; +#endif if( b->_test._test == BoolTest::ne ) { push_it = true; } @@ -2522,6 +2532,14 @@ // that a monitor exit operation contains a serializing instruction. if (xop == Op_MemBarVolatile || + xop == Op_CompareAndExchangeI || + xop == Op_CompareAndExchangeL || + xop == Op_CompareAndExchangeP || + xop == Op_CompareAndExchangeN || + xop == Op_WeakCompareAndSwapL || + xop == Op_WeakCompareAndSwapP || + xop == Op_WeakCompareAndSwapN || + xop == Op_WeakCompareAndSwapI || xop == Op_CompareAndSwapL || xop == Op_CompareAndSwapP || xop == Op_CompareAndSwapN || diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/memnode.cpp --- a/hotspot/src/share/vm/opto/memnode.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/memnode.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1582,6 +1582,21 @@ return NULL; } +static bool is_mismatched_access(ciConstant con, BasicType loadbt) { + BasicType conbt = con.basic_type(); + switch (conbt) { + case T_BOOLEAN: conbt = T_BYTE; break; + case T_ARRAY: conbt = T_OBJECT; break; + } + switch (loadbt) { + case T_BOOLEAN: loadbt = T_BYTE; break; + case T_NARROWOOP: loadbt = T_OBJECT; break; + case T_ARRAY: loadbt = T_OBJECT; break; + case T_ADDRESS: loadbt = T_OBJECT; break; + } + return (conbt != loadbt); +} + // Try to constant-fold a stable array element. static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { assert(ary->const_oop(), "array should be constant"); @@ -1590,10 +1605,12 @@ // Decode the results of GraphKit::array_element_address. ciArray* aobj = ary->const_oop()->as_array(); ciConstant con = aobj->element_value_by_offset(off); - if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) { + bool is_mismatched = is_mismatched_access(con, loadbt); + assert(!is_mismatched, "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt)); const Type* con_type = Type::make_from_constant(con); - if (con_type != NULL) { + // Guard against erroneous constant folding. + if (!is_mismatched && con_type != NULL) { if (con_type->isa_aryptr()) { // Join with the array element type, in case it is also stable. int dim = ary->stable_dimension(); @@ -1642,7 +1659,7 @@ const bool off_beyond_header = ((uint)off >= (uint)min_base_off); // Try to constant-fold a stable array element. - if (FoldStableValues && ary->is_stable() && ary->const_oop() != NULL) { + if (FoldStableValues && !is_mismatched_access() && ary->is_stable() && ary->const_oop() != NULL) { // Make sure the reference is not into the header and the offset is constant if (off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) { const Type* con_type = fold_stable_ary_elem(ary, off, memory_type()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/memnode.hpp --- a/hotspot/src/share/vm/opto/memnode.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/memnode.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -56,7 +56,9 @@ }; typedef enum { unordered = 0, acquire, // Load has to acquire or be succeeded by MemBarAcquire. - release // Store has to release or be preceded by MemBarRelease. + release, // Store has to release or be preceded by MemBarRelease. + seqcst, // LoadStore has to have both acquire and release semantics. + unset // The memory ordering is not set (used for testing) } MemOrd; protected: MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at ) @@ -848,34 +850,121 @@ virtual uint ideal_reg() const { return Op_RegFlags; } }; +class CompareAndSwapNode : public LoadStoreConditionalNode { +private: + const MemNode::MemOrd _mem_ord; +public: + CompareAndSwapNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : LoadStoreConditionalNode(c, mem, adr, val, ex), _mem_ord(mem_ord) {} + MemNode::MemOrd order() const { + return _mem_ord; + } +}; + +class CompareAndExchangeNode : public LoadStoreNode { +private: + const MemNode::MemOrd _mem_ord; +public: + enum { + ExpectedIn = MemNode::ValueIn+1 // One more input than MemNode + }; + CompareAndExchangeNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord, const TypePtr* at, const Type* t) : + LoadStoreNode(c, mem, adr, val, at, t, 5), _mem_ord(mem_ord) { + init_req(ExpectedIn, ex ); + } + + MemNode::MemOrd order() const { + return _mem_ord; + } +}; //------------------------------CompareAndSwapLNode--------------------------- -class CompareAndSwapLNode : public LoadStoreConditionalNode { +class CompareAndSwapLNode : public CompareAndSwapNode { public: - CompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { } + CompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } virtual int Opcode() const; }; //------------------------------CompareAndSwapINode--------------------------- -class CompareAndSwapINode : public LoadStoreConditionalNode { +class CompareAndSwapINode : public CompareAndSwapNode { public: - CompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { } + CompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } virtual int Opcode() const; }; //------------------------------CompareAndSwapPNode--------------------------- -class CompareAndSwapPNode : public LoadStoreConditionalNode { +class CompareAndSwapPNode : public CompareAndSwapNode { public: - CompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { } + CompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } virtual int Opcode() const; }; //------------------------------CompareAndSwapNNode--------------------------- -class CompareAndSwapNNode : public LoadStoreConditionalNode { +class CompareAndSwapNNode : public CompareAndSwapNode { +public: + CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } + virtual int Opcode() const; +}; + + +//------------------------------WeakCompareAndSwapLNode--------------------------- +class WeakCompareAndSwapLNode : public CompareAndSwapNode { +public: + WeakCompareAndSwapLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } + virtual int Opcode() const; +}; + + +//------------------------------WeakCompareAndSwapINode--------------------------- +class WeakCompareAndSwapINode : public CompareAndSwapNode { +public: + WeakCompareAndSwapINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } + virtual int Opcode() const; +}; + + +//------------------------------WeakCompareAndSwapPNode--------------------------- +class WeakCompareAndSwapPNode : public CompareAndSwapNode { public: - CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreConditionalNode(c, mem, adr, val, ex) { } + WeakCompareAndSwapPNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } + virtual int Opcode() const; +}; + +//------------------------------WeakCompareAndSwapNNode--------------------------- +class WeakCompareAndSwapNNode : public CompareAndSwapNode { +public: + WeakCompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapNode(c, mem, adr, val, ex, mem_ord) { } + virtual int Opcode() const; +}; + +//------------------------------CompareAndExchangeLNode--------------------------- +class CompareAndExchangeLNode : public CompareAndExchangeNode { +public: + CompareAndExchangeLNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, TypeLong::LONG) { } + virtual int Opcode() const; +}; + + +//------------------------------CompareAndExchangeINode--------------------------- +class CompareAndExchangeINode : public CompareAndExchangeNode { +public: + CompareAndExchangeINode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, TypeInt::INT) { } + virtual int Opcode() const; +}; + + +//------------------------------CompareAndExchangePNode--------------------------- +class CompareAndExchangePNode : public CompareAndExchangeNode { +public: + CompareAndExchangePNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, t) { } + virtual int Opcode() const; +}; + +//------------------------------CompareAndExchangeNNode--------------------------- +class CompareAndExchangeNNode : public CompareAndExchangeNode { +public: + CompareAndExchangeNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangeNode(c, mem, adr, val, ex, mem_ord, at, t) { } virtual int Opcode() const; }; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/node.cpp --- a/hotspot/src/share/vm/opto/node.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/node.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -576,17 +576,11 @@ //------------------------------~Node------------------------------------------ // Fancy destructor; eagerly attempt to reclaim Node numberings and storage -extern int reclaim_idx ; -extern int reclaim_in ; -extern int reclaim_node; void Node::destruct() { // Eagerly reclaim unique Node numberings Compile* compile = Compile::current(); if ((uint)_idx+1 == compile->unique()) { compile->set_unique(compile->unique()-1); -#ifdef ASSERT - reclaim_idx++; -#endif } // Clear debug info: Node_Notes* nn = compile->node_notes_at(_idx); @@ -604,43 +598,25 @@ int out_edge_size = _outmax*sizeof(void*); char *edge_end = ((char*)_in) + edge_size; char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out); - char *out_edge_end = out_array + out_edge_size; int node_size = size_of(); // Free the output edge array if (out_edge_size > 0) { -#ifdef ASSERT - if( out_edge_end == compile->node_arena()->hwm() ) - reclaim_in += out_edge_size; // count reclaimed out edges with in edges -#endif compile->node_arena()->Afree(out_array, out_edge_size); } // Free the input edge array and the node itself if( edge_end == (char*)this ) { -#ifdef ASSERT - if( edge_end+node_size == compile->node_arena()->hwm() ) { - reclaim_in += edge_size; - reclaim_node+= node_size; - } -#else // It was; free the input array and object all in one hit +#ifndef ASSERT compile->node_arena()->Afree(_in,edge_size+node_size); #endif } else { - // Free just the input array -#ifdef ASSERT - if( edge_end == compile->node_arena()->hwm() ) - reclaim_in += edge_size; -#endif compile->node_arena()->Afree(_in,edge_size); // Free just the object -#ifdef ASSERT - if( ((char*)this) + node_size == compile->node_arena()->hwm() ) - reclaim_node+= node_size; -#else +#ifndef ASSERT compile->node_arena()->Afree(this,node_size); #endif } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/node.hpp --- a/hotspot/src/share/vm/opto/node.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/node.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -60,6 +60,8 @@ class CodeBuffer; class ConstraintCastNode; class ConNode; +class CompareAndSwapNode; +class CompareAndExchangeNode; class CountedLoopNode; class CountedLoopEndNode; class DecodeNarrowPtrNode; @@ -679,6 +681,9 @@ DEFINE_CLASS_ID(Store, Mem, 1) DEFINE_CLASS_ID(StoreVector, Store, 0) DEFINE_CLASS_ID(LoadStore, Mem, 2) + DEFINE_CLASS_ID(LoadStoreConditional, LoadStore, 0) + DEFINE_CLASS_ID(CompareAndSwap, LoadStoreConditional, 0) + DEFINE_CLASS_ID(CompareAndExchangeNode, LoadStore, 1) DEFINE_CLASS_ID(Region, Node, 5) DEFINE_CLASS_ID(Loop, Region, 0) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/parse.hpp --- a/hotspot/src/share/vm/opto/parse.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/parse.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -104,13 +104,6 @@ // For temporary (stack-allocated, stateless) ilts: InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level); - // InlineTree enum - enum InlineStyle { - Inline_do_not_inline = 0, // - Inline_cha_is_monomorphic = 1, // - Inline_type_profile_monomorphic = 2 // - }; - // See if it is OK to inline. // The receiver is the inline tree for the caller. // @@ -349,9 +342,6 @@ Block* _block; // block currently getting parsed ciBytecodeStream _iter; // stream of this method's bytecodes - int _blocks_merged; // Progress meter: state merges from BB preds - int _blocks_parsed; // Progress meter: BBs actually parsed - const FastLockNode* _synch_lock; // FastLockNode for synchronized method #ifndef PRODUCT diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/parse1.cpp --- a/hotspot/src/share/vm/opto/parse1.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/parse1.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -45,6 +45,7 @@ // the most. Some of the non-static variables are needed in bytecodeInfo.cpp // and eventually should be encapsulated in a proper class (gri 8/18/98). +#ifndef PRODUCT int nodes_created = 0; int methods_parsed = 0; int methods_seen = 0; @@ -53,42 +54,42 @@ int explicit_null_checks_inserted = 0; int explicit_null_checks_elided = 0; -int all_null_checks_found = 0, implicit_null_checks = 0; -int implicit_null_throws = 0; +int all_null_checks_found = 0; +int implicit_null_checks = 0; -int reclaim_idx = 0; -int reclaim_in = 0; -int reclaim_node = 0; - -#ifndef PRODUCT bool Parse::BytecodeParseHistogram::_initialized = false; uint Parse::BytecodeParseHistogram::_bytecodes_parsed [Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_nodes_constructed[Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_nodes_transformed[Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_new_values [Bytecodes::number_of_codes]; -#endif //------------------------------print_statistics------------------------------- -#ifndef PRODUCT void Parse::print_statistics() { tty->print_cr("--- Compiler Statistics ---"); tty->print("Methods seen: %d Methods parsed: %d", methods_seen, methods_parsed); tty->print(" Nodes created: %d", nodes_created); tty->cr(); - if (methods_seen != methods_parsed) + if (methods_seen != methods_parsed) { tty->print_cr("Reasons for parse failures (NOT cumulative):"); + } tty->print_cr("Blocks parsed: %d Blocks seen: %d", blocks_parsed, blocks_seen); - if( explicit_null_checks_inserted ) - tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", explicit_null_checks_inserted, explicit_null_checks_elided, (100*explicit_null_checks_elided)/explicit_null_checks_inserted, all_null_checks_found); - if( all_null_checks_found ) + if (explicit_null_checks_inserted) { + tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", + explicit_null_checks_inserted, explicit_null_checks_elided, + (100*explicit_null_checks_elided)/explicit_null_checks_inserted, + all_null_checks_found); + } + if (all_null_checks_found) { tty->print_cr("%d made implicit (%2d%%)", implicit_null_checks, (100*implicit_null_checks)/all_null_checks_found); - if( implicit_null_throws ) + } + if (SharedRuntime::_implicit_null_throws) { tty->print_cr("%d implicit null exceptions at runtime", - implicit_null_throws); + SharedRuntime::_implicit_null_throws); + } - if( PrintParseStatistics && BytecodeParseHistogram::initialized() ) { + if (PrintParseStatistics && BytecodeParseHistogram::initialized()) { BytecodeParseHistogram::print(); } } @@ -495,7 +496,7 @@ C->dependencies()->assert_evol_method(method()); } - methods_seen++; + NOT_PRODUCT(methods_seen++); // Do some special top-level things. if (depth() == 1 && C->is_osr_compilation()) { @@ -530,8 +531,8 @@ } #endif +#ifndef PRODUCT methods_parsed++; -#ifndef PRODUCT // add method size here to guarantee that inlined methods are added too if (CITime) _total_bytes_compiled += method()->code_size(); @@ -652,7 +653,7 @@ continue; } - blocks_parsed++; + NOT_PRODUCT(blocks_parsed++); progress = true; if (block->is_loop_head() || block->is_handler() || has_irreducible && !block->is_ready()) { @@ -712,9 +713,9 @@ } } +#ifndef PRODUCT blocks_seen += block_count(); -#ifndef PRODUCT // Make sure there are no half-processed blocks remaining. // Every remaining unprocessed block is dead and may be ignored now. for (int rpo = 0; rpo < block_count(); rpo++) { @@ -1446,7 +1447,6 @@ assert(block()->is_merged(), "must be merged before being parsed"); block()->mark_parsed(); - ++_blocks_parsed; // Set iterator to start of block. iter().reset_to_bci(block()->start()); @@ -1596,9 +1596,6 @@ return; } - // Record that a new block has been merged. - ++_blocks_merged; - // Make a region if we know there are multiple or unpredictable inputs. // (Also, if this is a plain fall-through, we might see another region, // which must not be allowed into this block's map.) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/parse2.cpp --- a/hotspot/src/share/vm/opto/parse2.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/parse2.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -44,8 +44,10 @@ #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" +#ifndef PRODUCT extern int explicit_null_checks_inserted, explicit_null_checks_elided; +#endif //---------------------------------array_load---------------------------------- void Parse::array_load(BasicType elem_type) { @@ -997,7 +999,7 @@ return; } - explicit_null_checks_inserted++; + NOT_PRODUCT(explicit_null_checks_inserted++); // Generate real control flow Node *tst = _gvn.transform( new BoolNode( c, btest ) ); @@ -1013,7 +1015,7 @@ set_control(iftrue); if (stopped()) { // Path is dead? - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); if (C->eliminate_boxing()) { // Mark the successor block as parsed branch_block->next_path_num(); @@ -1033,7 +1035,7 @@ set_control(iffalse); if (stopped()) { // Path is dead? - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); if (C->eliminate_boxing()) { // Mark the successor block as parsed next_block->next_path_num(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/phaseX.cpp --- a/hotspot/src/share/vm/opto/phaseX.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/phaseX.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1471,6 +1471,27 @@ } } +// Return counted loop Phi if as a counted loop exit condition, cmp +// compares the the induction variable with n +static PhiNode* countedloop_phi_from_cmp(CmpINode* cmp, Node* n) { + for (DUIterator_Fast imax, i = cmp->fast_outs(imax); i < imax; i++) { + Node* bol = cmp->fast_out(i); + for (DUIterator_Fast i2max, i2 = bol->fast_outs(i2max); i2 < i2max; i2++) { + Node* iff = bol->fast_out(i2); + if (iff->is_CountedLoopEnd()) { + CountedLoopEndNode* cle = iff->as_CountedLoopEnd(); + if (cle->limit() == n) { + PhiNode* phi = cle->phi(); + if (phi != NULL) { + return phi; + } + } + } + } + } + return NULL; +} + void PhaseIterGVN::add_users_to_worklist( Node *n ) { add_users_to_worklist0(n); @@ -1500,18 +1521,7 @@ Node* bol = use->raw_out(0); if (bol->outcnt() > 0) { Node* iff = bol->raw_out(0); - if (use_op == Op_CmpI && - iff->is_CountedLoopEnd()) { - CountedLoopEndNode* cle = iff->as_CountedLoopEnd(); - if (cle->limit() == n && cle->phi() != NULL) { - // If an opaque node feeds into the limit condition of a - // CountedLoop, we need to process the Phi node for the - // induction variable when the opaque node is removed: - // the range of values taken by the Phi is now known and - // so its type is also known. - _worklist.push(cle->phi()); - } - } else if (iff->outcnt() == 2) { + if (iff->outcnt() == 2) { // Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the // phi merging either 0 or 1 onto the worklist Node* ifproj0 = iff->raw_out(0); @@ -1526,6 +1536,15 @@ } } if (use_op == Op_CmpI) { + Node* phi = countedloop_phi_from_cmp((CmpINode*)use, n); + if (phi != NULL) { + // If an opaque node feeds into the limit condition of a + // CountedLoop, we need to process the Phi node for the + // induction variable when the opaque node is removed: + // the range of values taken by the Phi is now known and + // so its type is also known. + _worklist.push(phi); + } Node* in1 = use->in(1); for (uint i = 0; i < in1->outcnt(); i++) { if (in1->raw_out(i)->Opcode() == Op_CastII) { @@ -1714,6 +1733,15 @@ } } } + // If n is used in a counted loop exit condition then the type + // of the counted loop's Phi depends on the type of n. See + // PhiNode::Value(). + if (m_op == Op_CmpI) { + PhiNode* phi = countedloop_phi_from_cmp((CmpINode*)m, n); + if (phi != NULL) { + worklist.push(phi); + } + } } } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/opto/phaseX.hpp --- a/hotspot/src/share/vm/opto/phaseX.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/opto/phaseX.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -431,7 +431,7 @@ // Phase for iteratively performing local, pessimistic GVN-style optimizations. // and ideal transformations on the graph. class PhaseIterGVN : public PhaseGVN { - private: +private: bool _delay_transform; // When true simply register the node when calling transform // instead of actually optimizing it diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/prims/jni.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -73,6 +73,7 @@ #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" +#include "trace/traceMacros.hpp" #include "trace/tracing.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" @@ -88,7 +89,7 @@ #include "jvmci/jvmciRuntime.hpp" #endif -static jint CurrentVersion = JNI_VERSION_1_8; +static jint CurrentVersion = JNI_VERSION_9; #ifdef _WIN32 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); @@ -3929,7 +3930,7 @@ EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } @@ -4149,7 +4150,7 @@ EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/prims/jni.h --- a/hotspot/src/share/vm/prims/jni.h Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/prims/jni.h Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1952,6 +1952,7 @@ #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 #ifdef __cplusplus } /* extern "C" */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp --- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -173,9 +173,7 @@ _global_code_blobs = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(50,true); // iterate over the stub code descriptors and put them in the list first. - int index = 0; - StubCodeDesc* desc; - while ((desc = StubCodeDesc::desc_for_index(++index)) != NULL) { + for (StubCodeDesc* desc = StubCodeDesc::first(); desc != NULL; desc = StubCodeDesc::next(desc)) { _global_code_blobs->append(new JvmtiCodeBlobDesc(desc->name(), desc->begin(), desc->end())); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3940,6 +3940,10 @@ scratch_class->set_methods(_old_methods); // To prevent potential GCing of the old methods, // and to be able to undo operation easily. + Array* old_ordering = the_class->method_ordering(); + the_class->set_method_ordering(scratch_class->method_ordering()); + scratch_class->set_method_ordering(old_ordering); + ConstantPool* old_constants = the_class->constants(); the_class->set_constants(scratch_class->constants()); scratch_class->set_constants(old_constants); // See the previous comment. diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/prims/unsafe.cpp --- a/hotspot/src/share/vm/prims/unsafe.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/prims/unsafe.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1117,6 +1117,44 @@ // JSR166 ------------------------------------------------------------------ +UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) + UnsafeWrapper("Unsafe_CompareAndExchangeObject"); + oop x = JNIHandles::resolve(x_h); + oop e = JNIHandles::resolve(e_h); + oop p = JNIHandles::resolve(obj); + HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); + oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); + if (res == e) + update_barrier_set((void*)addr, x); + return JNIHandles::make_local(env, res); +UNSAFE_END + +UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) + UnsafeWrapper("Unsafe_CompareAndExchangeInt"); + oop p = JNIHandles::resolve(obj); + jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); + return (jint)(Atomic::cmpxchg(x, addr, e)); +UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) + UnsafeWrapper("Unsafe_CompareAndExchangeLong"); + Handle p (THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); +#ifdef SUPPORTS_NATIVE_CX8 + return (jlong)(Atomic::cmpxchg(x, addr, e)); +#else + if (VM_Version::supports_cx8()) + return (jlong)(Atomic::cmpxchg(x, addr, e)); + else { + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); + if (val == e) + Atomic::store(x, addr); + return val; + } +#endif +UNSAFE_END + UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) UnsafeWrapper("Unsafe_CompareAndSwapObject"); oop x = JNIHandles::resolve(x_h); @@ -1384,6 +1422,10 @@ {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, {CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)}, {CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)}, + {CC "compareAndExchangeObjectVolatile", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeObject)}, + {CC "compareAndExchangeIntVolatile", CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)}, + {CC "compareAndExchangeLongVolatile", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)}, + {CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)}, {CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)}, {CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)}, diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -34,6 +34,7 @@ #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" #include "memory/universe.hpp" +#include "oops/constantPool.hpp" #include "oops/oop.inline.hpp" #include "prims/wbtestmethods/parserTests.hpp" #include "prims/whitebox.hpp" @@ -643,12 +644,12 @@ return (mh->queued_for_compilation() || nm != NULL); WB_END -WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method)) +WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method, jint comp_level)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(CompLevel_simple)); + DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(comp_level)); bool result = directive->PrintAssemblyOption; DirectivesStack::release(directive); @@ -1305,6 +1306,38 @@ return (jlong) ikh->constants(); WB_END +WB_ENTRY(jint, WB_GetConstantPoolCacheIndexTag(JNIEnv* env, jobject wb)) + return ConstantPool::CPCACHE_INDEX_TAG; +WB_END + +WB_ENTRY(jint, WB_GetConstantPoolCacheLength(JNIEnv* env, jobject wb, jclass klass)) + instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); + ConstantPool* cp = ikh->constants(); + if (cp->cache() == NULL) { + return -1; + } + return cp->cache()->length(); +WB_END + +WB_ENTRY(jint, WB_ConstantPoolRemapInstructionOperandFromCache(JNIEnv* env, jobject wb, jclass klass, jint index)) + instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass))); + ConstantPool* cp = ikh->constants(); + if (cp->cache() == NULL) { + THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), "Constant pool does not have a cache"); + } + jint cpci = index; + jint cpciTag = ConstantPool::CPCACHE_INDEX_TAG; + if (cpciTag > cpci || cpci >= cp->cache()->length() + cpciTag) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Constant pool cache index is out of range"); + } + jint cpi = cp->remap_instruction_operand_from_cache(cpci); + return cpi; +WB_END + +WB_ENTRY(jint, WB_ConstantPoolEncodeIndyIndex(JNIEnv* env, jobject wb, jint index)) + return ConstantPool::encode_invokedynamic_index(index); +WB_END + WB_ENTRY(void, WB_ClearInlineCaches(JNIEnv* env, jobject wb)) VM_ClearICs clear_ics; VMThread::execute(&clear_ics); @@ -1523,8 +1556,8 @@ #endif // INCLUDE_NMT {CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames }, {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, - {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I", - (void*)&WB_DeoptimizeMethod }, + {CC"deoptimizeMethod0", CC"(Ljava/lang/reflect/Executable;Z)I", + (void*)&WB_DeoptimizeMethod }, {CC"isMethodCompiled0", CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_IsMethodCompiled }, {CC"isMethodCompilable0", CC"(Ljava/lang/reflect/Executable;IZ)Z", @@ -1559,7 +1592,7 @@ CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I", (void*)&WB_MatchesInline}, {CC"shouldPrintAssembly", - CC"(Ljava/lang/reflect/Executable;)Z", + CC"(Ljava/lang/reflect/Executable;I)Z", (void*)&WB_ShouldPrintAssembly}, {CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag}, @@ -1620,6 +1653,12 @@ {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, {CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool }, + {CC"getConstantPoolCacheIndexTag0", CC"()I", (void*)&WB_GetConstantPoolCacheIndexTag}, + {CC"getConstantPoolCacheLength0", CC"(Ljava/lang/Class;)I", (void*)&WB_GetConstantPoolCacheLength}, + {CC"remapInstructionOperandFromCPCache0", + CC"(Ljava/lang/Class;I)I", (void*)&WB_ConstantPoolRemapInstructionOperandFromCache}, + {CC"encodeConstantPoolIndyIndex0", + CC"(I)I", (void*)&WB_ConstantPoolEncodeIndyIndex}, {CC"getMethodBooleanOption", CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;", (void*)&WB_GetMethodBooleaneOption}, diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -372,6 +372,7 @@ { "PreInflateSpin", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "JNIDetachReleasesMonitors", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "UseAltSigs", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "SegmentedHeapDumpThreshold", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, @@ -405,8 +406,9 @@ static AliasedLoggingFlag const aliased_logging_flags[] = { { "TraceClassLoading", LogLevel::Info, true, LogTag::_classload }, + { "TraceClassPaths", LogLevel::Info, true, LogTag::_classpath }, + { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload }, - { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions }, { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation }, { "TraceBiasedLocking", LogLevel::Info, true, LogTag::_biasedlocking }, @@ -2315,6 +2317,17 @@ //=========================================================================================================== // Parsing of main arguments +#if INCLUDE_JVMCI +// Check consistency of jvmci vm argument settings. +bool Arguments::check_jvmci_args_consistency() { + if (!EnableJVMCI && !JVMCIGlobals::check_jvmci_flags_are_consistent()) { + JVMCIGlobals::print_jvmci_args_inconsistency_error_message(); + return false; + } + return true; +} +#endif //INCLUDE_JVMCI + // Check consistency of GC selection bool Arguments::check_gc_consistency() { // Ensure that the user has not selected conflicting sets @@ -2411,6 +2424,9 @@ #endif } #if INCLUDE_JVMCI + + status = status && check_jvmci_args_consistency(); + if (EnableJVMCI) { if (!ScavengeRootsInCode) { warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled"); @@ -3255,7 +3271,7 @@ // PrintSharedArchiveAndExit will turn on // -Xshare:on - // -XX:+TraceClassPaths + // -Xlog:classpath=info if (PrintSharedArchiveAndExit) { if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, true) != Flag::SUCCESS) { return JNI_EINVAL; @@ -3263,9 +3279,7 @@ if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true) != Flag::SUCCESS) { return JNI_EINVAL; } - if (FLAG_SET_CMDLINE(bool, TraceClassPaths, true) != Flag::SUCCESS) { - return JNI_EINVAL; - } + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classpath)); } // Change the default value for flags which have different default values @@ -3318,10 +3332,6 @@ _java_class_path->set_value(copy); FreeHeap(copy); // a copy was made by set_value, so don't need this anymore } - - if (!PrintSharedArchiveAndExit) { - ClassLoader::trace_class_path(tty, "[classpath: ", _java_class_path->value()); - } } static bool has_jar_files(const char* directory) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/arguments.hpp --- a/hotspot/src/share/vm/runtime/arguments.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/arguments.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -505,7 +505,10 @@ static void set_gc_specific_flags(); static inline bool gc_selected(); // whether a gc has been selected static void select_gc_ergonomically(); - +#if INCLUDE_JVMCI + // Check consistency of jvmci vm argument settings. + static bool check_jvmci_args_consistency(); +#endif // Check for consistency in the selection of the garbage collector. static bool check_gc_consistency(); // Check user-selected gc // Check consistency or otherwise of VM argument settings diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -33,9 +33,6 @@ #include "runtime/commandLineFlagConstraintsRuntime.hpp" #include "runtime/os.hpp" #include "utilities/macros.hpp" -#if INCLUDE_JVMCI -#include "jvmci/commandLineFlagConstraintsJVMCI.hpp" -#endif class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint { CommandLineFlagConstraintFunc_bool _constraint; @@ -254,17 +251,6 @@ IGNORE_RANGE, EMIT_CONSTRAINT_CHECK)); -#if INCLUDE_JVMCI - emit_constraint_no(NULL JVMCI_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, - EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, - EMIT_CONSTRAINT_PRODUCT_FLAG, - EMIT_CONSTRAINT_PD_PRODUCT_FLAG, - EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, - EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, - EMIT_CONSTRAINT_NOTPRODUCT_FLAG, - IGNORE_RANGE, - EMIT_CONSTRAINT_CHECK)); -#endif // INCLUDE_JVMCI #ifdef COMPILER1 emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/fprofiler.cpp --- a/hotspot/src/share/vm/runtime/fprofiler.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/fprofiler.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -836,8 +836,7 @@ vm_thread_profiler->inc_thread_ticks(); // Get a snapshot of a current VMThread pc (and leave it running!) - // The call may fail if, for instance the VM thread is interrupted while - // holding the Interrupt_lock or for other reasons. + // The call may fail in some circumstances epc = os::get_thread_pc(VMThread::vm_thread()); if(epc.pc() != NULL) { if (os::dll_address_to_function_name(epc.pc(), buf, sizeof(buf), NULL)) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/frame.cpp --- a/hotspot/src/share/vm/runtime/frame.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/frame.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -662,14 +662,14 @@ st->print("J %d%s %s ", nm->compile_id(), (nm->is_osr_method() ? "%" : ""), ((nm->compiler() != NULL) ? nm->compiler()->name() : "")); + st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]", + buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin()); #if INCLUDE_JVMCI char* jvmciName = nm->jvmci_installed_code_name(buf, buflen); if (jvmciName != NULL) { st->print(" (%s)", jvmciName); } #endif - st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]", - buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin()); } else { st->print("J " PTR_FORMAT, p2i(pc())); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1055,10 +1055,6 @@ "directory) of the dump file (defaults to java_pid.hprof " \ "in the working directory)") \ \ - develop(size_t, SegmentedHeapDumpThreshold, 2*G, \ - "Generate a segmented heap dump (JAVA PROFILE 1.0.2 format) " \ - "when the heap usage is larger than this") \ - \ develop(size_t, HeapDumpSegmentSize, 1*G, \ "Approximate segment size when generating a segmented heap dump") \ \ @@ -1437,9 +1433,6 @@ product(bool, VerifyMergedCPBytecodes, true, \ "Verify bytecodes after RedefineClasses constant pool merging") \ \ - develop(bool, TraceJNIHandleAllocation, false, \ - "Trace allocation/deallocation of JNI handle blocks") \ - \ develop(bool, TraceBytecodes, false, \ "Trace bytecode execution") \ \ @@ -1482,9 +1475,6 @@ develop(bool, TraceCompiledIC, false, \ "Trace changes of compiled IC") \ \ - develop(bool, TraceProtectionDomainVerification, false, \ - "Trace protection domain verification") \ - \ develop(bool, TraceClearedExceptions, false, \ "Print when an exception is forcibly cleared") \ \ @@ -2403,9 +2393,6 @@ product(bool, IgnoreEmptyClassPaths, false, \ "Ignore empty path elements in -classpath") \ \ - product(bool, TraceClassPaths, false, \ - "Trace processing of class paths") \ - \ product(bool, TraceClassLoadingPreorder, false, \ "Trace all classes loaded in order referenced (not loaded)") \ \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/java.cpp --- a/hotspot/src/share/vm/runtime/java.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/java.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -64,6 +64,7 @@ #include "runtime/timer.hpp" #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" +#include "trace/traceMacros.hpp" #include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" @@ -485,7 +486,7 @@ EventThreadEnd event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/jniHandles.cpp --- a/hotspot/src/share/vm/runtime/jniHandles.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/jniHandles.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -278,10 +278,6 @@ // Allocate new block block = new JNIHandleBlock(); _blocks_allocated++; - if (TraceJNIHandleAllocation) { - tty->print_cr("JNIHandleBlock " INTPTR_FORMAT " allocated (%d total blocks)", - p2i(block), _blocks_allocated); - } if (ZapJNIHandleArea) block->zap(); #ifndef PRODUCT // Link new block to list of all allocated blocks @@ -499,10 +495,6 @@ // Not as many free handles as we would like - compute number of new blocks to append _allocate_before_rebuild = (extra + block_size_in_oops - 1) / block_size_in_oops; } - if (TraceJNIHandleAllocation) { - tty->print_cr("Rebuild free list JNIHandleBlock " INTPTR_FORMAT " blocks=%d used=%d free=%d add=%d", - p2i(this), blocks, total-free, free, _allocate_before_rebuild); - } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/mutex.cpp --- a/hotspot/src/share/vm/runtime/mutex.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/mutex.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1320,15 +1320,12 @@ // The rank Mutex::native is an exception in that it is not subject // to the verification rules. // Here are some further notes relating to mutex acquisition anomalies: - // . under Solaris, the interrupt lock gets acquired when doing - // profiling, so any lock could be held. // . it is also ok to acquire Safepoint_lock at the very end while we // already hold Terminator_lock - may happen because of periodic safepoints if (this->rank() != Mutex::native && this->rank() != Mutex::suspend_resume && locks != NULL && locks->rank() <= this->rank() && !SafepointSynchronize::is_at_safepoint() && - this != Interrupt_lock && this != ProfileVM_lock && !(this == Safepoint_lock && contains(locks, Terminator_lock) && SafepointSynchronize::is_synchronizing())) { new_owner->print_owned_locks(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,6 @@ Mutex* JfieldIdCreation_lock = NULL; Monitor* JNICritical_lock = NULL; Mutex* JvmtiThreadState_lock = NULL; -Monitor* JvmtiPendingEvent_lock = NULL; Monitor* Heap_lock = NULL; Mutex* ExpandHeap_lock = NULL; Mutex* AdapterHandlerLibrary_lock = NULL; @@ -73,8 +72,6 @@ Monitor* STS_lock = NULL; Monitor* SLT_lock = NULL; Monitor* FullGCCount_lock = NULL; -Monitor* CMark_lock = NULL; -Mutex* CMRegionStack_lock = NULL; Mutex* SATB_Q_FL_lock = NULL; Monitor* SATB_Q_CBL_mon = NULL; Mutex* Shared_SATB_Q_lock = NULL; @@ -94,11 +91,8 @@ Monitor* Terminator_lock = NULL; Monitor* BeforeExit_lock = NULL; Monitor* Notify_lock = NULL; -Monitor* Interrupt_lock = NULL; -Monitor* ProfileVM_lock = NULL; Mutex* ProfilePrint_lock = NULL; Mutex* ExceptionCache_lock = NULL; -Monitor* ObjAllocPost_lock = NULL; Mutex* OsrList_lock = NULL; #ifndef PRODUCT @@ -184,8 +178,6 @@ } if (UseG1GC) { - def(CMark_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_never); // coordinate concurrent mark thread - def(CMRegionStack_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); def(SATB_Q_FL_lock , Mutex , special, true, Monitor::_safepoint_check_never); def(SATB_Q_CBL_mon , Monitor, nonleaf, true, Monitor::_safepoint_check_never); def(Shared_SATB_Q_lock , Mutex, nonleaf, true, Monitor::_safepoint_check_never); @@ -206,12 +198,10 @@ def(ParGCRareEvent_lock , Mutex , leaf , true, Monitor::_safepoint_check_sometimes); def(DerivedPointerTableGC_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); def(CodeCache_lock , Mutex , special, true, Monitor::_safepoint_check_never); - def(Interrupt_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for interrupt processing def(RawMonitor_lock , Mutex, special, true, Monitor::_safepoint_check_never); def(OopMapCacheAlloc_lock , Mutex, leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation. def(Patching_lock , Mutex , special, true, Monitor::_safepoint_check_never); // used for safepointing and code patching. - def(ObjAllocPost_lock , Monitor, special, false, Monitor::_safepoint_check_never); def(Service_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for service thread operations def(JmethodIdCreation_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // used for creating jmethodIDs. @@ -267,7 +257,6 @@ def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController - def(JvmtiPendingEvent_lock , Monitor, nonleaf, false, Monitor::_safepoint_check_never); // Used by JvmtiCodeBlobEvents def(Management_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // used for JVM management def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes); @@ -277,7 +266,6 @@ def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always); def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); def(Debug3_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); - def(ProfileVM_lock , Monitor, special, false, Monitor::_safepoint_check_never); // used for profiling of the VMThread def(CompileThread_lock , Monitor, nonleaf+5, false, Monitor::_safepoint_check_always); def(PeriodicTask_lock , Monitor, nonleaf+5, true, Monitor::_safepoint_check_sometimes); if (WhiteBoxAPI) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/mutexLocker.hpp --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data -extern Monitor* JvmtiPendingEvent_lock; // a lock on the JVMTI pending events list extern Monitor* Heap_lock; // a lock on the heap extern Mutex* ExpandHeap_lock; // a lock on expanding the heap extern Mutex* AdapterHandlerLibrary_lock; // a lock on the AdapterHandlerLibrary @@ -68,8 +67,6 @@ extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet. extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc -extern Monitor* CMark_lock; // used for concurrent mark thread coordination -extern Mutex* CMRegionStack_lock; // used for protecting accesses to the CM region stack extern Mutex* SATB_Q_FL_lock; // Protects SATB Q // buffer free list. extern Monitor* SATB_Q_CBL_mon; // Protects SATB Q @@ -98,8 +95,6 @@ extern Monitor* Terminator_lock; // a lock used to guard termination of the vm extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks extern Monitor* Notify_lock; // a lock used to synchronize the start-up of the vm -extern Monitor* Interrupt_lock; // a lock used for condition variable mediated interrupt processing -extern Monitor* ProfileVM_lock; // a lock used for profiling the VMThread extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/objectMonitor.cpp --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -401,7 +401,7 @@ if (event.should_commit()) { event.set_klass(((oop)this->object())->klass()); - event.set_previousOwner((TYPE_JAVALANGTHREAD)_previous_owner_tid); + event.set_previousOwner((TYPE_THREAD)_previous_owner_tid); event.set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); event.commit(); } @@ -937,7 +937,7 @@ // get the owner's thread id for the MonitorEnter event // if it is enabled and the thread isn't suspended if (not_suspended && Tracing::is_event_enabled(TraceJavaMonitorEnterEvent)) { - _previous_owner_tid = SharedRuntime::get_java_tid(Self); + _previous_owner_tid = THREAD_TRACE_ID(Self); } #endif @@ -1391,11 +1391,12 @@ jlong notifier_tid, jlong timeout, bool timedout) { + assert(event != NULL, "invariant"); event->set_klass(((oop)this->object())->klass()); - event->set_timeout((TYPE_ULONG)timeout); - event->set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); - event->set_notifier((TYPE_OSTHREAD)notifier_tid); - event->set_timedOut((TYPE_BOOLEAN)timedout); + event->set_timeout(timeout); + event->set_address((TYPE_ADDRESS)this->object_addr()); + event->set_notifier(notifier_tid); + event->set_timedOut(timedout); event->commit(); } @@ -1655,7 +1656,7 @@ iterator->TState = ObjectWaiter::TS_ENTER; } iterator->_notified = 1; - iterator->_notifier_tid = Self->osthread()->thread_id(); + iterator->_notifier_tid = THREAD_TRACE_ID(Self); ObjectWaiter * list = _EntryList; if (list != NULL) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1134,12 +1134,19 @@ MethodHandles::is_signature_polymorphic_intrinsic(id)) { bc = MethodHandles::signature_polymorphic_intrinsic_bytecode(id); - // Need to adjust invokehandle since inlining through signature-polymorphic - // method happened. - if (bc == Bytecodes::_invokehandle && - !MethodHandles::is_signature_polymorphic_method(attached_method())) { - bc = attached_method->is_static() ? Bytecodes::_invokestatic - : Bytecodes::_invokevirtual; + // Adjust invocation mode according to the attached method. + switch (bc) { + case Bytecodes::_invokeinterface: + if (!attached_method->method_holder()->is_interface()) { + bc = Bytecodes::_invokevirtual; + } + break; + case Bytecodes::_invokehandle: + if (!MethodHandles::is_signature_polymorphic_method(attached_method())) { + bc = attached_method->is_static() ? Bytecodes::_invokestatic + : Bytecodes::_invokevirtual; + } + break; } } } else { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/stubCodeGenerator.cpp --- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -36,19 +36,13 @@ // Implementation of StubCodeDesc StubCodeDesc* StubCodeDesc::_list = NULL; -int StubCodeDesc::_count = 0; bool StubCodeDesc::_frozen = false; StubCodeDesc* StubCodeDesc::desc_for(address pc) { StubCodeDesc* p = _list; - while (p != NULL && !p->contains(pc)) p = p->_next; - // p == NULL || p->contains(pc) - return p; -} - -StubCodeDesc* StubCodeDesc::desc_for_index(int index) { - StubCodeDesc* p = _list; - while (p != NULL && p->index() != index) p = p->_next; + while (p != NULL && !p->contains(pc)) { + p = p->_next; + } return p; } @@ -73,43 +67,17 @@ // Implementation of StubCodeGenerator StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) { - _masm = new MacroAssembler(code); - _first_stub = _last_stub = NULL; - _print_code = print_code; -} - -extern "C" { - static int compare_cdesc(const void* void_a, const void* void_b) { - int ai = (*((StubCodeDesc**) void_a))->index(); - int bi = (*((StubCodeDesc**) void_b))->index(); - return ai - bi; - } + _masm = new MacroAssembler(code ); + _print_code = PrintStubCode || print_code; } StubCodeGenerator::~StubCodeGenerator() { - if (PrintStubCode || _print_code) { + if (_print_code) { CodeBuffer* cbuf = _masm->code(); CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); if (blob != NULL) { blob->set_strings(cbuf->strings()); } - bool saw_first = false; - StubCodeDesc* toprint[1000]; - int toprint_len = 0; - for (StubCodeDesc* cdesc = _last_stub; cdesc != NULL; cdesc = cdesc->_next) { - toprint[toprint_len++] = cdesc; - if (cdesc == _first_stub) { saw_first = true; break; } - } - assert(toprint_len == 0 || saw_first, "must get both first & last"); - // Print in reverse order: - qsort(toprint, toprint_len, sizeof(toprint[0]), compare_cdesc); - for (int i = 0; i < toprint_len; i++) { - StubCodeDesc* cdesc = toprint[i]; - cdesc->print(); - tty->cr(); - Disassembler::decode(cdesc->begin(), cdesc->end()); - tty->cr(); - } } } @@ -118,9 +86,12 @@ } void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) { - // default implementation - record the cdesc - if (_first_stub == NULL) _first_stub = cdesc; - _last_stub = cdesc; + if (_print_code) { + cdesc->print(); + tty->cr(); + Disassembler::decode(cdesc->begin(), cdesc->end()); + tty->cr(); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/stubCodeGenerator.hpp --- a/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -39,13 +39,11 @@ class StubCodeDesc: public CHeapObj { private: static StubCodeDesc* _list; // the list of all descriptors - static int _count; // length of list static bool _frozen; // determines whether _list modifications are allowed StubCodeDesc* _next; // the next element in the linked list const char* _group; // the group to which the stub code belongs const char* _name; // the name assigned to the stub code - int _index; // serial number assigned to the stub address _begin; // points to the first byte of the stub code (included) address _end; // points to the first byte after the stub code (excluded) @@ -64,8 +62,10 @@ friend class StubCodeGenerator; public: + static StubCodeDesc* first() { return _list; } + static StubCodeDesc* next(StubCodeDesc* desc) { return desc->_next; } + static StubCodeDesc* desc_for(address pc); // returns the code descriptor for the code containing pc or NULL - static StubCodeDesc* desc_for_index(int); // returns the code descriptor for the index or NULL static const char* name_for(address pc); // returns the name of the code containing pc or NULL StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) { @@ -74,7 +74,6 @@ _next = _list; _group = group; _name = name; - _index = ++_count; // (never zero) _begin = begin; _end = end; _list = this; @@ -84,7 +83,6 @@ const char* group() const { return _group; } const char* name() const { return _name; } - int index() const { return _index; } address begin() const { return _begin; } address end() const { return _end; } int size_in_bytes() const { return _end - _begin; } @@ -97,13 +95,12 @@ // Provides utility functions. class StubCodeGenerator: public StackObj { + private: + bool _print_code; + protected: MacroAssembler* _masm; - StubCodeDesc* _first_stub; - StubCodeDesc* _last_stub; - bool _print_code; - public: StubCodeGenerator(CodeBuffer* code, bool print_code = false); ~StubCodeGenerator(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -324,6 +324,10 @@ // record thread's native stack, stack grows downward MemTracker::record_thread_stack(stack_end(), stack_size()); #endif // INCLUDE_NMT + log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: " + PTR_FORMAT "-" PTR_FORMAT " (" SIZE_FORMAT "k).", + os::current_thread_id(), p2i(stack_base() - stack_size()), + p2i(stack_base()), stack_size()/1024); } @@ -1690,7 +1694,7 @@ EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.set_thread(THREAD_TRACE_ID(this)); event.commit(); } @@ -1795,7 +1799,7 @@ // from java_lang_Thread object EventThreadEnd event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.set_thread(THREAD_TRACE_ID(this)); event.commit(); } @@ -1924,6 +1928,10 @@ } #endif // INCLUDE_ALL_GCS + log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").", + exit_type == JavaThread::normal_exit ? "exiting" : "detaching", + os::current_thread_id()); + // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } @@ -2491,18 +2499,25 @@ // warning("Guarding at " PTR_FORMAT " for len " SIZE_FORMAT "\n", low_addr, len); if (allocate && !os::create_stack_guard_pages((char *) low_addr, len)) { - warning("Attempt to allocate stack guard pages failed."); + log_warning(os, thread)("Attempt to allocate stack guard pages failed."); return; } if (os::guard_memory((char *) low_addr, len)) { _stack_guard_state = stack_guard_enabled; } else { - warning("Attempt to protect stack guard pages failed."); + log_warning(os, thread)("Attempt to protect stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); if (os::uncommit_memory((char *) low_addr, len)) { - warning("Attempt to deallocate stack guard pages failed."); + log_warning(os, thread)("Attempt to deallocate stack guard pages failed."); } + return; } + + log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages activated: " + PTR_FORMAT "-" PTR_FORMAT ".", + os::current_thread_id(), p2i(low_addr), p2i(low_addr + len)); + } void JavaThread::remove_stack_guard_pages() { @@ -2515,16 +2530,25 @@ if (os::remove_stack_guard_pages((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { - warning("Attempt to deallocate stack guard pages failed."); + log_warning(os, thread)("Attempt to deallocate stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); + return; } } else { if (_stack_guard_state == stack_guard_unused) return; if (os::unguard_memory((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { - warning("Attempt to unprotect stack guard pages failed."); + log_warning(os, thread)("Attempt to unprotect stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); + return; } } + + log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages removed: " + PTR_FORMAT "-" PTR_FORMAT ".", + os::current_thread_id(), p2i(low_addr), p2i(low_addr + len)); + } void JavaThread::enable_stack_reserved_zone() { @@ -3530,6 +3554,10 @@ return status; } + if (TRACE_INITIALIZE() != JNI_OK) { + vm_exit_during_initialization("Failed to initialize tracing backend"); + } + // Should be done after the heap is fully created main_thread->cache_global_variables(); @@ -3598,11 +3626,6 @@ quicken_jni_functions(); - // Must be run after init_ft which initializes ft_enabled - if (TRACE_INITIALIZE() != JNI_OK) { - vm_exit_during_initialization("Failed to initialize tracing backend"); - } - // No more stub generation allowed after that point. StubCodeDesc::freeze(); @@ -4110,6 +4133,7 @@ if (version == JNI_VERSION_1_4) return JNI_TRUE; if (version == JNI_VERSION_1_6) return JNI_TRUE; if (version == JNI_VERSION_1_8) return JNI_TRUE; + if (version == JNI_VERSION_9) return JNI_TRUE; return JNI_FALSE; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/thread.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -448,7 +448,8 @@ void incr_allocated_bytes(jlong size) { _allocated_bytes += size; } inline jlong cooked_allocated_bytes(); - TRACE_DATA* trace_data() { return &_trace_data; } + TRACE_DEFINE_THREAD_TRACE_DATA_OFFSET; + TRACE_DATA* trace_data() const { return &_trace_data; } const ThreadExt& ext() const { return _ext; } ThreadExt& ext() { return _ext; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -960,7 +960,6 @@ nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _comp_level, int) \ nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ - nonstatic_field(nmethod, _marked_for_deoptimization, bool) \ \ unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \ \ @@ -2006,10 +2005,20 @@ declare_c2_type(LoadStoreNode, Node) \ declare_c2_type(StorePConditionalNode, LoadStoreNode) \ declare_c2_type(StoreLConditionalNode, LoadStoreNode) \ - declare_c2_type(CompareAndSwapLNode, LoadStoreNode) \ - declare_c2_type(CompareAndSwapINode, LoadStoreNode) \ - declare_c2_type(CompareAndSwapPNode, LoadStoreNode) \ - declare_c2_type(CompareAndSwapNNode, LoadStoreNode) \ + declare_c2_type(CompareAndSwapNode, LoadStoreConditionalNode) \ + declare_c2_type(CompareAndSwapLNode, CompareAndSwapNode) \ + declare_c2_type(CompareAndSwapINode, CompareAndSwapNode) \ + declare_c2_type(CompareAndSwapPNode, CompareAndSwapNode) \ + declare_c2_type(CompareAndSwapNNode, CompareAndSwapNode) \ + declare_c2_type(WeakCompareAndSwapLNode, CompareAndSwapNode) \ + declare_c2_type(WeakCompareAndSwapINode, CompareAndSwapNode) \ + declare_c2_type(WeakCompareAndSwapPNode, CompareAndSwapNode) \ + declare_c2_type(WeakCompareAndSwapNNode, CompareAndSwapNode) \ + declare_c2_type(CompareAndExchangeNode, LoadStoreNode) \ + declare_c2_type(CompareAndExchangeLNode, CompareAndExchangeNode) \ + declare_c2_type(CompareAndExchangeINode, CompareAndExchangeNode) \ + declare_c2_type(CompareAndExchangePNode, CompareAndExchangeNode) \ + declare_c2_type(CompareAndExchangeNNode, CompareAndExchangeNode) \ declare_c2_type(MulNode, Node) \ declare_c2_type(MulINode, MulNode) \ declare_c2_type(MulLNode, MulNode) \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/vmThread.cpp --- a/hotspot/src/share/vm/runtime/vmThread.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/vmThread.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -359,7 +359,7 @@ // Only write caller thread information for non-concurrent vm operations. // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown. // This is because the caller thread could have exited already. - event.set_caller(is_concurrent ? 0 : op->calling_thread()->osthread()->thread_id()); + event.set_caller(is_concurrent ? 0 : THREAD_TRACE_ID(op->calling_thread())); event.commit(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/vm_operations.cpp --- a/hotspot/src/share/vm/runtime/vm_operations.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -485,6 +485,10 @@ } } +void VM_PrintCompileQueue::doit() { + CompileBroker::print_compile_queues(_out); +} + #if INCLUDE_SERVICES void VM_PrintClassHierarchy::doit() { KlassHierarchy::print_class_hierarchy(_out, _print_interfaces, _print_subclasses, _classname); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/runtime/vm_operations.hpp --- a/hotspot/src/share/vm/runtime/vm_operations.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -105,6 +105,7 @@ template(DumpHashtable) \ template(DumpTouchedMethods) \ template(MarkActiveNMethods) \ + template(PrintCompileQueue) \ template(PrintClassHierarchy) \ class VM_Operation: public CHeapObj { @@ -421,6 +422,17 @@ void doit(); }; +class VM_PrintCompileQueue: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCompileQueue(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCompileQueue; } + Mode evaluation_mode() const { return _safepoint; } + void doit(); +}; + #if INCLUDE_SERVICES class VM_PrintClassHierarchy: public VM_Operation { private: diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/services/diagnosticCommand.cpp --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -893,7 +893,8 @@ } void CompileQueueDCmd::execute(DCmdSource source, TRAPS) { - CompileBroker::print_compile_queues(output()); + VM_PrintCompileQueue printCompileQueueOp(output()); + VMThread::execute(&printCompileQueueOp); } void CodeListDCmd::execute(DCmdSource source, TRAPS) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/services/heapDumper.cpp --- a/hotspot/src/share/vm/services/heapDumper.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/services/heapDumper.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,8 +53,7 @@ * src/share/demo/jvmti/hprof/hprof_io.c * * - * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" - * (0-terminated) + * header "JAVA PROFILE 1.0.2" (0-terminated) * * u4 size of identifiers. Identifiers are used to represent * UTF8 strings, objects, stack traces, etc. They usually @@ -385,6 +384,8 @@ size_t _size; size_t _pos; + jlong _dump_start; + char* _error; // error message when I/O fails void set_file_descriptor(int fd) { _fd = fd; } @@ -408,6 +409,10 @@ bool is_open() const { return file_descriptor() >= 0; } void flush(); + jlong dump_start() const { return _dump_start; } + void set_dump_start(jlong pos); + julong current_record_length(); + // total number of bytes written to the disk julong bytes_written() const { return _bytes_written; } @@ -449,6 +454,7 @@ _pos = 0; _error = NULL; _bytes_written = 0L; + _dump_start = (jlong)-1; _fd = os::create_binary_file(path, false); // don't replace existing file // if the open failed we record the error @@ -476,6 +482,22 @@ } } +// sets the dump starting position +void DumpWriter::set_dump_start(jlong pos) { + _dump_start = pos; +} + +julong DumpWriter::current_record_length() { + if (is_open()) { + // calculate the size of the dump record + julong dump_end = bytes_written() + bytes_unwritten(); + assert(dump_end == (size_t)current_offset(), "checking"); + julong dump_len = dump_end - dump_start() - 4; + return dump_len; + } + return 0; +} + // write directly to the file void DumpWriter::write_internal(void* s, size_t len) { if (is_open()) { @@ -645,6 +667,18 @@ static void dump_prim_array(DumpWriter* writer, typeArrayOop array); // create HPROF_FRAME record for the given method and bci static void dump_stack_frame(DumpWriter* writer, int frame_serial_num, int class_serial_num, Method* m, int bci); + + // check if we need to truncate an array + static int calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size); + + // writes a HPROF_HEAP_DUMP_SEGMENT record + static void write_dump_header(DumpWriter* writer); + + // fixes up the length of the current dump record + static void write_current_dump_record_length(DumpWriter* writer); + + // fixes up the current dump record and writes HPROF_HEAP_DUMP_END record + static void end_of_dump(DumpWriter* writer); }; // write a header of the given type @@ -1005,50 +1039,102 @@ } } +// Hprof uses an u4 as record length field, +// which means we need to truncate arrays that are too long. +int DumperSupport::calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size) { + BasicType type = ArrayKlass::cast(array->klass())->element_type(); + assert(type >= T_BOOLEAN && type <= T_OBJECT, "invalid array element type"); + + int length = array->length(); + + int type_size; + if (type == T_OBJECT) { + type_size = sizeof(address); + } else { + type_size = type2aelembytes(type); + } + + size_t length_in_bytes = (size_t)length * type_size; + + // Create a new record if the current record is non-empty and the array can't fit. + julong current_record_length = writer->current_record_length(); + if (current_record_length > 0 && + (current_record_length + header_size + length_in_bytes) > max_juint) { + write_current_dump_record_length(writer); + write_dump_header(writer); + + // We now have an empty record. + current_record_length = 0; + } + + // Calculate max bytes we can use. + uint max_bytes = max_juint - (header_size + current_record_length); + + // Array too long for the record? + // Calculate max length and return it. + if (length_in_bytes > max_bytes) { + length = max_bytes / type_size; + length_in_bytes = (size_t)length * type_size; + + warning("cannot dump array of type %s[] with length %d; truncating to length %d", + type2name_tab[type], array->length(), length); + } + return length; +} + // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array void DumperSupport::dump_object_array(DumpWriter* writer, objArrayOop array) { + // sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + sizeof(classID) + short header_size = 1 + 2 * 4 + 2 * sizeof(address); + + int length = calculate_array_max_length(writer, array, header_size); writer->write_u1(HPROF_GC_OBJ_ARRAY_DUMP); writer->write_objectID(array); writer->write_u4(STACK_TRACE_ID); - writer->write_u4((u4)array->length()); + writer->write_u4(length); // array class ID writer->write_classID(array->klass()); // [id]* elements - for (int index=0; indexlength(); index++) { + for (int index = 0; index < length; index++) { oop o = array->obj_at(index); writer->write_objectID(o); } } -#define WRITE_ARRAY(Array, Type, Size) \ - for (int i=0; ilength(); i++) { writer->write_##Size((Size)array->Type##_at(i)); } - +#define WRITE_ARRAY(Array, Type, Size, Length) \ + for (int i = 0; i < Length; i++) { writer->write_##Size((Size)Array->Type##_at(i)); } // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { BasicType type = TypeArrayKlass::cast(array->klass())->element_type(); + // 2 * sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + short header_size = 2 * 1 + 2 * 4 + sizeof(address); + + int length = calculate_array_max_length(writer, array, header_size); + int type_size = type2aelembytes(type); + u4 length_in_bytes = (u4)length * type_size; + writer->write_u1(HPROF_GC_PRIM_ARRAY_DUMP); writer->write_objectID(array); writer->write_u4(STACK_TRACE_ID); - writer->write_u4((u4)array->length()); + writer->write_u4(length); writer->write_u1(type2tag(type)); // nothing to copy - if (array->length() == 0) { + if (length == 0) { return; } // If the byte ordering is big endian then we can copy most types directly - u4 length_in_bytes = (u4)array->length() * type2aelembytes(type); switch (type) { case T_INT : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, int, u4); + WRITE_ARRAY(array, int, u4, length); } else { writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes); } @@ -1060,7 +1146,7 @@ } case T_CHAR : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, char, u2); + WRITE_ARRAY(array, char, u2, length); } else { writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes); } @@ -1068,7 +1154,7 @@ } case T_SHORT : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, short, u2); + WRITE_ARRAY(array, short, u2, length); } else { writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes); } @@ -1076,7 +1162,7 @@ } case T_BOOLEAN : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, bool, u1); + WRITE_ARRAY(array, bool, u1, length); } else { writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes); } @@ -1084,7 +1170,7 @@ } case T_LONG : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, long, u8); + WRITE_ARRAY(array, long, u8, length); } else { writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes); } @@ -1096,14 +1182,14 @@ // use IEEE 754. case T_FLOAT : { - for (int i=0; ilength(); i++) { - dump_float( writer, array->float_at(i) ); + for (int i = 0; i < length; i++) { + dump_float(writer, array->float_at(i)); } break; } case T_DOUBLE : { - for (int i=0; ilength(); i++) { - dump_double( writer, array->double_at(i) ); + for (int i = 0; i < length; i++) { + dump_double(writer, array->double_at(i)); } break; } @@ -1320,8 +1406,6 @@ JavaThread* _oome_thread; Method* _oome_constructor; bool _gc_before_heap_dump; - bool _is_segmented_dump; - jlong _dump_start; GrowableArray* _klass_map; ThreadStackTrace** _stack_traces; int _num_threads; @@ -1340,11 +1424,6 @@ void clear_global_dumper() { _global_dumper = NULL; } void clear_global_writer() { _global_writer = NULL; } - bool is_segmented_dump() const { return _is_segmented_dump; } - void set_segmented_dump() { _is_segmented_dump = true; } - jlong dump_start() const { return _dump_start; } - void set_dump_start(jlong pos); - bool skip_operation() const; // writes a HPROF_LOAD_CLASS record @@ -1369,16 +1448,6 @@ // HPROF_TRACE and HPROF_FRAME records void dump_stack_traces(); - // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record - void write_dump_header(); - - // fixes up the length of the current dump record - void write_current_dump_record_length(); - - // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END - // record in the case of a segmented heap dump) - void end_of_dump(); - public: VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) : VM_GC_Operation(0 /* total collections, dummy, ignored */, @@ -1387,8 +1456,6 @@ gc_before_heap_dump) { _local_writer = writer; _gc_before_heap_dump = gc_before_heap_dump; - _is_segmented_dump = false; - _dump_start = (jlong)-1; _klass_map = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_CLASS_COUNT, true); _stack_traces = NULL; _num_threads = 0; @@ -1428,35 +1495,23 @@ return false; } -// sets the dump starting position -void VM_HeapDumper::set_dump_start(jlong pos) { - _dump_start = pos; -} - - // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record -void VM_HeapDumper::write_dump_header() { - if (writer()->is_open()) { - if (is_segmented_dump()) { - writer()->write_u1(HPROF_HEAP_DUMP_SEGMENT); - } else { - writer()->write_u1(HPROF_HEAP_DUMP); - } - writer()->write_u4(0); // current ticks + // writes a HPROF_HEAP_DUMP_SEGMENT record +void DumperSupport::write_dump_header(DumpWriter* writer) { + if (writer->is_open()) { + writer->write_u1(HPROF_HEAP_DUMP_SEGMENT); + writer->write_u4(0); // current ticks // record the starting position for the dump (its length will be fixed up later) - set_dump_start(writer()->current_offset()); - writer()->write_u4(0); + writer->set_dump_start(writer->current_offset()); + writer->write_u4(0); } } // fixes up the length of the current dump record -void VM_HeapDumper::write_current_dump_record_length() { - if (writer()->is_open()) { - assert(dump_start() >= 0, "no dump start recorded"); - - // calculate the size of the dump record - julong dump_end = writer()->current_offset(); - julong dump_len = (dump_end - dump_start() - 4); +void DumperSupport::write_current_dump_record_length(DumpWriter* writer) { + if (writer->is_open()) { + julong dump_end = writer->bytes_written() + writer->bytes_unwritten(); + julong dump_len = writer->current_record_length(); // record length must fit in a u4 if (dump_len > max_juint) { @@ -1464,17 +1519,18 @@ } // seek to the dump start and fix-up the length - writer()->seek_to_offset(dump_start()); - writer()->write_u4((u4)dump_len); + assert(writer->dump_start() >= 0, "no dump start recorded"); + writer->seek_to_offset(writer->dump_start()); + writer->write_u4((u4)dump_len); // adjust the total size written to keep the bytes written correct. - writer()->adjust_bytes_written(-((jlong) sizeof(u4))); + writer->adjust_bytes_written(-((jlong) sizeof(u4))); // seek to dump end so we can continue - writer()->seek_to_offset(dump_end); + writer->seek_to_offset(dump_end); // no current dump record - set_dump_start((jlong)-1); + writer->set_dump_start((jlong)-1); } } @@ -1482,33 +1538,23 @@ // new segment. void VM_HeapDumper::check_segment_length() { if (writer()->is_open()) { - if (is_segmented_dump()) { - // don't use current_offset that would be too expensive on a per record basis - julong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); - assert(dump_end == (julong)writer()->current_offset(), "checking"); - julong dump_len = (dump_end - dump_start() - 4); - assert(dump_len <= max_juint, "bad dump length"); + julong dump_len = writer()->current_record_length(); - if (dump_len > HeapDumpSegmentSize) { - write_current_dump_record_length(); - write_dump_header(); - } + if (dump_len > 2UL*G) { + DumperSupport::write_current_dump_record_length(writer()); + DumperSupport::write_dump_header(writer()); } } } -// fixes up the current dump record )and writes HPROF_HEAP_DUMP_END -// record in the case of a segmented heap dump) -void VM_HeapDumper::end_of_dump() { - if (writer()->is_open()) { - write_current_dump_record_length(); +// fixes up the current dump record and writes HPROF_HEAP_DUMP_END record +void DumperSupport::end_of_dump(DumpWriter* writer) { + if (writer->is_open()) { + write_current_dump_record_length(writer); - // for segmented dump we write the end record - if (is_segmented_dump()) { - writer()->write_u1(HPROF_HEAP_DUMP_END); - writer()->write_u4(0); - writer()->write_u4(0); - } + writer->write_u1(HPROF_HEAP_DUMP_END); + writer->write_u4(0); + writer->write_u4(0); } } @@ -1686,16 +1732,17 @@ // [HPROF_LOAD_CLASS]* // [[HPROF_FRAME]*|HPROF_TRACE]* // [HPROF_GC_CLASS_DUMP]* -// HPROF_HEAP_DUMP +// [HPROF_HEAP_DUMP_SEGMENT]* +// HPROF_HEAP_DUMP_END // // The HPROF_TRACE records represent the stack traces where the heap dump // is generated and a "dummy trace" record which does not include // any frames. The dummy trace record is used to be referenced as the // unknown object alloc site. // -// The HPROF_HEAP_DUMP record has a length following by sub-records. To allow -// the heap dump be generated in a single pass we remember the position of -// the dump length and fix it up after all sub-records have been written. +// Each HPROF_HEAP_DUMP_SEGMENT record has a length followed by sub-records. +// To allow the heap dump be generated in a single pass we remember the position +// of the dump length and fix it up after all sub-records have been written. // To generate the sub-records we iterate over the heap, writing // HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP // records as we go. Once that is done we write records for some of the GC @@ -1722,15 +1769,9 @@ set_global_dumper(); set_global_writer(); - // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 + // Write the file header - we always use 1.0.2 size_t used = ch->used(); - const char* header; - if (used > SegmentedHeapDumpThreshold) { - set_segmented_dump(); - header = "JAVA PROFILE 1.0.2"; - } else { - header = "JAVA PROFILE 1.0.1"; - } + const char* header = "JAVA PROFILE 1.0.2"; // header is few bytes long - no chance to overflow int writer()->write_raw((void*)header, (int)strlen(header)); @@ -1750,8 +1791,8 @@ // this must be called after _klass_map is built when iterating the classes above. dump_stack_traces(); - // write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT - write_dump_header(); + // write HPROF_HEAP_DUMP_SEGMENT + DumperSupport::write_dump_header(writer()); // Writes HPROF_GC_CLASS_DUMP records ClassLoaderDataGraph::classes_do(&do_class_dump); @@ -1759,9 +1800,9 @@ check_segment_length(); // writes HPROF_GC_INSTANCE_DUMP records. - // After each sub-record is written check_segment_length will be invoked. When - // generated a segmented heap dump this allows us to check if the current - // segment exceeds a threshold and if so, then a new segment is started. + // After each sub-record is written check_segment_length will be invoked + // to check if the current segment exceeds a threshold. If so, a new + // segment is started. // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk // of the heap dump. HeapObjectDumper obj_dumper(this, writer()); @@ -1785,9 +1826,8 @@ StickyClassDumper class_dumper(writer()); SystemDictionary::always_strong_classes_do(&class_dumper); - // fixes up the length of the dump record. In the case of a segmented - // heap then the HPROF_HEAP_DUMP_END record is also written. - end_of_dump(); + // fixes up the length of the dump record and writes the HPROF_HEAP_DUMP_END record. + DumperSupport::end_of_dump(writer()); // Now we clear the global variables, so that a future dumper might run. clear_global_dumper(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/trace/trace.xml --- a/hotspot/src/share/vm/trace/trace.xml Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/trace/trace.xml Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ - + diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/trace/traceBackend.hpp --- a/hotspot/src/share/vm/trace/traceBackend.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/trace/traceBackend.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,10 @@ static void on_unloading_classes(void) { } + + static void on_vm_error(bool) { + } + }; class TraceThreadData { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/trace/traceDataTypes.hpp --- a/hotspot/src/share/vm/trace/traceDataTypes.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/trace/traceDataTypes.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,39 +31,32 @@ enum { CONTENT_TYPE_NONE = 0, - CONTENT_TYPE_BYTES = 1, - CONTENT_TYPE_EPOCHMILLIS = 2, - CONTENT_TYPE_MILLIS = 3, - CONTENT_TYPE_NANOS = 4, - CONTENT_TYPE_TICKS = 5, - CONTENT_TYPE_ADDRESS = 6, + CONTENT_TYPE_CLASS = 20, + CONTENT_TYPE_UTF8 = 21, + CONTENT_TYPE_THREAD = 22, + CONTENT_TYPE_STACKTRACE = 23, + CONTENT_TYPE_BYTES = 24, + CONTENT_TYPE_EPOCHMILLIS = 25, + CONTENT_TYPE_MILLIS = 26, + CONTENT_TYPE_NANOS = 27, + CONTENT_TYPE_TICKS = 28, + CONTENT_TYPE_ADDRESS = 29, + CONTENT_TYPE_PERCENTAGE = 30, - CONTENT_TYPE_OSTHREAD, - CONTENT_TYPE_JAVALANGTHREAD, - CONTENT_TYPE_STACKTRACE, - CONTENT_TYPE_CLASS, - CONTENT_TYPE_PERCENTAGE, - - JVM_CONTENT_TYPES_START = 30, - JVM_CONTENT_TYPES_END = 100 + JVM_CONTENT_TYPES_START = 33, + JVM_CONTENT_TYPES_END = 255 }; enum ReservedEvent { - EVENT_PRODUCERS, + EVENT_METADATA, EVENT_CHECKPOINT, EVENT_BUFFERLOST, - NUM_RESERVED_EVENTS + NUM_RESERVED_EVENTS = JVM_CONTENT_TYPES_END }; typedef enum ReservedEvent ReservedEvent; -typedef u8 classid; -typedef u8 stacktraceid; -typedef u8 methodid; -typedef u8 fieldid; - -class TraceUnicodeString; +class Symbol; #endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP - diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/trace/traceEvent.hpp --- a/hotspot/src/share/vm/trace/traceEvent.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/trace/traceEvent.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,6 @@ _endTime = time; } - public: TraceEvent(EventStartTime timing=TIMED) : _startTime(0), _endTime(0), @@ -76,12 +75,21 @@ { if (T::is_enabled()) { _started = true; - if (timing == TIMED && !T::isInstant) { - static_cast(this)->set_starttime(Tracing::time()); + if (TIMED == timing && !T::isInstant) { + static_cast(this)->set_starttime(Tracing::time()); } } } + public: + void set_starttime(const Ticks& time) { + _startTime = time.value(); + } + + void set_endtime(const Ticks& time) { + _endTime = time.value(); + } + static bool is_enabled() { return Tracing::is_event_enabled(T::eventId); } @@ -90,67 +98,68 @@ return _started; } - void ignoreCheck() { - DEBUG_ONLY(_ignore_check = true); - } - void commit() { if (!should_commit()) { - cancel(); - return; + DEBUG_ONLY(cancel()); + return; } - if (_endTime == 0) { + assert(!_cancelled, "Committing an event that has already been cancelled"); + if (_startTime == 0) { + static_cast(this)->set_starttime(Tracing::time()); + } else if (_endTime == 0) { static_cast(this)->set_endtime(Tracing::time()); } if (static_cast(this)->should_write()) { static_cast(this)->writeEvent(); } - set_commited(); + DEBUG_ONLY(set_commited()); } - void set_starttime(const Ticks& time) { - _startTime = time.value(); - } - - void set_endtime(const Ticks& time) { - _endTime = time.value(); - } - - TraceEventId id() const { + static TraceEventId id() { return T::eventId; } - bool is_instant() const { + static bool is_instant() { return T::isInstant; } - bool is_requestable() const { + static bool is_requestable() { return T::isRequestable; } - bool has_thread() const { + static bool has_thread() { return T::hasThread; } - bool has_stacktrace() const { + static bool has_stacktrace() { return T::hasStackTrace; } void cancel() { - assert(!_committed && !_cancelled, "event was already committed/cancelled"); + assert(!_committed && !_cancelled, + "event was already committed/cancelled"); DEBUG_ONLY(_cancelled = true); } - void set_commited() { - assert(!_committed, "event has already been committed"); - DEBUG_ONLY(_committed = true); - } - ~TraceEvent() { if (_started) { - assert(_ignore_check || _committed || _cancelled, "event was not committed/cancelled"); + assert(_ignore_check || _committed || _cancelled, + "event was not committed/cancelled"); } } + +#ifdef ASSERT + protected: + void ignoreCheck() { + _ignore_check = true; + } + + private: + void set_commited() { + assert(!_committed, "event has already been committed"); + _committed = true; + } +#endif // ASSERT }; #endif // INCLUDE_TRACE diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/trace/traceEventClasses.xsl --- a/hotspot/src/share/vm/trace/traceEventClasses.xsl Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,6 @@ - + - + - - + - - - + type="const char*" sizeop="sizeof_utf(%)"/> + type="const Symbol*" sizeop="sizeof(u8)"/> + type="const Klass*" sizeop="sizeof(u8)"/> + type="const Method*" sizeop="sizeof(u8)"/> - - - - - - - - + + - + sizeop="sizeof(u8)"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/utilities/debug.cpp --- a/hotspot/src/share/vm/utilities/debug.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/utilities/debug.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -51,9 +51,14 @@ #include "services/heapDumper.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" #include "utilities/vmError.hpp" +#if INCLUDE_TRACE +#include "trace/tracing.hpp" +#endif + #ifndef ASSERT # ifdef _DEBUG // NOTE: don't turn the lines below into a comment -- if you're getting @@ -280,6 +285,12 @@ exit(2); } +static void notify_tracing() { +#if INCLUDE_TRACE + Tracing::on_vm_error(true); +#endif +} + void report_insufficient_metaspace(size_t required_size) { warning("\nThe MaxMetaspaceSize of " SIZE_FORMAT " bytes is not large enough.\n" "Either don't specify the -XX:MaxMetaspaceSize=\n" @@ -302,6 +313,8 @@ HeapDumper::dump_heap_from_oome(); } + notify_tracing(); + if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { VMError::report_java_out_of_memory(message); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/utilities/growableArray.hpp --- a/hotspot/src/share/vm/utilities/growableArray.hpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/utilities/growableArray.hpp Mon Mar 21 11:21:08 2016 +0100 @@ -396,7 +396,7 @@ int max = length() - 1; while (max >= min) { - int mid = (max + min) / 2; + int mid = (int)(((uint)max + min) / 2); E value = at(mid); int diff = compare(key, value); if (diff > 0) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/utilities/hashtable.cpp --- a/hotspot/src/share/vm/utilities/hashtable.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/utilities/hashtable.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -383,4 +383,9 @@ template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; +#if INCLUDE_TRACE +template class Hashtable; +template class HashtableEntry; +template class BasicHashtable; +#endif template class BasicHashtable; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/utilities/macros.hpp diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/src/share/vm/utilities/vmError.cpp --- a/hotspot/src/share/vm/utilities/vmError.cpp Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Mar 21 11:21:08 2016 +0100 @@ -1121,6 +1121,10 @@ if (first_error_tid == -1 && Atomic::cmpxchg_ptr(mytid, &first_error_tid, -1) == -1) { + // Initialize time stamps to use the same base. + out.time_stamp().update_to(1); + log.time_stamp().update_to(1); + _id = id; _message = message; _thread = thread; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/TEST.groups Mon Mar 21 11:21:08 2016 +0100 @@ -297,7 +297,8 @@ compiler/types/ \ compiler/uncommontrap/ \ compiler/unsafe/ \ - -compiler/intrinsics/bmi/verifycode \ + -compiler/intrinsics/adler32 \ + -compiler/intrinsics/bmi \ -compiler/intrinsics/mathexact \ -compiler/intrinsics/multiplytolen \ -compiler/intrinsics/sha \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/c1/CanonicalizeArrayLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8150102 8150514 8150534 + * @summary C1 crashes in Canonicalizer::do_ArrayLength() after fix for JDK-8150102 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:+PatchALot CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=0 CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=1 CanonicalizeArrayLength + */ +public class CanonicalizeArrayLength { + int[] arr = new int[42]; + int[] arrNull = null; + + final int[] finalArr = new int[42]; + final int[] finalArrNull = null; + + static int[] staticArr = new int[42]; + static int[] staticArrNull = null; + + static final int[] staticFinalArr = new int[42]; + static final int[] staticFinalArrNull = null; + + public static void main(String... args) { + CanonicalizeArrayLength t = new CanonicalizeArrayLength(); + for (int i = 0; i < 20000; i++) { + if (t.testLocal() != 42) + throw new IllegalStateException(); + if (t.testLocalNull() != 42) + throw new IllegalStateException(); + if (t.testField() != 42) + throw new IllegalStateException(); + if (t.testFieldNull() != 42) + throw new IllegalStateException(); + if (t.testFinalField() != 42) + throw new IllegalStateException(); + if (t.testFinalFieldNull() != 42) + throw new IllegalStateException(); + if (t.testStaticField() != 42) + throw new IllegalStateException(); + if (t.testStaticFieldNull() != 42) + throw new IllegalStateException(); + if (t.testStaticFinalField() != 42) + throw new IllegalStateException(); + if (t.testStaticFinalFieldNull() != 42) + throw new IllegalStateException(); + } + } + + int testField() { + try { + return arr.length; + } catch (Throwable t) { + return -1; + } + } + + int testFieldNull() { + try { + return arrNull.length; + } catch (Throwable t) { + return 42; + } + } + + int testFinalField() { + try { + return finalArr.length; + } catch (Throwable t) { + return -1; + } + } + + int testFinalFieldNull() { + try { + return finalArrNull.length; + } catch (Throwable t) { + return 42; + } + } + + int testStaticField() { + try { + return staticArr.length; + } catch (Throwable t) { + return -1; + } + } + + int testStaticFieldNull() { + try { + return staticArrNull.length; + } catch (Throwable t) { + return 42; + } + } + + int testStaticFinalField() { + try { + return staticFinalArr.length; + } catch (Throwable t) { + return -1; + } + } + + int testStaticFinalFieldNull() { + try { + return staticFinalArrNull.length; + } catch (Throwable t) { + return 42; + } + } + + int testLocal() { + int[] arr = new int[42]; + try { + return arr.length; + } catch (Throwable t) { + return -1; + } + } + + int testLocalNull() { + int[] arrNull = null; + try { + return arrNull.length; + } catch (Throwable t) { + return 42; + } + } + + +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/c2/TestDominatingDeadCheckCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/c2/TestDominatingDeadCheckCast.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8149797 + * @summary node replaced by dominating dead cast during parsing + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=200 -XX:CompileCommand=dontinline,TestDominatingDeadCheckCast::not_inlined TestDominatingDeadCheckCast + * + */ + +public class TestDominatingDeadCheckCast { + + static class A { + int f; + } + + static class B extends A { + } + + static A not_inlined() { + return new A(); + } + + static void inlined(A param) { + param.f = 42; + } + + static A field; + + static void test(boolean flag1, boolean flag2, boolean flag3, boolean flag4, boolean flag5) { + // Go through memory rather than through a local to defeat C2's replace_in_map + field = not_inlined(); + // Speculation adds a CheckCast on entry of this inlined + // method for the parameter + inlined(field); + // Walk up the dominators is depth limited, make the CheckCast + // above unreachable from the last inlined call + if (flag1) { + if (flag2) { + if (flag3) { + // Speculation adds a CheckCast on entry of this + // inlined method for the parameter. This + // CheckCast is replaced by the CheckCast of the + // first inlined method call but the replaced + // CheckCast is still around during parsing. + inlined(field); + // Same as above, some useless control + if (flag4) { + if (flag5) { + // Speculation adds a CheckCast on entry + // of this inlined method for the + // parameter. This CheckCast is replaced + // by the dead CheckCast of the previous + // inlined() call. + inlined(field); + } + } + } + } + } + } + + static public void main(String[] args) { + field = new A(); + for (int i = 0; i < 20000; i++) { + test(true, true, true, true, true); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Mon Mar 21 11:21:08 2016 +0100 @@ -24,25 +24,26 @@ /* * @test TestCompilerDirectivesCompatibilityBase * @bug 8137167 - * @library /testlibrary /test/lib + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase * @summary Test compiler control compatibility with compile command */ +import compiler.testlibrary.CompilerUtils; +import compiler.whitebox.CompilerWhiteBoxTest; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; - import org.testng.annotations.Test; import org.testng.Assert; - import sun.hotspot.WhiteBox; import java.io.BufferedReader; @@ -64,32 +65,38 @@ method = getMethod(TestCompilerDirectivesCompatibilityBase.class, "helper"); nomatch = getMethod(TestCompilerDirectivesCompatibilityBase.class, "another"); - testCompatibility(executor); + int[] levels = CompilerUtils.getAvailableCompilationLevels(); + for (int complevel : levels) { + // Only test the major compilers, ignore profiling levels + if (complevel == CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE || complevel == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION){ + testCompatibility(executor, complevel); + } + } } - public void testCompatibility(CommandExecutor executor) throws Exception { + public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception { // Call all validation twice to catch error when overwriting a directive // Flag is default off expect(!WB.getBooleanVMFlag("PrintAssembly")); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); // load directives that turn it on executor.execute("Compiler.directives_add " + control_on); - expect(WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); - expect(WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); // remove and see that it is true again executor.execute("Compiler.directives_remove"); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); } public void expect(boolean test) throws Exception { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Mon Mar 21 11:21:08 2016 +0100 @@ -24,16 +24,17 @@ /* * @test TestCompilerDirectivesCompatibilityCommandOff * @bug 8137167 - * @library /testlibrary /test/lib + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions * -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false * -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff * @summary Test compiler control compatibility with compile command @@ -55,27 +56,27 @@ public class TestCompilerDirectivesCompatibilityCommandOff extends TestCompilerDirectivesCompatibilityBase { - public void testCompatibility(CommandExecutor executor) throws Exception { + public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception { // Call all validation twice to catch error when overwriting a directive // Flag is default off - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); // load directives that turn it on executor.execute("Compiler.directives_add " + control_on); - expect(WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); - expect(WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); // remove and see that it is false again executor.execute("Compiler.directives_remove"); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); - expect(!WB.shouldPrintAssembly(method)); - expect(!WB.shouldPrintAssembly(nomatch)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(!WB.shouldPrintAssembly(nomatch, comp_level)); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Mon Mar 21 11:21:08 2016 +0100 @@ -24,16 +24,17 @@ /* * @test TestCompilerDirectivesCompatibilityCommandOn * @bug 8137167 - * @library /testlibrary /test/lib + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions * -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+WhiteBoxAPI * TestCompilerDirectivesCompatibilityCommandOn * @summary Test compiler control compatibility with compile command @@ -55,27 +56,27 @@ public class TestCompilerDirectivesCompatibilityCommandOn extends TestCompilerDirectivesCompatibilityBase{ - public void testCompatibility(CommandExecutor executor) throws Exception { + public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception { // Call all validation twice to catch error when overwriting a directive // Flag is default on - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); // load directives that turn it off executor.execute("Compiler.directives_add " + control_off); - expect(!WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); - expect(!WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); // remove and see that it is true again executor.execute("Compiler.directives_remove"); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Mon Mar 21 11:21:08 2016 +0100 @@ -24,16 +24,17 @@ /* * @test TestCompilerDirectivesCompatibilityFlag * @bug 8137167 - * @library /testlibrary /test/lib + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions * -XX:+PrintAssembly -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag * @summary Test compiler control compatibility with compile command */ @@ -54,28 +55,28 @@ public class TestCompilerDirectivesCompatibilityFlag extends TestCompilerDirectivesCompatibilityBase { - public void testCompatibility(CommandExecutor executor) throws Exception { + public void testCompatibility(CommandExecutor executor, int comp_level) throws Exception { // Call all validation twice to catch error when overwriting a directive // Flag is default on expect(WB.getBooleanVMFlag("PrintAssembly")); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); // load directives that turn it off executor.execute("Compiler.directives_add " + control_off); - expect(!WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); - expect(!WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); + expect(!WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); // remove and see that it is true again executor.execute("Compiler.directives_remove"); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); - expect(WB.shouldPrintAssembly(method)); - expect(WB.shouldPrintAssembly(nomatch)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); + expect(WB.shouldPrintAssembly(method, comp_level)); + expect(WB.shouldPrintAssembly(nomatch, comp_level)); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java --- a/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/compilercontrol/share/AbstractTestBase.java Mon Mar 21 11:21:08 2016 +0100 @@ -51,8 +51,9 @@ for (int i = 0; !md.isValid() && i < ATTEMPTS; i++) { md = METHOD_GEN.generateRandomDescriptor(exec); } - if (!md.isValid()) { - System.out.println("WARN: Using predefined pattern"); + if (!md.isValid() || "any.method()".matches(md.getRegexp())) { + /* if we haven't got a valid pattern or it matches any method + leading to timeouts, then use plain standard descriptor */ md = MethodGenerator.commandDescriptor(exec); } return md; diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java --- a/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java Mon Mar 21 11:21:08 2016 +0100 @@ -494,6 +494,29 @@ return s.indexOf("1"); } + static String text1UTF16 = "A" + "\u05d0" + "\u05d1" + "B"; + + @Test(role = Role.TEST_ENTRY) + public static void test_indexOf_immUTF16() { + assertEquals( 3, indexOf_imm1Latin1_needle(text1UTF16), "test_indexOf_immUTF16"); + assertEquals( 1, indexOf_imm1UTF16_needle(text1UTF16), "test_indexOf_immUTF16"); + assertEquals( 1, indexOf_immUTF16_needle(text1UTF16), "test_indexOf_immUTF16"); + } + + @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" }) + static int indexOf_imm1Latin1_needle(String s) { + return s.indexOf("B"); + } + + @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" }) + static int indexOf_imm1UTF16_needle(String s) { + return s.indexOf("\u05d0"); + } + + @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "A" + "\u05d0" + "\u05d1" + "B" }) + static int indexOf_immUTF16_needle(String s) { + return s.indexOf("\u05d0" + "\u05d1"); + } @Test(role = Role.TEST_HELPER, compileAt = 4, warmup = 1, warmupArgs = { "abc", "abcd" }) public static int asmStringCompareTo(String a, String b) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jsr292/ContinuousCallSiteTargetChange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jsr292/ContinuousCallSiteTargetChange.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @library /testlibrary + * @run main ContinuousCallSiteTargetChange + */ +import java.lang.invoke.*; +import jdk.test.lib.*; + +public class ContinuousCallSiteTargetChange { + static void testServer() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", + "-server", "-XX:-TieredCompilation", "-Xbatch", + "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "ContinuousCallSiteTargetChange$Test", "100"); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldNotContain("made not compilable"); + analyzer.shouldNotContain("decompile_count > PerMethodRecompilationCutoff"); + } + + static void testClient() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", + "-client", "-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1", "-Xbatch", + "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "ContinuousCallSiteTargetChange$Test", "100"); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + analyzer.shouldNotContain("made not compilable"); + analyzer.shouldNotContain("decompile_count > PerMethodRecompilationCutoff"); + } + + public static void main(String[] args) throws Exception { + testServer(); + testClient(); + } + + static class Test { + static final MethodType mt = MethodType.methodType(void.class); + static final CallSite cs = new MutableCallSite(mt); + + static final MethodHandle mh = cs.dynamicInvoker(); + + static void f() { + } + + static void test1() throws Throwable { + mh.invokeExact(); + } + + static void test2() throws Throwable { + cs.getTarget().invokeExact(); + } + + static void iteration() throws Throwable { + MethodHandle mh1 = MethodHandles.lookup().findStatic(ContinuousCallSiteTargetChange.Test.class, "f", mt); + cs.setTarget(mh1); + for (int i = 0; i < 20_000; i++) { + test1(); + test2(); + } + } + + public static void main(String[] args) throws Throwable { + int iterations = Integer.parseInt(args[0]); + for (int i = 0; i < iterations; i++) { + iteration(); + } + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java --- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -180,7 +180,10 @@ static void testInterface() { System.out.println("linkToInterface"); - // Monomorphic case (optimized virtual call) + // Monomorphic case (optimized virtual call), concrete target method + run(() -> linkToInterface(new P1(), P1.class)); + + // Monomorphic case (optimized virtual call), default target method run(() -> linkToInterface(new T(), I.class)); // Megamorphic case (virtual call) diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/common/testcases/MultipleAbstractImplementer.java --- a/hotspot/test/compiler/jvmci/common/testcases/MultipleAbstractImplementer.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleAbstractImplementer.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,93 @@ package compiler.jvmci.common.testcases; +import java.util.HashMap; +import java.util.Map; + public abstract class MultipleAbstractImplementer implements MultipleImplementersInterface { + // Different access levels on the fields of this class are used on purpose. + // It is needed to verify jdk.vm.ci.CompilerToVM constant pool related + // methods, e.g. resolveFieldInPool. + + private static int intStaticField = INT_CONSTANT; + final static long longStaticField = LONG_CONSTANT; + volatile static float floatStaticField = FLOAT_CONSTANT; + static double doubleStaticField = DOUBLE_CONSTANT; + public static String stringStaticField = STRING_CONSTANT; + protected static Object objectStaticField = OBJECT_CONSTANT; + + public int intField = INT_CONSTANT; + private long longField = LONG_CONSTANT; + protected float floatField = FLOAT_CONSTANT; + transient double doubleField = DOUBLE_CONSTANT; + volatile String stringField = STRING_CONSTANT; + String stringFieldEmpty = ""; + final Object objectField; + + public MultipleAbstractImplementer() { + intField = Integer.MAX_VALUE; + longField = Long.MAX_VALUE; + floatField = Float.MAX_VALUE; + doubleField = Double.MAX_VALUE; + stringField = "Message"; + objectField = new Object(); + } + public abstract void abstractMethod(); @Override public void finalize() throws Throwable { super.finalize(); } + + public void lambdaUsingMethod2() { + Thread t = new Thread(this::testMethod); + t.start(); + } + + /** + * This method is needed to have "getstatic" and "getfield" instructions + * in the class. These instructions are needed to test + * resolveFieldInPool method, because it needs a bytecode as one of its arguments. + */ + public void printFileds() { + System.out.println(intStaticField); + System.out.println(longStaticField); + System.out.println(floatStaticField); + System.out.println(doubleStaticField); + System.out.println(stringStaticField); + System.out.println(objectStaticField); + System.out.println(intField); + System.out.println(longField); + System.out.println(floatField); + System.out.println(doubleField); + System.out.println(stringField); + System.out.println(stringFieldEmpty); + System.out.println(objectField); + } + + public static void staticMethod() { + System.getProperties(); // calling some static method + Map map = new HashMap(); // calling some constructor + map.put(OBJECT_CONSTANT, OBJECT_CONSTANT); // calling some interface method + map.remove(OBJECT_CONSTANT); // calling some default interface method + } + + @Override + public void instanceMethod() { + toString(); // calling some virtual method + super.toString(); // calling some special method + } + + @Override + public void anonClassMethod() { + new Runnable() { + @Override + public void run() { + System.out.println("Running"); + } + }.run(); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer2.java --- a/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer2.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementer2.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,18 @@ package compiler.jvmci.common.testcases; +import java.util.HashMap; +import java.util.Map; + public class MultipleImplementer2 implements MultipleImplementersInterface { + // Different access levels on the fields of this class are used on purpose. + // It is needed to verify jdk.vm.ci.CompilerToVM constant pool related + // methods, e.g. resolveFieldInPool. + private static int intStaticField = INT_CONSTANT; - static long longStaticField = LONG_CONSTANT; - static float floatStaticField = FLOAT_CONSTANT; + final static long longStaticField = LONG_CONSTANT; + volatile static float floatStaticField = FLOAT_CONSTANT; static double doubleStaticField = DOUBLE_CONSTANT; public static String stringStaticField = STRING_CONSTANT; protected static Object objectStaticField = OBJECT_CONSTANT; @@ -35,9 +42,10 @@ public int intField = INT_CONSTANT; private long longField = LONG_CONSTANT; protected float floatField = FLOAT_CONSTANT; - double doubleField = DOUBLE_CONSTANT; - String stringField = STRING_CONSTANT; - Object objectField = OBJECT_CONSTANT; + transient double doubleField = DOUBLE_CONSTANT; + volatile String stringField = STRING_CONSTANT; + String stringFieldEmpty = ""; + final Object objectField; public MultipleImplementer2() { intField = Integer.MAX_VALUE; @@ -58,12 +66,52 @@ super.finalize(); } - public void interfaceMethodReferral2(MultipleImplementersInterface obj) { - obj.interfaceMethodReferral(obj); - } - public void lambdaUsingMethod2() { Thread t = new Thread(this::testMethod); t.start(); } + + /** + * This method is needed to have "getstatic" and "getfield" instructions + * in the class. These instructions are needed to test + * resolveFieldInPool method, because it needs a bytecode as one of its arguments. + */ + public void printFileds() { + System.out.println(intStaticField); + System.out.println(longStaticField); + System.out.println(floatStaticField); + System.out.println(doubleStaticField); + System.out.println(stringStaticField); + System.out.println(objectStaticField); + System.out.println(intField); + System.out.println(longField); + System.out.println(floatField); + System.out.println(doubleField); + System.out.println(stringField); + System.out.println(stringFieldEmpty); + System.out.println(objectField); + } + + public static void staticMethod() { + System.getProperties(); // calling some static method + Map map = new HashMap(); // calling some constructor + map.put(OBJECT_CONSTANT, OBJECT_CONSTANT); // calling some interface method + map.remove(OBJECT_CONSTANT); // calling some default interface method + } + + @Override + public void instanceMethod() { + toString(); // calling some virtual method + super.toString(); // calling some special method + } + + @Override + public void anonClassMethod() { + new Runnable() { + @Override + public void run() { + System.out.println("Running"); + } + }.run(); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterface.java --- a/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterface.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleImplementersInterface.java Mon Mar 21 11:21:08 2016 +0100 @@ -23,6 +23,9 @@ package compiler.jvmci.common.testcases; +import java.util.HashMap; +import java.util.Map; + public interface MultipleImplementersInterface { int INT_CONSTANT = Integer.MAX_VALUE; @@ -42,12 +45,34 @@ // empty } - default void interfaceMethodReferral(MultipleImplementersInterface obj) { - obj.defaultMethod(); - } - default void lambdaUsingMethod() { Thread t = new Thread(this::defaultMethod); t.start(); } + + default void printFields() { + System.out.println(OBJECT_CONSTANT); + String s = ""; + System.out.println(s); + } + + static void staticMethod() { + System.getProperties(); // calling some static method + Map map = new HashMap(); // calling some constructor + map.put(OBJECT_CONSTANT, OBJECT_CONSTANT); // calling some interface method + map.remove(OBJECT_CONSTANT); // calling some default interface method + } + + default void instanceMethod() { + toString(); // calling some virtual method + } + + default void anonClassMethod() { + new Runnable() { + @Override + public void run() { + System.out.println("Running"); + } + }.run(); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java --- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,118 +27,214 @@ import java.util.HashMap; import java.util.Map; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.internal.misc.SharedSecrets; +import sun.hotspot.WhiteBox; import sun.reflect.ConstantPool; +import sun.reflect.ConstantPool.Tag; +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; /** * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests */ public class ConstantPoolTestCase { - private final Map typeTests; + + private static final Map TAG_TO_TYPE_MAP; + static { + TAG_TO_TYPE_MAP = new HashMap<>(); + TAG_TO_TYPE_MAP.put(Tag.CLASS, CONSTANT_CLASS); + TAG_TO_TYPE_MAP.put(Tag.FIELDREF, CONSTANT_FIELDREF); + TAG_TO_TYPE_MAP.put(Tag.METHODREF, CONSTANT_METHODREF); + TAG_TO_TYPE_MAP.put(Tag.INTERFACEMETHODREF, CONSTANT_INTERFACEMETHODREF); + TAG_TO_TYPE_MAP.put(Tag.STRING, CONSTANT_STRING); + TAG_TO_TYPE_MAP.put(Tag.INTEGER, CONSTANT_INTEGER); + TAG_TO_TYPE_MAP.put(Tag.FLOAT, CONSTANT_FLOAT); + TAG_TO_TYPE_MAP.put(Tag.LONG, CONSTANT_LONG); + TAG_TO_TYPE_MAP.put(Tag.DOUBLE, CONSTANT_DOUBLE); + TAG_TO_TYPE_MAP.put(Tag.NAMEANDTYPE, CONSTANT_NAMEANDTYPE); + TAG_TO_TYPE_MAP.put(Tag.UTF8, CONSTANT_UTF8); + TAG_TO_TYPE_MAP.put(Tag.METHODHANDLE, CONSTANT_METHODHANDLE); + TAG_TO_TYPE_MAP.put(Tag.METHODTYPE, CONSTANT_METHODTYPE); + TAG_TO_TYPE_MAP.put(Tag.INVOKEDYNAMIC, CONSTANT_INVOKEDYNAMIC); + TAG_TO_TYPE_MAP.put(Tag.INVALID, CONSTANT_INVALID); + } + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private final Map typeTests; + + public static enum ConstantTypes { + CONSTANT_CLASS { + @Override + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + ConstantPool constantPoolSS = dummyClass.constantPoolSS; + checkIndex(constantPoolSS, index); + Class klass = constantPoolSS.getClassAt(index); + String klassName = klass.getName(); + TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); + for (TestedCPEntry entry : testedEntries) { + if (entry.klass.replaceAll("/", "\\.").equals(klassName)) { + return entry; + } + } + return null; + } + }, + CONSTANT_FIELDREF { + @Override + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + return this.getTestedCPEntryForMethodAndField(dummyClass, index); + } + }, + CONSTANT_METHODREF { + @Override + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + return this.getTestedCPEntryForMethodAndField(dummyClass, index); + } + }, + CONSTANT_INTERFACEMETHODREF { + @Override + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + return this.getTestedCPEntryForMethodAndField(dummyClass, index); + } + }, + CONSTANT_STRING { + @Override + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + ConstantPool constantPoolSS = dummyClass.constantPoolSS; + checkIndex(constantPoolSS, index); + String value = constantPoolSS.getStringAt(index); + TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); + for (TestedCPEntry entry : testedEntries) { + if (entry.name.equals(value)) { + return entry; + } + } + return null; + } + }, + CONSTANT_INTEGER, + CONSTANT_FLOAT, + CONSTANT_LONG, + CONSTANT_DOUBLE, + CONSTANT_NAMEANDTYPE, + CONSTANT_UTF8, + CONSTANT_METHODHANDLE, + CONSTANT_METHODTYPE, + CONSTANT_INVOKEDYNAMIC { + @Override + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + ConstantPool constantPoolSS = dummyClass.constantPoolSS; + checkIndex(constantPoolSS, index); + int nameAndTypeIndex = constantPoolSS.getNameAndTypeRefIndexAt(index); + String[] info = constantPoolSS.getNameAndTypeRefInfoAt(nameAndTypeIndex); + TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); + for (TestedCPEntry entry : testedEntries) { + if (info[0].equals(entry.name) && info[1].equals(entry.type)) { + return entry; + } + } + return null; + } + }, + CONSTANT_INVALID; + + public TestedCPEntry getTestedCPEntry(DummyClasses dummyClass, int index) { + return null; // returning null by default + } + + public TestedCPEntry[] getAllCPEntriesForType(DummyClasses dummyClass) { + TestedCPEntry[] toReturn = dummyClass.testedCP.get(this); + if (toReturn == null) { + return new TestedCPEntry[0]; + } + return dummyClass.testedCP.get(this); + } + + protected TestedCPEntry getTestedCPEntryForMethodAndField(DummyClasses dummyClass, int index) { + ConstantPool constantPoolSS = dummyClass.constantPoolSS; + checkIndex(constantPoolSS, index); + String[] info = constantPoolSS.getMemberRefInfoAt(index); + TestedCPEntry[] testedEntries = dummyClass.testedCP.get(this); + for (TestedCPEntry entry : testedEntries) { + if (info[0].equals(entry.klass) && info[1].equals(entry.name) && info[2].equals(entry.type)) { + return entry; + } + } + return null; + } + + protected void checkIndex(ConstantPool constantPoolSS, int index) { + ConstantPool.Tag tag = constantPoolSS.getTagAt(index); + ConstantTypes type = mapTagToCPType(tag); + if (!this.equals(type)) { + String msg = String.format("TESTBUG: CP tag should be a %s, but is %s", + this.name(), + type.name()); + throw new Error(msg); + } + } + } public static interface Validator { void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, - ConstantPool constantPoolSS, - ConstantPoolTestsHelper.DummyClasses dummyClass, int index); + ConstantTypes cpType, + DummyClasses dummyClass, + int index); } - public ConstantPoolTestCase(Map typeTests) { + public static class TestedCPEntry { + public final String klass; + public final String name; + public final String type; + public final byte[] opcodes; + public final long accFlags; + + public TestedCPEntry(String klass, String name, String type, byte[] opcodes, long accFlags) { + this.klass = klass; + this.name = name; + this.type = type; + if (opcodes != null) { + this.opcodes = new byte[opcodes.length]; + System.arraycopy(opcodes, 0, this.opcodes, 0, opcodes.length); + } else { + this.opcodes = null; + } + this.accFlags = accFlags; + } + + public TestedCPEntry(String klass, String name, String type, byte[] opcodes) { + this(klass, name, type, opcodes, 0); + } + + public TestedCPEntry(String klass, String name, String type) { + this(klass, name, type, null, 0); + } + } + + public static ConstantTypes mapTagToCPType(Tag tag) { + return TAG_TO_TYPE_MAP.get(tag); + } + + public ConstantPoolTestCase(Map typeTests) { this.typeTests = new HashMap<>(); this.typeTests.putAll(typeTests); } - private void messageOnFail(Throwable t, - ConstantPoolTestsHelper.ConstantTypes cpType, - ConstantPoolTestsHelper.DummyClasses dummyClass, int index) { - ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess(). - getConstantPool(dummyClass.klass); - String msg = String.format("Test for %s constant pool entry of" - + " type %s", - dummyClass.klass, cpType.name()); - switch (cpType) { - case CONSTANT_CLASS: - case CONSTANT_STRING: - case CONSTANT_METHODTYPE: - String utf8 = constantPoolSS - .getUTF8At((int) dummyClass.cp.get(index).value); - msg = String.format("%s (%s) failed with %s", msg, utf8, t); - break; - case CONSTANT_INTEGER: - int intValue = constantPoolSS.getIntAt(index); - msg = String.format("%s (%d) failed with %s", msg, intValue, t); - break; - case CONSTANT_LONG: - long longValue = constantPoolSS.getLongAt(index); - msg = String.format("%s (%d) failed with %s", msg, longValue, t); - break; - case CONSTANT_FLOAT: - float floatValue = constantPoolSS.getFloatAt(index); - msg = String.format("%s (%E) failed with %s", msg, floatValue, t); - break; - case CONSTANT_DOUBLE: - double doubleValue = constantPoolSS.getDoubleAt(index); - msg = String.format("%s (%E) failed with %s", msg, doubleValue, t); - break; - case CONSTANT_UTF8: - String utf8Value = constantPoolSS.getUTF8At(index); - msg = String.format("%s (%s) failed with %s", msg, utf8Value, t); - break; - case CONSTANT_INVOKEDYNAMIC: - index = ((int[]) dummyClass.cp.get(index).value)[1]; - case CONSTANT_NAMEANDTYPE: - String name = constantPoolSS - .getUTF8At(((int[]) dummyClass.cp.get(index).value)[0]); - String type = constantPoolSS - .getUTF8At(((int[]) dummyClass.cp.get(index).value)[1]); - msg = String.format("%s (%s:%s) failed with %s", - msg, name, type, t); - break; - case CONSTANT_METHODHANDLE: - index = ((int[]) dummyClass.cp.get(index).value)[1]; - case CONSTANT_METHODREF: - case CONSTANT_INTERFACEMETHODREF: - case CONSTANT_FIELDREF: - int classIndex = ((int[]) dummyClass.cp.get(index).value)[0]; - int nameAndTypeIndex = ((int[]) dummyClass.cp.get(index).value)[1]; - String cName = constantPoolSS - .getUTF8At((int) dummyClass.cp.get(classIndex).value); - String mName = constantPoolSS - .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[0]); - String mType = constantPoolSS - .getUTF8At(((int[]) dummyClass.cp.get(nameAndTypeIndex).value)[1]); - msg = String.format("%s (%s.%s:%s) failed with %s ", - msg, cName, mName, mType, t); - break; - default: - msg = String.format("Test bug: unknown constant type %s ", cpType); - } - throw new Error(msg + t.getMessage(), t); - } - public void test() { - for (ConstantPoolTestsHelper.DummyClasses dummyClass - : ConstantPoolTestsHelper.DummyClasses.values()) { - System.out.printf("%nTesting dummy %s%n", dummyClass.klass); - HotSpotResolvedObjectType holder = HotSpotResolvedObjectType - .fromObjectClass(dummyClass.klass); - jdk.vm.ci.meta.ConstantPool constantPoolCTVM - = holder.getConstantPool(); - ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess(). - getConstantPool(dummyClass.klass); - for (Integer i : dummyClass.cp.keySet()) { - ConstantPoolTestsHelper.ConstantTypes cpType - = dummyClass.cp.get(i).type; + for (DummyClasses dummyClass : DummyClasses.values()) { + boolean isCPCached = WB.getConstantPoolCacheLength(dummyClass.klass) > -1; + System.out.printf("Testing dummy %s with constant pool cached = %b%n", + dummyClass.klass, + isCPCached); + HotSpotResolvedObjectType holder = HotSpotResolvedObjectType.fromObjectClass(dummyClass.klass); + jdk.vm.ci.meta.ConstantPool constantPoolCTVM = holder.getConstantPool(); + ConstantPool constantPoolSS = dummyClass.constantPoolSS; + for (int i = 0; i < constantPoolSS.getSize(); i++) { + Tag tag = constantPoolSS.getTagAt(i); + ConstantTypes cpType = mapTagToCPType(tag); if (!typeTests.keySet().contains(cpType)) { continue; } - try { - typeTests.get(cpType).validate(constantPoolCTVM, - constantPoolSS, dummyClass, i); - } catch (Throwable t) { - messageOnFail(t, cpType, dummyClass, i); - } + typeTests.get(cpType).validate(constantPoolCTVM, cpType, dummyClass, i); } } } } - diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java --- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,19 @@ */ package compiler.jvmci.compilerToVM; +import compiler.jvmci.common.testcases.MultipleAbstractImplementer; import compiler.jvmci.common.testcases.MultipleImplementer2; import compiler.jvmci.common.testcases.MultipleImplementersInterface; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; import java.util.HashMap; import java.util.Map; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.org.objectweb.asm.Opcodes; +import sun.hotspot.WhiteBox; +import sun.reflect.ConstantPool; +import sun.reflect.ConstantPool.Tag; /** * Class contains hard-coded constant pool tables for dummy classes used for @@ -34,104 +43,437 @@ */ public class ConstantPoolTestsHelper { - public enum ConstantTypes { - CONSTANT_CLASS, - CONSTANT_FIELDREF, - CONSTANT_METHODREF, - CONSTANT_INTERFACEMETHODREF, - CONSTANT_STRING, - CONSTANT_INTEGER, - CONSTANT_FLOAT, - CONSTANT_LONG, - CONSTANT_DOUBLE, - CONSTANT_NAMEANDTYPE, - CONSTANT_UTF8, - CONSTANT_METHODHANDLE, - CONSTANT_METHODTYPE, - CONSTANT_INVOKEDYNAMIC; - } + public static final int NO_CP_CACHE_PRESENT = Integer.MAX_VALUE; public enum DummyClasses { DUMMY_CLASS(MultipleImplementer2.class, CP_MAP_FOR_CLASS), + DUMMY_ABS_CLASS(MultipleAbstractImplementer.class, CP_MAP_FOR_ABS_CLASS), DUMMY_INTERFACE(MultipleImplementersInterface.class, CP_MAP_FOR_INTERFACE); + private static final WhiteBox WB = WhiteBox.getWhiteBox(); public final Class klass; - public final Map cp; + public final ConstantPool constantPoolSS; + public final Map testedCP; - DummyClasses(Class klass, Map cp) { + DummyClasses(Class klass, Map testedCP) { this.klass = klass; - this.cp = cp; + this.constantPoolSS = SharedSecrets.getJavaLangAccess().getConstantPool(klass); + this.testedCP = testedCP; } - } - public static class ConstantPoolEntry { - - public final ConstantTypes type; - public final Object value; - - public ConstantPoolEntry(ConstantTypes type, Object value) { - this.type = type; - this.value = value; + public int getCPCacheIndex(int cpi) { + int cacheLength = WB.getConstantPoolCacheLength(this.klass); + int indexTag = WB.getConstantPoolCacheIndexTag(); + for (int cpci = indexTag; cpci < cacheLength + indexTag; cpci++) { + if (WB.remapInstructionOperandFromCPCache(this.klass, cpci) == cpi) { + if (constantPoolSS.getTagAt(cpi).equals(Tag.INVOKEDYNAMIC)) { + return WB.encodeConstantPoolIndyIndex(cpci) + indexTag; + } + return cpci; + } + } + return NO_CP_CACHE_PRESENT; } } - private static final Map CP_MAP_FOR_CLASS - = new HashMap<>(); + private static final Map CP_MAP_FOR_CLASS = new HashMap<>(); static { - CP_MAP_FOR_CLASS.put(1, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{22, 68})); - CP_MAP_FOR_CLASS.put(2, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 69)); - CP_MAP_FOR_CLASS.put(3, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTEGER, 2147483647)); - CP_MAP_FOR_CLASS.put(4, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{35, 70})); - CP_MAP_FOR_CLASS.put(5, new ConstantPoolEntry(ConstantTypes.CONSTANT_LONG, 9223372036854775807L)); - CP_MAP_FOR_CLASS.put(8, new ConstantPoolEntry(ConstantTypes.CONSTANT_FLOAT, 3.4028235E38F)); - CP_MAP_FOR_CLASS.put(10, new ConstantPoolEntry(ConstantTypes.CONSTANT_DOUBLE, 1.7976931348623157E308D)); - CP_MAP_FOR_CLASS.put(13, new ConstantPoolEntry(ConstantTypes.CONSTANT_STRING, 74)); - CP_MAP_FOR_CLASS.put(22, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 83)); - CP_MAP_FOR_CLASS.put(23, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{22, 84})); - CP_MAP_FOR_CLASS.put(24, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTERFACEMETHODREF, new int[]{2, 85})); - CP_MAP_FOR_CLASS.put(26, new ConstantPoolEntry(ConstantTypes.CONSTANT_INVOKEDYNAMIC, new int[]{0, 91})); - CP_MAP_FOR_CLASS.put(29, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{35, 94})); - CP_MAP_FOR_CLASS.put(35, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 100)); - CP_MAP_FOR_CLASS.put(68, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{54, 55})); - CP_MAP_FOR_CLASS.put(70, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{48, 37})); - CP_MAP_FOR_CLASS.put(84, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{59, 55})); - CP_MAP_FOR_CLASS.put(85, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{103, 63})); - CP_MAP_FOR_CLASS.put(91, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{106, 107})); - CP_MAP_FOR_CLASS.put(94, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{36, 37})); - CP_MAP_FOR_CLASS.put(104, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{110, 111})); - CP_MAP_FOR_CLASS.put(105, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{35, 112})); - CP_MAP_FOR_CLASS.put(110, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 113)); - CP_MAP_FOR_CLASS.put(111, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{114, 118})); - CP_MAP_FOR_CLASS.put(112, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{58, 55})); + CP_MAP_FOR_CLASS.put(CONSTANT_CLASS, + new TestedCPEntry[] { + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", null, null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", null, null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2$1", null, null), + new TestedCPEntry("java/lang/invoke/MethodHandles$Lookup", null, null), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_FIELDREF, + new TestedCPEntry[] { + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "intStaticField", + "I", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "longStaticField", + "J", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_FINAL | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "floatStaticField", + "F", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_VOLATILE | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "doubleStaticField", + "D", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "stringStaticField", + "Ljava/lang/String;", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "objectStaticField", + "Ljava/lang/Object;", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "intField", + "I", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_PUBLIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "longField", + "J", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_PRIVATE), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "floatField", + "F", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_PROTECTED), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "doubleField", + "D", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_TRANSIENT), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "objectField", + "Ljava/lang/Object;", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_FINAL), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "stringField", + "Ljava/lang/String;", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_VOLATILE), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "stringFieldEmpty", + "Ljava/lang/String;", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + 0L), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_METHODREF, + new TestedCPEntry[] { + new TestedCPEntry("java/lang/System", + "getProperties", + "()Ljava/util/Properties;", + new byte[] {(byte) Opcodes.INVOKESTATIC}), + new TestedCPEntry("java/util/HashMap", + "", + "()V", + new byte[] {(byte) Opcodes.INVOKESPECIAL}), + new TestedCPEntry("java/lang/Object", + "toString", + "()Ljava/lang/String;", + new byte[] {(byte) Opcodes.INVOKESPECIAL, + (byte) Opcodes.INVOKEVIRTUAL}), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2$1", + "", + "(Lcompiler/jvmci/common/testcases/MultipleImplementer2;)V", + new byte[0]), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", + "run", + "()V", + new byte[0]), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_INTERFACEMETHODREF, + new TestedCPEntry[] { + new TestedCPEntry("java/util/Map", + "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + new byte[] {(byte) Opcodes.INVOKEINTERFACE}), + new TestedCPEntry("java/util/Map", + "remove", + "(Ljava/lang/Object;)Ljava/lang/Object;", + new byte[] {(byte) Opcodes.INVOKEINTERFACE}), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_STRING, + new TestedCPEntry[] { + new TestedCPEntry(null, "Message", null), + new TestedCPEntry(null, "", null), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_METHODHANDLE, + new TestedCPEntry[] { + new TestedCPEntry("java/lang/invoke/LambdaMetafactory", + "metafactory", + "(Ljava/lang/invoke/MethodHandles$Lookup;" + + "Ljava/lang/String;" + + "Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodHandle;" + + "Ljava/lang/invoke/MethodType;)" + + "Ljava/lang/invoke/CallSite;", + null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2", + "testMethod", + "()V"), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_METHODTYPE, + new TestedCPEntry[] { + new TestedCPEntry(null, null, "()V"), + } + ); + CP_MAP_FOR_CLASS.put(CONSTANT_INVOKEDYNAMIC, + new TestedCPEntry[] { + new TestedCPEntry(null, + "run", + "(Lcompiler/jvmci/common/testcases/MultipleImplementer2;)" + + "Ljava/lang/Runnable;"), + } + ); } - private static final Map CP_MAP_FOR_INTERFACE + private static final Map CP_MAP_FOR_ABS_CLASS = new HashMap<>(); static { - CP_MAP_FOR_INTERFACE.put(1, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 48)); - CP_MAP_FOR_INTERFACE.put(5, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTERFACEMETHODREF, new int[]{13, 52})); - CP_MAP_FOR_INTERFACE.put(6, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 53)); - CP_MAP_FOR_INTERFACE.put(7, new ConstantPoolEntry(ConstantTypes.CONSTANT_INVOKEDYNAMIC, new int[]{0, 58})); - CP_MAP_FOR_INTERFACE.put(8, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{6, 59})); - CP_MAP_FOR_INTERFACE.put(9, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{6, 60})); - CP_MAP_FOR_INTERFACE.put(12, new ConstantPoolEntry(ConstantTypes.CONSTANT_FIELDREF, new int[]{13, 63})); - CP_MAP_FOR_INTERFACE.put(13, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 64)); - CP_MAP_FOR_INTERFACE.put(17, new ConstantPoolEntry(ConstantTypes.CONSTANT_INTEGER, 2147483647)); - CP_MAP_FOR_INTERFACE.put(20, new ConstantPoolEntry(ConstantTypes.CONSTANT_LONG, 9223372036854775807l)); - CP_MAP_FOR_INTERFACE.put(24, new ConstantPoolEntry(ConstantTypes.CONSTANT_FLOAT, 3.4028235E38f)); - CP_MAP_FOR_INTERFACE.put(27, new ConstantPoolEntry(ConstantTypes.CONSTANT_DOUBLE, 1.7976931348623157E308d)); - CP_MAP_FOR_INTERFACE.put(31, new ConstantPoolEntry(ConstantTypes.CONSTANT_STRING, 65)); - CP_MAP_FOR_INTERFACE.put(52, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{34, 35})); - CP_MAP_FOR_INTERFACE.put(55, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODHANDLE, new int[]{6, 67})); - CP_MAP_FOR_INTERFACE.put(56, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODTYPE, 35)); - CP_MAP_FOR_INTERFACE.put(57, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODHANDLE, new int[]{9, 5})); - CP_MAP_FOR_INTERFACE.put(58, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{68, 69})); - CP_MAP_FOR_INTERFACE.put(59, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{70, 71})); - CP_MAP_FOR_INTERFACE.put(60, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{72, 35})); - CP_MAP_FOR_INTERFACE.put(63, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{32, 33})); - CP_MAP_FOR_INTERFACE.put(67, new ConstantPoolEntry(ConstantTypes.CONSTANT_METHODREF, new int[]{73, 74})); - CP_MAP_FOR_INTERFACE.put(73, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 75)); - CP_MAP_FOR_INTERFACE.put(74, new ConstantPoolEntry(ConstantTypes.CONSTANT_NAMEANDTYPE, new int[]{76, 80})); - CP_MAP_FOR_INTERFACE.put(77, new ConstantPoolEntry(ConstantTypes.CONSTANT_CLASS, 82)); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_CLASS, + new TestedCPEntry[] { + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", null, null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", null, null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", null, null), + new TestedCPEntry("java/lang/invoke/MethodHandles$Lookup", null, null), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_FIELDREF, + new TestedCPEntry[] { + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "intStaticField", + "I", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "longStaticField", + "J", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_FINAL | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "floatStaticField", + "F", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_VOLATILE | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "doubleStaticField", + "D", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "stringStaticField", + "Ljava/lang/String;", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "objectStaticField", + "Ljava/lang/Object;", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "intField", + "I", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_PUBLIC), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "longField", + "J", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_PRIVATE), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "floatField", + "F", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_PROTECTED), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "doubleField", + "D", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_TRANSIENT), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "objectField", + "Ljava/lang/Object;", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_FINAL), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "stringField", + "Ljava/lang/String;", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + Opcodes.ACC_VOLATILE), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "stringFieldEmpty", + "Ljava/lang/String;", + new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD}, + 0L), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODREF, + new TestedCPEntry[] { + new TestedCPEntry("java/lang/System", + "getProperties", + "()Ljava/util/Properties;", + new byte[] {(byte) Opcodes.INVOKESTATIC}), + new TestedCPEntry("java/util/HashMap", + "", + "()V", + new byte[] {(byte) Opcodes.INVOKESPECIAL}), + new TestedCPEntry("java/lang/Object", + "toString", + "()Ljava/lang/String;", + new byte[] {(byte) Opcodes.INVOKESPECIAL, + (byte) Opcodes.INVOKEVIRTUAL}), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", + "", + "(Lcompiler/jvmci/common/testcases/MultipleAbstractImplementer;)V", + new byte[0]), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", + "run", + "()V", + new byte[0]), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_INTERFACEMETHODREF, + new TestedCPEntry[] { + new TestedCPEntry("java/util/Map", + "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + new byte[] {(byte) Opcodes.INVOKEINTERFACE}), + new TestedCPEntry("java/util/Map", + "remove", + "(Ljava/lang/Object;)Ljava/lang/Object;", + new byte[] {(byte) Opcodes.INVOKEINTERFACE}), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_STRING, + new TestedCPEntry[] { + new TestedCPEntry(null, "Message", null), + new TestedCPEntry(null, "", null), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODHANDLE, + new TestedCPEntry[] { + new TestedCPEntry("java/lang/invoke/LambdaMetafactory", + "metafactory", + "(Ljava/lang/invoke/MethodHandles$Lookup;" + + "Ljava/lang/String;" + + "Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodHandle;" + + "Ljava/lang/invoke/MethodType;)" + + "Ljava/lang/invoke/CallSite;", + null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer", + "testMethod", + "()V"), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODTYPE, + new TestedCPEntry[] { + new TestedCPEntry(null, null, "()V"), + } + ); + CP_MAP_FOR_ABS_CLASS.put(CONSTANT_INVOKEDYNAMIC, + new TestedCPEntry[] { + new TestedCPEntry(null, + "run", + "(Lcompiler/jvmci/common/testcases/MultipleAbstractImplementer;)" + + "Ljava/lang/Runnable;"), + } + ); + } + + private static final Map CP_MAP_FOR_INTERFACE + = new HashMap<>(); + static { + CP_MAP_FOR_INTERFACE.put(CONSTANT_CLASS, + new TestedCPEntry[] { + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", null, null), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface$1", null, null), + new TestedCPEntry("java/lang/Object", null, null), + new TestedCPEntry("java/lang/invoke/MethodHandles$Lookup", null, null), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_FIELDREF, + new TestedCPEntry[] { + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", + "OBJECT_CONSTANT", + "Ljava/lang/Object;", + new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC}, + Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_METHODREF, + new TestedCPEntry[] { + new TestedCPEntry("java/lang/System", + "getProperties", + "()Ljava/util/Properties;", + new byte[] {(byte) Opcodes.INVOKESTATIC}), + new TestedCPEntry("java/util/HashMap", + "", + "()V", + new byte[] {(byte) Opcodes.INVOKESPECIAL}), + new TestedCPEntry("java/lang/Object", + "toString", + "()Ljava/lang/String;", + new byte[] {(byte) Opcodes.INVOKEVIRTUAL}), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", + "", + "(Lcompiler/jvmci/common/testcases/MultipleAbstractImplementer;)V", + new byte[0]), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer$1", + "run", + "()V", + new byte[0]), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_INTERFACEMETHODREF, + new TestedCPEntry[] { + new TestedCPEntry("java/util/Map", + "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + new byte[] {(byte) Opcodes.INVOKEINTERFACE}), + new TestedCPEntry("java/util/Map", + "remove", + "(Ljava/lang/Object;)Ljava/lang/Object;", + new byte[] {(byte) Opcodes.INVOKEINTERFACE}), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_STRING, + new TestedCPEntry[] { + new TestedCPEntry(null, "Hello", null), + new TestedCPEntry(null, "", null), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_METHODHANDLE, + new TestedCPEntry[] { + new TestedCPEntry("java/lang/invoke/LambdaMetafactory", + "metafactory", + "(Ljava/lang/invoke/MethodHandles$Lookup;" + + "Ljava/lang/String;Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodHandle;" + + "Ljava/lang/invoke/MethodType;)" + + "Ljava/lang/invoke/CallSite;"), + new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface", + "defaultMethod", + "()V"), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_METHODTYPE, + new TestedCPEntry[] { + new TestedCPEntry(null, null, "()V"), + } + ); + CP_MAP_FOR_INTERFACE.put(CONSTANT_INVOKEDYNAMIC, + new TestedCPEntry[] { + new TestedCPEntry(null, + "run", + "(Lcompiler/jvmci/common/testcases/MultipleImplementersInterface;)" + + "Ljava/lang/Runnable;"), + } + ); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java --- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,58 +29,73 @@ * @summary Testing compiler.jvmci.CompilerToVM.lookupKlassInPool method * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java - * @build compiler.jvmci.common.testcases.MultipleImplementersInterface - * compiler.jvmci.common.testcases.MultipleImplementer2 - * compiler.jvmci.compilerToVM.ConstantPoolTestsHelper - * compiler.jvmci.compilerToVM.ConstantPoolTestCase + * @build sun.hotspot.WhiteBox * compiler.jvmci.compilerToVM.LookupKlassInPoolTest - * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.LookupKlassInPoolTest */ package compiler.jvmci.compilerToVM; +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; import java.util.HashMap; import java.util.Map; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import sun.reflect.ConstantPool; +import jdk.vm.ci.meta.ConstantPool; /** - * Test for {@code compiler.jvmci.CompilerToVM.lookupKlassInPool} method + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupKlassInPool} method */ public class LookupKlassInPoolTest { - public static void main(String[] args) { - Map typeTests = new HashMap<>(1); - typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_CLASS, - LookupKlassInPoolTest::validate); + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_CLASS, LookupKlassInPoolTest::validate); ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); } - public static void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM, - ConstantPool constantPoolSS, - ConstantPoolTestsHelper.DummyClasses dummyClass, int i) { - Object classToVerify = CompilerToVMHelper - .lookupKlassInPool(constantPoolCTVM, i); - if (!(classToVerify instanceof HotSpotResolvedObjectType) - && !(classToVerify instanceof String)) { - String msg = String.format("Output of method" - + " CTVM.lookupKlassInPool is neither" - + " a HotSpotResolvedObjectType, nor a String"); + public static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int i) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, i); + if (entry == null) { + return; + } + Object classToVerify = CompilerToVMHelper.lookupKlassInPool(constantPoolCTVM, i); + if (!(classToVerify instanceof HotSpotResolvedObjectType) && !(classToVerify instanceof String)) { + String msg = String.format("Output of method CTVM.lookupKlassInPool is neither" + + " a HotSpotResolvedObjectType, nor a String"); throw new AssertionError(msg); } - int classNameIndex = (int) dummyClass.cp.get(i).value; - String classNameToRefer - = constantPoolSS.getUTF8At(classNameIndex); + String classNameToRefer = entry.klass; String outputToVerify = classToVerify.toString(); if (!outputToVerify.contains(classNameToRefer)) { - String msg = String.format("Wrong class accessed by constant" - + " pool index %d: %s, but should be %s", - i, outputToVerify, classNameToRefer); + String msg = String.format("Wrong class accessed by constant pool index %d: %s, but should be %s", + i, + outputToVerify, + classNameToRefer); throw new AssertionError(msg); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.util.HashMap; +import java.util.Map; +import jdk.test.lib.Asserts; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.meta.ConstantPool; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupKlassRefIndexInPool} method + */ +public class LookupKlassRefIndexInPoolTest { + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_METHODREF, LookupKlassRefIndexInPoolTest::validate); + typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupKlassRefIndexInPoolTest::validate); + typeTests.put(CONSTANT_FIELDREF, LookupKlassRefIndexInPoolTest::validate); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + int indexToVerify = CompilerToVMHelper.lookupKlassRefIndexInPool(constantPoolCTVM, index); + int indexToRefer = dummyClass.constantPoolSS.getClassRefIndexAt(cpi); + String msg = String.format("Wrong class index returned by lookupKlassRefIndexInPool method " + + "applied to %sconstant pool index %d", + cached, + index); + Asserts.assertEQ(indexToRefer, indexToVerify, msg); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.LookupMethodInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.LookupMethodInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.util.HashMap; +import java.util.Map; +import jdk.test.lib.Asserts; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.meta.ConstantPool; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupMethodInPool} method + */ +public class LookupMethodInPoolTest { + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_METHODREF, LookupMethodInPoolTest::validate); + typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupMethodInPoolTest::validate); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + for (int j = 0; j < entry.opcodes.length; j++) { + HotSpotResolvedJavaMethod methodToVerify = CompilerToVMHelper + .lookupMethodInPool(constantPoolCTVM, index, entry.opcodes[j]); + String msg = String.format("Object returned by lookupMethodInPool method" + + " for %sindex %d should not be null", + cached, + index); + Asserts.assertNotNull(methodToVerify, msg); + String[] classNameSplit = entry.klass.split("/"); + String classNameToRefer = classNameSplit[classNameSplit.length - 1]; + String methodNameToRefer = entry.name; + String methodToVerifyToString = methodToVerify.toString(); + if (!methodToVerifyToString.contains(classNameToRefer) + || !methodToVerifyToString.contains(methodNameToRefer)) { + msg = String.format("String representation \"%s\" of the object" + + " returned by lookupMethodInPool method" + + " for index %d does not contain a method's class name" + + " or method's name, should contain %s.%s", + methodToVerifyToString, + index, + classNameToRefer, + methodNameToRefer); + throw new AssertionError(msg); + } + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.util.HashMap; +import java.util.Map; +import jdk.test.lib.Asserts; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.meta.ConstantPool; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupNameAndTypeRefIndexInPool} method + */ +public class LookupNameAndTypeRefIndexInPoolTest { + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_METHODREF, LookupNameAndTypeRefIndexInPoolTest::validate); + typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupNameAndTypeRefIndexInPoolTest::validate); + typeTests.put(CONSTANT_FIELDREF, LookupNameAndTypeRefIndexInPoolTest::validate); + typeTests.put(CONSTANT_INVOKEDYNAMIC, LookupNameAndTypeRefIndexInPoolTest::validate); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + int indexToVerify = CompilerToVMHelper.lookupNameAndTypeRefIndexInPool(constantPoolCTVM, index); + int indexToRefer = dummyClass.constantPoolSS.getNameAndTypeRefIndexAt(cpi); + String msg = String.format("Wrong nameAndType index returned by lookupNameAndTypeRefIndexInPool" + + " method applied to %sconstant pool index %d", + cached, + index); + Asserts.assertEQ(indexToRefer, indexToVerify, msg); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.LookupNameInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.LookupNameInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.util.HashMap; +import java.util.Map; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.meta.ConstantPool; +import jdk.test.lib.Asserts; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupNameInPool} method + */ +public class LookupNameInPoolTest { + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_METHODREF, LookupNameInPoolTest::validate); + typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupNameInPoolTest::validate); + typeTests.put(CONSTANT_FIELDREF, LookupNameInPoolTest::validate); + typeTests.put(CONSTANT_INVOKEDYNAMIC, LookupNameInPoolTest::validate); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + String nameToVerify = CompilerToVMHelper.lookupNameInPool(constantPoolCTVM, index); + String nameToRefer = entry.name; + String msg = String.format("Wrong name accessed by %sconstant pool index %d", cached, index); + Asserts.assertEQ(nameToVerify, nameToRefer, msg); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.LookupSignatureInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.LookupSignatureInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.util.HashMap; +import java.util.Map; +import jdk.test.lib.Asserts; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.meta.ConstantPool; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.lookupSignatureInPool} method + */ +public class LookupSignatureInPoolTest { + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_METHODREF, LookupSignatureInPoolTest::validate); + typeTests.put(CONSTANT_INTERFACEMETHODREF, LookupSignatureInPoolTest::validate); + typeTests.put(CONSTANT_FIELDREF, LookupSignatureInPoolTest::validate); + typeTests.put(CONSTANT_INVOKEDYNAMIC, LookupSignatureInPoolTest::validate); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + String sigToVerify = CompilerToVMHelper.lookupSignatureInPool(constantPoolCTVM, index); + String sigToRefer = entry.type; + String msg = String.format("Wrong signature accessed by %sconstant pool index %d", + cached, + index); + Asserts.assertEQ(sigToVerify, sigToRefer, msg); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,66 +28,86 @@ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java - * @build compiler.jvmci.compilerToVM.ResolveConstantInPoolTest - * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.ResolveConstantInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI * compiler.jvmci.compilerToVM.ResolveConstantInPoolTest */ package compiler.jvmci.compilerToVM; +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.HashMap; import java.util.Map; +import jdk.test.lib.Asserts; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.test.lib.Asserts; -import sun.reflect.ConstantPool; +import jdk.vm.ci.meta.ConstantPool; /** - * Test for {@code compiler.jvmci.CompilerToVM.resolveConstantInPool} method + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolveConstantInPool} method */ public class ResolveConstantInPoolTest { + private static final String NOT_NULL_MSG + = "Object returned by resolveConstantInPool method should not be null"; + public static void main(String[] args) throws Exception { - Map typeTests = new HashMap<>(2); - typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_METHODHANDLE, - ResolveConstantInPoolTest::validateMethodHandle); - typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_METHODTYPE, - ResolveConstantInPoolTest::validateMethodType); + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_METHODHANDLE, ResolveConstantInPoolTest::validateMethodHandle); + typeTests.put(CONSTANT_METHODTYPE, ResolveConstantInPoolTest::validateMethodType); ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); } - private static void validateMethodHandle( - jdk.vm.ci.meta.ConstantPool constantPoolCTVM, - ConstantPool constantPoolSS, - ConstantPoolTestsHelper.DummyClasses dummyClass, int index) { - Object constantInPool = CompilerToVMHelper - .resolveConstantInPool(constantPoolCTVM, index); + private static void validateMethodHandle(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int index) { + Object constantInPool = CompilerToVMHelper.resolveConstantInPool(constantPoolCTVM, index); + String msg = String.format("%s for index %d", NOT_NULL_MSG, index); + Asserts.assertNotNull(constantInPool, msg); if (!(constantInPool instanceof MethodHandle)) { - String msg = String.format( - "Wrong constant pool entry accessed by index" - + " %d: %s, but should be subclass of %s", - index + 1, constantInPool.getClass(), - MethodHandle.class.getName()); + msg = String.format("Wrong constant pool entry accessed by index" + + " %d: %s, but should be subclass of %s", + index, + constantInPool.getClass(), + MethodHandle.class.getName()); throw new AssertionError(msg); } } - private static void validateMethodType( - jdk.vm.ci.meta.ConstantPool constantPoolCTVM, - ConstantPool constantPoolSS, - ConstantPoolTestsHelper.DummyClasses dummyClass, int index) { - Object constantInPool = CompilerToVMHelper - .resolveConstantInPool(constantPoolCTVM, index); + private static void validateMethodType(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int index) { + Object constantInPool = CompilerToVMHelper.resolveConstantInPool(constantPoolCTVM, index); + String msg = String.format("%s for index %d", NOT_NULL_MSG, index); + Asserts.assertNotNull(constantInPool, msg); Class mtToVerify = constantInPool.getClass(); Class mtToRefer = MethodType.class; - String msg = String.format("Wrong %s accessed by constant pool index" - + " %d: %s, but should be %s", "method type class", - index, mtToVerify, mtToRefer); + msg = String.format("Wrong method type class accessed by" + + " constant pool index %d", + index); Asserts.assertEQ(mtToRefer, mtToVerify, msg); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.ResolveFieldInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.ResolveFieldInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.ConstantPool; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import sun.misc.Unsafe; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolveFieldInPool} method + */ +public class ResolveFieldInPoolTest { + + private static final Unsafe UNSAFE = Utils.getUnsafe(); + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_FIELDREF, ResolveFieldInPoolTest::validate); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + for (int j = 0; j < entry.opcodes.length; j++) { + long[] info = new long[2]; + HotSpotResolvedObjectType fieldToVerify + = CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM, + index, + entry.opcodes[j], + info); + String msg = String.format("Object returned by resolveFieldInPool method" + + " for %sindex %d should not be null", + cached, + index); + Asserts.assertNotNull(fieldToVerify, msg); + String classNameToRefer = entry.klass; + String fieldToVerifyKlassToString = fieldToVerify.klass().toValueString(); + if (!fieldToVerifyKlassToString.contains(classNameToRefer)) { + msg = String.format("String representation \"%s\" of the object" + + " returned by resolveFieldInPool method" + + " for index %d does not contain a field's class name," + + " should contain %s", + fieldToVerifyKlassToString, + index, + classNameToRefer); + throw new AssertionError(msg); + } + msg = String.format("Access flags returned by resolveFieldInPool" + + " method are wrong for the field %s.%s" + + " at %sindex %d", + entry.klass, + entry.name, + cached, + index); + Asserts.assertEQ(info[0], entry.accFlags, msg); + if (cpci == -1) { + return; + } + Class classOfTheField = null; + Field fieldToRefer = null; + try { + classOfTheField = Class.forName(classNameToRefer.replaceAll("/", "\\.")); + fieldToRefer = classOfTheField.getDeclaredField(entry.name); + fieldToRefer.setAccessible(true); + } catch (Exception ex) { + throw new Error("Unexpected exception", ex); + } + long offsetToRefer; + if ((entry.accFlags & Opcodes.ACC_STATIC) != 0) { + offsetToRefer = UNSAFE.staticFieldOffset(fieldToRefer); + } else { + offsetToRefer = UNSAFE.objectFieldOffset(fieldToRefer); + } + msg = String.format("Field offset returned by resolveFieldInPool" + + " method is wrong for the field %s.%s" + + " at %sindex %d", + entry.klass, + entry.name, + cached, + index); + Asserts.assertEQ(info[1], offsetToRefer, msg); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8138708 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile ../common/CompilerToVMHelper.java + * @build sun.hotspot.WhiteBox + * compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest + */ + +package compiler.jvmci.compilerToVM; + +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; +import java.util.HashMap; +import java.util.Map; +import jdk.test.lib.Asserts; +import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.meta.ConstantPool; + +/** + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolvePossiblyCachedConstantInPool} method + */ +public class ResolvePossiblyCachedConstantInPoolTest { + + public static void main(String[] args) throws Exception { + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_STRING, ResolvePossiblyCachedConstantInPoolTest::validateString); + ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); + // The next "Class.forName" is here for the following reason. + // When class is initialized, constant pool cache is available. + // This method works only with cached constant pool. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); + } + + private static void validateString(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int cpi) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, cpi); + if (entry == null) { + return; + } + int index = cpi; + String cached = ""; + int cpci = dummyClass.getCPCacheIndex(cpi); + if (cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + index = cpci; + cached = "cached "; + } + Object constantInPool = CompilerToVMHelper.resolvePossiblyCachedConstantInPool(constantPoolCTVM, index); + String stringToVerify = (String) constantInPool; + String stringToRefer = entry.name; + if (stringToRefer.equals("") && cpci != ConstantPoolTestsHelper.NO_CP_CACHE_PRESENT) { + stringToRefer = null; // tested method returns null for cached empty strings + } + String msg = String.format("Wrong string accessed by %sconstant pool index %d", cached, index); + Asserts.assertEQ(stringToRefer, stringToVerify, msg); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java --- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,51 +29,69 @@ * @summary Testing compiler.jvmci.CompilerToVM.resolveTypeInPool method * @library /testlibrary /test/lib / * @compile ../common/CompilerToVMHelper.java - * @build compiler.jvmci.common.testcases.MultipleImplementersInterface - * compiler.jvmci.common.testcases.MultipleImplementer2 - * compiler.jvmci.compilerToVM.ConstantPoolTestsHelper - * compiler.jvmci.compilerToVM.ConstantPoolTestCase + * @build sun.hotspot.WhiteBox * compiler.jvmci.compilerToVM.ResolveTypeInPoolTest - * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * jdk.vm.ci.hotspot.CompilerToVMHelper + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveTypeInPoolTest */ package compiler.jvmci.compilerToVM; +import compiler.jvmci.compilerToVM.ConstantPoolTestsHelper.DummyClasses; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes; +import static compiler.jvmci.compilerToVM.ConstantPoolTestCase.ConstantTypes.*; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry; +import compiler.jvmci.compilerToVM.ConstantPoolTestCase.Validator; import java.util.HashMap; import java.util.Map; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import sun.reflect.ConstantPool; +import jdk.vm.ci.meta.ConstantPool; /** - * Test for {@code compiler.jvmci.CompilerToVM.resolveTypeInPool} method + * Test for {@code jdk.vm.ci.hotspot.CompilerToVM.resolveTypeInPool} method */ public class ResolveTypeInPoolTest { public static void main(String[] args) throws Exception { - Map typeTests = new HashMap<>(1); - typeTests.put(ConstantPoolTestsHelper.ConstantTypes.CONSTANT_CLASS, - ResolveTypeInPoolTest::validate); + Map typeTests = new HashMap<>(); + typeTests.put(CONSTANT_CLASS, ResolveTypeInPoolTest::validate); ConstantPoolTestCase testCase = new ConstantPoolTestCase(typeTests); testCase.test(); + // The next "Class.forName" and repeating "testCase.test()" + // are here for the following reason. + // The first test run is without dummy class initialization, + // which means no constant pool cache exists. + // The second run is with initialized class (with constant pool cache available). + // Some CompilerToVM methods require different input + // depending on whether CP cache exists or not. + for (DummyClasses dummy : DummyClasses.values()) { + Class.forName(dummy.klass.getName()); + } + testCase.test(); } - public static void validate( - jdk.vm.ci.meta.ConstantPool constantPoolCTVM, - ConstantPool constantPoolSS, - ConstantPoolTestsHelper.DummyClasses dummyClass, int i) { - HotSpotResolvedObjectType typeToVerify = CompilerToVMHelper - .resolveTypeInPool(constantPoolCTVM, i); - int classNameIndex = (int) dummyClass.cp.get(i).value; - String classNameToRefer = constantPoolSS.getUTF8At(classNameIndex); + public static void validate(ConstantPool constantPoolCTVM, + ConstantTypes cpType, + DummyClasses dummyClass, + int i) { + TestedCPEntry entry = cpType.getTestedCPEntry(dummyClass, i); + if (entry == null) { + return; + } + HotSpotResolvedObjectType typeToVerify = CompilerToVMHelper.resolveTypeInPool(constantPoolCTVM, i); + String classNameToRefer = entry.klass; String outputToVerify = typeToVerify.toString(); if (!outputToVerify.contains(classNameToRefer)) { String msg = String.format("Wrong class accessed by constant" - + " pool index %d: %s, but should be %s", - i, outputToVerify, classNameToRefer); + + " pool index %d: %s, but should be %s", + i, + outputToVerify, + classNameToRefer); throw new AssertionError(msg); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/native/TestDirtyInt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/native/TestDirtyInt.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @run main/native TestDirtyInt + */ +public class TestDirtyInt { + static { + System.loadLibrary("TestDirtyInt"); + } + + native static int test(int v); + + static int compiled(int v) { + return test(v<<2); + } + + static public void main(String[] args) { + for (int i = 0; i < 20000; i++) { + int res = compiled(Integer.MAX_VALUE); + if (res != 0x42) { + throw new RuntimeException("Test failed"); + } + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/native/libTestDirtyInt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/native/libTestDirtyInt.c Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" +#include + +static int array = 0x42; + +JNIEXPORT jint JNICALL Java_TestDirtyInt_test(JNIEnv* env, jclass jclazz, jint v) +{ + int* ptr = &array + v + 4; + return *ptr; +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java Mon Mar 21 11:21:08 2016 +0100 @@ -128,6 +128,20 @@ } + // Lazy + { + UNSAFE.putBooleanRelease(base, offset, true); + boolean x = UNSAFE.getBooleanAcquire(base, offset); + assertEquals(x, true, "putRelease boolean value"); + } + + // Opaque + { + UNSAFE.putBooleanOpaque(base, offset, false); + boolean x = UNSAFE.getBooleanOpaque(base, offset); + assertEquals(x, false, "putOpaque boolean value"); + } + } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java Mon Mar 21 11:21:08 2016 +0100 @@ -157,6 +157,20 @@ } + // Lazy + { + UNSAFE.putByteRelease(base, offset, (byte)1); + byte x = UNSAFE.getByteAcquire(base, offset); + assertEquals(x, (byte)1, "putRelease byte value"); + } + + // Opaque + { + UNSAFE.putByteOpaque(base, offset, (byte)2); + byte x = UNSAFE.getByteOpaque(base, offset); + assertEquals(x, (byte)2, "putOpaque byte value"); + } + } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java Mon Mar 21 11:21:08 2016 +0100 @@ -157,6 +157,20 @@ } + // Lazy + { + UNSAFE.putCharRelease(base, offset, 'a'); + char x = UNSAFE.getCharAcquire(base, offset); + assertEquals(x, 'a', "putRelease char value"); + } + + // Opaque + { + UNSAFE.putCharOpaque(base, offset, 'b'); + char x = UNSAFE.getCharOpaque(base, offset); + assertEquals(x, 'b', "putOpaque char value"); + } + // Unaligned { UNSAFE.putCharUnaligned(base, offset, 'b'); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java Mon Mar 21 11:21:08 2016 +0100 @@ -157,6 +157,20 @@ } + // Lazy + { + UNSAFE.putDoubleRelease(base, offset, 1.0d); + double x = UNSAFE.getDoubleAcquire(base, offset); + assertEquals(x, 1.0d, "putRelease double value"); + } + + // Opaque + { + UNSAFE.putDoubleOpaque(base, offset, 2.0d); + double x = UNSAFE.getDoubleOpaque(base, offset); + assertEquals(x, 2.0d, "putOpaque double value"); + } + } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java Mon Mar 21 11:21:08 2016 +0100 @@ -157,6 +157,20 @@ } + // Lazy + { + UNSAFE.putFloatRelease(base, offset, 1.0f); + float x = UNSAFE.getFloatAcquire(base, offset); + assertEquals(x, 1.0f, "putRelease float value"); + } + + // Opaque + { + UNSAFE.putFloatOpaque(base, offset, 2.0f); + float x = UNSAFE.getFloatOpaque(base, offset); + assertEquals(x, 2.0f, "putOpaque float value"); + } + } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java Mon Mar 21 11:21:08 2016 +0100 @@ -163,6 +163,20 @@ assertEquals(x, 1, "putRelease int value"); } + // Lazy + { + UNSAFE.putIntRelease(base, offset, 1); + int x = UNSAFE.getIntAcquire(base, offset); + assertEquals(x, 1, "putRelease int value"); + } + + // Opaque + { + UNSAFE.putIntOpaque(base, offset, 2); + int x = UNSAFE.getIntOpaque(base, offset); + assertEquals(x, 2, "putOpaque int value"); + } + // Unaligned { UNSAFE.putIntUnaligned(base, offset, 2); @@ -199,6 +213,70 @@ assertEquals(x, 2, "failing compareAndSwap int value"); } + // Advanced compare + { + int r = UNSAFE.compareAndExchangeIntVolatile(base, offset, 2, 1); + assertEquals(r, 2, "success compareAndExchangeVolatile int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 1, "success compareAndExchangeVolatile int value"); + } + + { + int r = UNSAFE.compareAndExchangeIntVolatile(base, offset, 2, 3); + assertEquals(r, 1, "failing compareAndExchangeVolatile int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 1, "failing compareAndExchangeVolatile int value"); + } + + { + int r = UNSAFE.compareAndExchangeIntAcquire(base, offset, 1, 2); + assertEquals(r, 1, "success compareAndExchangeAcquire int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 2, "success compareAndExchangeAcquire int value"); + } + + { + int r = UNSAFE.compareAndExchangeIntAcquire(base, offset, 1, 3); + assertEquals(r, 2, "failing compareAndExchangeAcquire int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 2, "failing compareAndExchangeAcquire int value"); + } + + { + int r = UNSAFE.compareAndExchangeIntRelease(base, offset, 2, 1); + assertEquals(r, 2, "success compareAndExchangeRelease int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 1, "success compareAndExchangeRelease int value"); + } + + { + int r = UNSAFE.compareAndExchangeIntRelease(base, offset, 2, 3); + assertEquals(r, 1, "failing compareAndExchangeRelease int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 1, "failing compareAndExchangeRelease int value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapInt(base, offset, 1, 2); + assertEquals(r, true, "weakCompareAndSwap int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 2, "weakCompareAndSwap int value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapIntAcquire(base, offset, 2, 1); + assertEquals(r, true, "weakCompareAndSwapAcquire int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 1, "weakCompareAndSwapAcquire int"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapIntRelease(base, offset, 1, 2); + assertEquals(r, true, "weakCompareAndSwapRelease int"); + int x = UNSAFE.getInt(base, offset); + assertEquals(x, 2, "weakCompareAndSwapRelease int"); + } + // Compare set and get { int o = UNSAFE.getAndSetInt(base, offset, 1); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java Mon Mar 21 11:21:08 2016 +0100 @@ -163,6 +163,20 @@ assertEquals(x, 1L, "putRelease long value"); } + // Lazy + { + UNSAFE.putLongRelease(base, offset, 1L); + long x = UNSAFE.getLongAcquire(base, offset); + assertEquals(x, 1L, "putRelease long value"); + } + + // Opaque + { + UNSAFE.putLongOpaque(base, offset, 2L); + long x = UNSAFE.getLongOpaque(base, offset); + assertEquals(x, 2L, "putOpaque long value"); + } + // Unaligned { UNSAFE.putLongUnaligned(base, offset, 2L); @@ -199,6 +213,70 @@ assertEquals(x, 2L, "failing compareAndSwap long value"); } + // Advanced compare + { + long r = UNSAFE.compareAndExchangeLongVolatile(base, offset, 2L, 1L); + assertEquals(r, 2L, "success compareAndExchangeVolatile long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 1L, "success compareAndExchangeVolatile long value"); + } + + { + long r = UNSAFE.compareAndExchangeLongVolatile(base, offset, 2L, 3L); + assertEquals(r, 1L, "failing compareAndExchangeVolatile long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 1L, "failing compareAndExchangeVolatile long value"); + } + + { + long r = UNSAFE.compareAndExchangeLongAcquire(base, offset, 1L, 2L); + assertEquals(r, 1L, "success compareAndExchangeAcquire long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 2L, "success compareAndExchangeAcquire long value"); + } + + { + long r = UNSAFE.compareAndExchangeLongAcquire(base, offset, 1L, 3L); + assertEquals(r, 2L, "failing compareAndExchangeAcquire long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 2L, "failing compareAndExchangeAcquire long value"); + } + + { + long r = UNSAFE.compareAndExchangeLongRelease(base, offset, 2L, 1L); + assertEquals(r, 2L, "success compareAndExchangeRelease long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 1L, "success compareAndExchangeRelease long value"); + } + + { + long r = UNSAFE.compareAndExchangeLongRelease(base, offset, 2L, 3L); + assertEquals(r, 1L, "failing compareAndExchangeRelease long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 1L, "failing compareAndExchangeRelease long value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapLong(base, offset, 1L, 2L); + assertEquals(r, true, "weakCompareAndSwap long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 2L, "weakCompareAndSwap long value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapLongAcquire(base, offset, 2L, 1L); + assertEquals(r, true, "weakCompareAndSwapAcquire long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 1L, "weakCompareAndSwapAcquire long"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapLongRelease(base, offset, 1L, 2L); + assertEquals(r, true, "weakCompareAndSwapRelease long"); + long x = UNSAFE.getLong(base, offset); + assertEquals(x, 2L, "weakCompareAndSwapRelease long"); + } + // Compare set and get { long o = UNSAFE.getAndSetLong(base, offset, 1L); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java Mon Mar 21 11:21:08 2016 +0100 @@ -134,6 +134,20 @@ assertEquals(x, "foo", "putRelease Object value"); } + // Lazy + { + UNSAFE.putObjectRelease(base, offset, "foo"); + Object x = UNSAFE.getObjectAcquire(base, offset); + assertEquals(x, "foo", "putRelease Object value"); + } + + // Opaque + { + UNSAFE.putObjectOpaque(base, offset, "bar"); + Object x = UNSAFE.getObjectOpaque(base, offset); + assertEquals(x, "bar", "putOpaque Object value"); + } + UNSAFE.putObject(base, offset, "foo"); @@ -152,6 +166,70 @@ assertEquals(x, "bar", "failing compareAndSwap Object value"); } + // Advanced compare + { + Object r = UNSAFE.compareAndExchangeObjectVolatile(base, offset, "bar", "foo"); + assertEquals(r, "bar", "success compareAndExchangeVolatile Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "success compareAndExchangeVolatile Object value"); + } + + { + Object r = UNSAFE.compareAndExchangeObjectVolatile(base, offset, "bar", "baz"); + assertEquals(r, "foo", "failing compareAndExchangeVolatile Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "failing compareAndExchangeVolatile Object value"); + } + + { + Object r = UNSAFE.compareAndExchangeObjectAcquire(base, offset, "foo", "bar"); + assertEquals(r, "foo", "success compareAndExchangeAcquire Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "bar", "success compareAndExchangeAcquire Object value"); + } + + { + Object r = UNSAFE.compareAndExchangeObjectAcquire(base, offset, "foo", "baz"); + assertEquals(r, "bar", "failing compareAndExchangeAcquire Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "bar", "failing compareAndExchangeAcquire Object value"); + } + + { + Object r = UNSAFE.compareAndExchangeObjectRelease(base, offset, "bar", "foo"); + assertEquals(r, "bar", "success compareAndExchangeRelease Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "success compareAndExchangeRelease Object value"); + } + + { + Object r = UNSAFE.compareAndExchangeObjectRelease(base, offset, "bar", "baz"); + assertEquals(r, "foo", "failing compareAndExchangeRelease Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "failing compareAndExchangeRelease Object value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapObject(base, offset, "foo", "bar"); + assertEquals(r, true, "weakCompareAndSwap Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "bar", "weakCompareAndSwap Object value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapObjectAcquire(base, offset, "bar", "foo"); + assertEquals(r, true, "weakCompareAndSwapAcquire Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "foo", "weakCompareAndSwapAcquire Object"); + } + + { + boolean r = UNSAFE.weakCompareAndSwapObjectRelease(base, offset, "foo", "bar"); + assertEquals(r, true, "weakCompareAndSwapRelease Object"); + Object x = UNSAFE.getObject(base, offset); + assertEquals(x, "bar", "weakCompareAndSwapRelease Object"); + } + // Compare set and get { Object o = UNSAFE.getAndSetObject(base, offset, "foo"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java --- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java Mon Mar 21 11:21:08 2016 +0100 @@ -157,6 +157,20 @@ } + // Lazy + { + UNSAFE.putShortRelease(base, offset, (short)1); + short x = UNSAFE.getShortAcquire(base, offset); + assertEquals(x, (short)1, "putRelease short value"); + } + + // Opaque + { + UNSAFE.putShortOpaque(base, offset, (short)2); + short x = UNSAFE.getShortOpaque(base, offset); + assertEquals(x, (short)2, "putOpaque short value"); + } + // Unaligned { UNSAFE.putShortUnaligned(base, offset, (short)2); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/UnsafeGetConstantField.java --- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Mon Mar 21 11:21:08 2016 +0100 @@ -27,6 +27,9 @@ * @test * @summary tests on constant folding of unsafe get operations * @library /testlibrary /test/lib + * + * @requires vm.flavor != "client" + * * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions * -Xbatch -XX:-TieredCompilation * -XX:+FoldStableValues diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary tests on constant folding of unsafe get operations from stable arrays + * @library /testlibrary /test/lib + * @ignore 8151137 + * + * @requires vm.flavor != "client" + * + * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions + * -Xbatch -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileCommand=dontinline,*Test::test* + * UnsafeGetStableArrayElement + */ +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.Stable; +import java.util.concurrent.Callable; + +import static jdk.internal.misc.Unsafe.*; +import static jdk.test.lib.Asserts.*; + +public class UnsafeGetStableArrayElement { + @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16]; + @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[16]; + @Stable static final short[] STABLE_SHORT_ARRAY = new short[8]; + @Stable static final char[] STABLE_CHAR_ARRAY = new char[8]; + @Stable static final int[] STABLE_INT_ARRAY = new int[4]; + @Stable static final long[] STABLE_LONG_ARRAY = new long[2]; + @Stable static final float[] STABLE_FLOAT_ARRAY = new float[4]; + @Stable static final double[] STABLE_DOUBLE_ARRAY = new double[2]; + @Stable static final Object[] STABLE_OBJECT_ARRAY = new Object[4]; + + static { + Setter.reset(); + } + static final Unsafe U = Unsafe.getUnsafe(); + + static class Setter { + private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false : true; } + private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0] = defaultVal ? 0 : Byte.MAX_VALUE; } + private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0] = defaultVal ? 0 : Short.MAX_VALUE; } + private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0] = defaultVal ? 0 : Character.MAX_VALUE; } + private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0] = defaultVal ? 0 : Integer.MAX_VALUE; } + private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0] = defaultVal ? 0 : Long.MAX_VALUE; } + private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0] = defaultVal ? 0 : Float.MAX_VALUE; } + private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0] = defaultVal ? 0 : Double.MAX_VALUE; } + private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0] = defaultVal ? null : new Object(); } + + static void reset() { + setZ(false); + setB(false); + setS(false); + setC(false); + setI(false); + setJ(false); + setF(false); + setD(false); + setL(false); + } + } + + static class Test { + static void changeZ() { Setter.setZ(true); } + static void changeB() { Setter.setB(true); } + static void changeS() { Setter.setS(true); } + static void changeC() { Setter.setC(true); } + static void changeI() { Setter.setI(true); } + static void changeJ() { Setter.setJ(true); } + static void changeF() { Setter.setF(true); } + static void changeD() { Setter.setD(true); } + static void changeL() { Setter.setL(true); } + + static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static byte testZ_B() { return U.getByte( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static short testZ_S() { return U.getShort( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static char testZ_C() { return U.getChar( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static int testZ_I() { return U.getInt( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static long testZ_J() { return U.getLong( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static float testZ_F() { return U.getFloat( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static double testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + + static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static byte testB_B() { return U.getByte( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static short testB_S() { return U.getShort( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static char testB_C() { return U.getChar( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static int testB_I() { return U.getInt( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static long testB_J() { return U.getLong( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static float testB_F() { return U.getFloat( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static double testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + + static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static byte testS_B() { return U.getByte( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static short testS_S() { return U.getShort( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static char testS_C() { return U.getChar( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static int testS_I() { return U.getInt( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static long testS_J() { return U.getLong( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static float testS_F() { return U.getFloat( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static double testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + + static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static byte testC_B() { return U.getByte( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static short testC_S() { return U.getShort( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static char testC_C() { return U.getChar( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static int testC_I() { return U.getInt( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static long testC_J() { return U.getLong( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static float testC_F() { return U.getFloat( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static double testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + + static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static byte testI_B() { return U.getByte( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static short testI_S() { return U.getShort( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static char testI_C() { return U.getChar( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static int testI_I() { return U.getInt( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static long testI_J() { return U.getLong( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static float testI_F() { return U.getFloat( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static double testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + + static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static byte testJ_B() { return U.getByte( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static short testJ_S() { return U.getShort( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static char testJ_C() { return U.getChar( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static int testJ_I() { return U.getInt( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static long testJ_J() { return U.getLong( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static float testJ_F() { return U.getFloat( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static double testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + + static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static byte testF_B() { return U.getByte( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static short testF_S() { return U.getShort( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static char testF_C() { return U.getChar( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static int testF_I() { return U.getInt( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static long testF_J() { return U.getLong( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static float testF_F() { return U.getFloat( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static double testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + + static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static byte testD_B() { return U.getByte( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static short testD_S() { return U.getShort( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static char testD_C() { return U.getChar( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static int testD_I() { return U.getInt( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static long testD_J() { return U.getLong( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static float testD_F() { return U.getFloat( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static double testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + + static Object testL_L() { return U.getObject( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static byte testL_B() { return U.getByte( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static short testL_S() { return U.getShort( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static char testL_C() { return U.getChar( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static int testL_I() { return U.getInt( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static long testL_J() { return U.getLong( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static float testL_F() { return U.getFloat( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static double testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + + static short testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); } + static char testC_U() { return U.getCharUnaligned( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET + 1); } + static int testI_U() { return U.getIntUnaligned( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET + 1); } + static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); } + } + + static void run(Callable c) throws Exception { + run(c, null, null); + } + + static void run(Callable c, Runnable sameResultAction, Runnable changeResultAction) throws Exception { + Object first = c.call(); + + // Trigger compilation. + for (int i = 0; i < 20_000; i++) { + // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC). + c.call(); + } + + if (sameResultAction != null) { + sameResultAction.run(); + assertEQ(first, c.call()); + } + + if (changeResultAction != null) { + changeResultAction.run(); + assertNE(first, c.call()); + assertEQ(c.call(), c.call()); + } + } + + static void testMatched(Callable c, Runnable setDefaultAction) throws Exception { + run(c, setDefaultAction, null); + Setter.reset(); + } + + static void testMismatched(Callable c, Runnable setDefaultAction) throws Exception { + run(c, null, setDefaultAction); + Setter.reset(); + } + + public static void main(String[] args) throws Exception { + // boolean[], aligned accesses + testMatched( Test::testZ_Z, Test::changeZ); + testMismatched(Test::testZ_B, Test::changeZ); + testMismatched(Test::testZ_S, Test::changeZ); + testMismatched(Test::testZ_C, Test::changeZ); + testMismatched(Test::testZ_I, Test::changeZ); + testMismatched(Test::testZ_J, Test::changeZ); + testMismatched(Test::testZ_F, Test::changeZ); + testMismatched(Test::testZ_D, Test::changeZ); + + // byte[], aligned accesses + testMismatched(Test::testB_Z, Test::changeB); + testMatched( Test::testB_B, Test::changeB); + testMismatched(Test::testB_S, Test::changeB); + testMismatched(Test::testB_C, Test::changeB); + testMismatched(Test::testB_I, Test::changeB); + testMismatched(Test::testB_J, Test::changeB); + testMismatched(Test::testB_F, Test::changeB); + testMismatched(Test::testB_D, Test::changeB); + + // short[], aligned accesses + testMismatched(Test::testS_Z, Test::changeS); + testMismatched(Test::testS_B, Test::changeS); + testMatched( Test::testS_S, Test::changeS); + testMismatched(Test::testS_C, Test::changeS); + testMismatched(Test::testS_I, Test::changeS); + testMismatched(Test::testS_J, Test::changeS); + testMismatched(Test::testS_F, Test::changeS); + testMismatched(Test::testS_D, Test::changeS); + + // char[], aligned accesses + testMismatched(Test::testC_Z, Test::changeC); + testMismatched(Test::testC_B, Test::changeC); + testMismatched(Test::testC_S, Test::changeC); + testMatched( Test::testC_C, Test::changeC); + testMismatched(Test::testC_I, Test::changeC); + testMismatched(Test::testC_J, Test::changeC); + testMismatched(Test::testC_F, Test::changeC); + testMismatched(Test::testC_D, Test::changeC); + + // int[], aligned accesses + testMismatched(Test::testI_Z, Test::changeI); + testMismatched(Test::testI_B, Test::changeI); + testMismatched(Test::testI_S, Test::changeI); + testMismatched(Test::testI_C, Test::changeI); + testMatched( Test::testI_I, Test::changeI); + testMismatched(Test::testI_J, Test::changeI); + testMismatched(Test::testI_F, Test::changeI); + testMismatched(Test::testI_D, Test::changeI); + + // long[], aligned accesses + testMismatched(Test::testJ_Z, Test::changeJ); + testMismatched(Test::testJ_B, Test::changeJ); + testMismatched(Test::testJ_S, Test::changeJ); + testMismatched(Test::testJ_C, Test::changeJ); + testMismatched(Test::testJ_I, Test::changeJ); + testMatched( Test::testJ_J, Test::changeJ); + testMismatched(Test::testJ_F, Test::changeJ); + testMismatched(Test::testJ_D, Test::changeJ); + + // float[], aligned accesses + testMismatched(Test::testF_Z, Test::changeF); + testMismatched(Test::testF_B, Test::changeF); + testMismatched(Test::testF_S, Test::changeF); + testMismatched(Test::testF_C, Test::changeF); + testMismatched(Test::testF_I, Test::changeF); + testMismatched(Test::testF_J, Test::changeF); + testMatched( Test::testF_F, Test::changeF); + testMismatched(Test::testF_D, Test::changeF); + + // double[], aligned accesses + testMismatched(Test::testD_Z, Test::changeD); + testMismatched(Test::testD_B, Test::changeD); + testMismatched(Test::testD_S, Test::changeD); + testMismatched(Test::testD_C, Test::changeD); + testMismatched(Test::testD_I, Test::changeD); + testMismatched(Test::testD_J, Test::changeD); + testMismatched(Test::testD_F, Test::changeD); + testMatched( Test::testD_D, Test::changeD); + + // Object[], aligned accesses + testMismatched(Test::testL_J, Test::changeL); // long & double are always as large as an OOP + testMismatched(Test::testL_D, Test::changeL); + testMatched( Test::testL_L, Test::changeL); + + // Unaligned accesses + testMismatched(Test::testS_U, Test::changeS); + testMismatched(Test::testC_U, Test::changeC); + testMismatched(Test::testI_U, Test::changeI); + testMismatched(Test::testJ_U, Test::changeJ); + + // No way to reliably check the expected behavior: + // (1) OOPs change during GC; + // (2) there's no way to reliably change some part of an OOP (e.g., when reading a byte from it). + // + // Just trigger the compilation hoping to catch any problems with asserts. + run(Test::testL_B); + run(Test::testL_Z); + run(Test::testL_S); + run(Test::testL_C); + run(Test::testL_I); + run(Test::testL_F); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template --- a/hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/compiler/unsafe/X-UnsafeAccessTest.java.template Mon Mar 21 11:21:08 2016 +0100 @@ -170,6 +170,22 @@ #end[Ordered] #if[JdkInternalMisc] + // Lazy + { + UNSAFE.put$Type$Release(base, offset, $value1$); + $type$ x = UNSAFE.get$Type$Acquire(base, offset); + assertEquals(x, $value1$, "putRelease $type$ value"); + } + + // Opaque + { + UNSAFE.put$Type$Opaque(base, offset, $value2$); + $type$ x = UNSAFE.get$Type$Opaque(base, offset); + assertEquals(x, $value2$, "putOpaque $type$ value"); + } +#end[JdkInternalMisc] + +#if[JdkInternalMisc] #if[Unaligned] // Unaligned { @@ -210,6 +226,72 @@ assertEquals(x, $value2$, "failing compareAndSwap $type$ value"); } +#if[JdkInternalMisc] + // Advanced compare + { + $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value1$); + assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value"); + } + + { + $type$ r = UNSAFE.compareAndExchange$Type$Volatile(base, offset, $value2$, $value3$); + assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value"); + } + + { + $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value2$); + assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value"); + } + + { + $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value3$); + assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value"); + } + + { + $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value1$); + assertEquals(r, $value2$, "success compareAndExchangeRelease $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value"); + } + + { + $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value3$); + assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwap$Type$(base, offset, $value1$, $value2$); + assertEquals(r, true, "weakCompareAndSwap $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value2$, "weakCompareAndSwap $type$ value"); + } + + { + boolean r = UNSAFE.weakCompareAndSwap$Type$Acquire(base, offset, $value2$, $value1$); + assertEquals(r, true, "weakCompareAndSwapAcquire $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value1$, "weakCompareAndSwapAcquire $type$"); + } + + { + boolean r = UNSAFE.weakCompareAndSwap$Type$Release(base, offset, $value1$, $value2$); + assertEquals(r, true, "weakCompareAndSwapRelease $type$"); + $type$ x = UNSAFE.get$Type$(base, offset); + assertEquals(x, $value2$, "weakCompareAndSwapRelease $type$"); + } +#end[JdkInternalMisc] + // Compare set and get { $type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$); @@ -244,4 +326,5 @@ } #end[!boolean] #end[!Object] -} \ No newline at end of file +} + diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/compiler/unsafe/generate-unsafe-tests.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/unsafe/generate-unsafe-tests.sh Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,97 @@ +#!/bin/bash + +javac -d . ../../../../jdk/make/src/classes/build/tools/spp/Spp.java + +SPP=build.tools.spp.Spp + +# Generates unsafe access tests for objects and all primitive types +# $1 = package name to Unsafe, sun.misc | jdk.internal.misc +# $2 = test class qualifier name, SunMisc | JdkInternalMisc +function generate { + package=$1 + Qualifier=$2 + + for type in boolean byte short char int long float double Object + do + Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" + args="-K$type -Dtype=$type -DType=$Type" + + case $type in + Object|int|long) + args="$args -KCAS -KOrdered" + ;; + esac + + case $type in + int|long) + args="$args -KAtomicAdd" + ;; + esac + + case $type in + short|char|int|long) + args="$args -KUnaligned" + ;; + esac + + case $type in + boolean) + value1=true + value2=false + value3=false + ;; + byte) + value1=(byte)1 + value2=(byte)2 + value3=(byte)3 + ;; + short) + value1=(short)1 + value2=(short)2 + value3=(short)3 + ;; + char) + value1=\'a\' + value2=\'b\' + value3=\'c\' + ;; + int) + value1=1 + value2=2 + value3=3 + ;; + long) + value1=1L + value2=2L + value3=3L + ;; + float) + value1=1.0f + value2=2.0f + value3=3.0f + ;; + double) + value1=1.0d + value2=2.0d + value3=3.0d + ;; + Object) + value1=\"foo\" + value2=\"bar\" + value3=\"baz\" + ;; + esac + + args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3" + + echo $args + + java $SPP -nel -K$Qualifier -Dpackage=$package -DQualifier=$Qualifier \ + $args < X-UnsafeAccessTest.java.template > ${Qualifier}UnsafeAccessTest${Type}.java + done +} + +generate sun.misc SunMisc +generate jdk.internal.misc JdkInternalMisc + +rm -fr build \ No newline at end of file diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/gc/g1/TestGCLogMessages.java --- a/hotspot/test/gc/g1/TestGCLogMessages.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/gc/g1/TestGCLogMessages.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test TestGCLogMessages - * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 + * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 8150630 * @summary Ensure the output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -38,10 +38,24 @@ public class TestGCLogMessages { private enum Level { - OFF, DEBUG, TRACE; - public boolean lessOrEqualTo(Level other) { + OFF(""), + INFO("info"), + DEBUG("debug"), + TRACE("trace"); + + private String logName; + + Level(String logName) { + this.logName = logName; + } + + public boolean lessThan(Level other) { return this.compareTo(other) < 0; } + + public String toString() { + return logName; + } } private class LogMessageWithLevel { @@ -56,44 +70,48 @@ private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] { // Update RS - new LogMessageWithLevel("Scan HCC", Level.DEBUG), + new LogMessageWithLevel("Scan HCC", Level.TRACE), // Ext Root Scan - new LogMessageWithLevel("Thread Roots:", Level.DEBUG), - new LogMessageWithLevel("StringTable Roots:", Level.DEBUG), - new LogMessageWithLevel("Universe Roots:", Level.DEBUG), - new LogMessageWithLevel("JNI Handles Roots:", Level.DEBUG), - new LogMessageWithLevel("ObjectSynchronizer Roots:", Level.DEBUG), - new LogMessageWithLevel("FlatProfiler Roots", Level.DEBUG), - new LogMessageWithLevel("Management Roots", Level.DEBUG), - new LogMessageWithLevel("SystemDictionary Roots", Level.DEBUG), - new LogMessageWithLevel("CLDG Roots", Level.DEBUG), - new LogMessageWithLevel("JVMTI Roots", Level.DEBUG), - new LogMessageWithLevel("SATB Filtering", Level.DEBUG), - new LogMessageWithLevel("CM RefProcessor Roots", Level.DEBUG), - new LogMessageWithLevel("Wait For Strong CLD", Level.DEBUG), - new LogMessageWithLevel("Weak CLD Roots", Level.DEBUG), + new LogMessageWithLevel("Thread Roots", Level.TRACE), + new LogMessageWithLevel("StringTable Roots", Level.TRACE), + new LogMessageWithLevel("Universe Roots", Level.TRACE), + new LogMessageWithLevel("JNI Handles Roots", Level.TRACE), + new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE), + new LogMessageWithLevel("FlatProfiler Roots", Level.TRACE), + new LogMessageWithLevel("Management Roots", Level.TRACE), + new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE), + new LogMessageWithLevel("CLDG Roots", Level.TRACE), + new LogMessageWithLevel("JVMTI Roots", Level.TRACE), + new LogMessageWithLevel("SATB Filtering", Level.TRACE), + new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), + new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE), + new LogMessageWithLevel("Weak CLD Roots", Level.TRACE), // Redirty Cards new LogMessageWithLevel("Redirty Cards", Level.DEBUG), - new LogMessageWithLevel("Parallel Redirty", Level.DEBUG), - new LogMessageWithLevel("Redirtied Cards", Level.DEBUG), + new LogMessageWithLevel("Parallel Redirty", Level.TRACE), + new LogMessageWithLevel("Redirtied Cards", Level.TRACE), // Misc Top-level - new LogMessageWithLevel("Code Root Purge", Level.DEBUG), - new LogMessageWithLevel("String Dedup Fixup", Level.DEBUG), - new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG), + new LogMessageWithLevel("Code Roots Purge", Level.DEBUG), + new LogMessageWithLevel("String Dedup Fixup", Level.INFO), + new LogMessageWithLevel("Expand Heap After Collection", Level.INFO), // Free CSet - new LogMessageWithLevel("Young Free CSet", Level.TRACE), - new LogMessageWithLevel("Non-Young Free CSet", Level.TRACE), + new LogMessageWithLevel("Young Free Collection Set", Level.DEBUG), + new LogMessageWithLevel("Non-Young Free Collection Set", Level.DEBUG), // Humongous Eager Reclaim new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), new LogMessageWithLevel("Humongous Register", Level.DEBUG), + // Preserve CM Referents + new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), + // Merge PSS + new LogMessageWithLevel("Merge Per-Thread State", Level.INFO), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { for (LogMessageWithLevel l : messages) { - if (level.lessOrEqualTo(l.level)) { + if (level.lessThan(l.level)) { output.shouldNotContain(l.message); } else { - output.shouldContain(l.message); + output.shouldMatch("\\[" + l.level + ".*" + l.message); } } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/gc/g1/TestPLABOutput.java --- a/hotspot/test/gc/g1/TestPLABOutput.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/gc/g1/TestPLABOutput.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ System.out.println(output.getStdout()); - String pattern = ".*GC\\(0\\) .*allocated = (\\d+).*"; + String pattern = ".*GC\\(0\\) .*allocated: (\\d+).*"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(output.getStdout()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/gc/g1/plab/TestPLABPromotion.java --- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java Mon Mar 21 11:21:08 2016 +0100 @@ -23,7 +23,7 @@ /* * @test TestPLABPromotion - * @bug 8141278 + * @bug 8141278 8141141 * @summary Test PLAB promotion * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true @@ -130,16 +130,15 @@ long plabAllocatedOld; long directAllocatedOld; long memAllocated = testCase.getMemToFill(); - long wordSize = Platform.is32bit() ? 4l : 8l; LogParser logParser = new LogParser(output); Map survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS); Map oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS); - plabAllocatedSurvivor = wordSize * survivorStats.get("used"); - directAllocatedSurvivor = wordSize * survivorStats.get("direct_allocated"); - plabAllocatedOld = wordSize * oldStats.get("used"); - directAllocatedOld = wordSize * oldStats.get("direct_allocated"); + plabAllocatedSurvivor = survivorStats.get("used"); + directAllocatedSurvivor = survivorStats.get("direct allocated"); + plabAllocatedOld = oldStats.get("used"); + directAllocatedOld = oldStats.get("direct allocated"); System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated); System.out.printf("Old PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/gc/g1/plab/TestPLABResize.java --- a/hotspot/test/gc/g1/plab/TestPLABResize.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java Mon Mar 21 11:21:08 2016 +0100 @@ -23,7 +23,7 @@ /* * @test TestPLABResize - * @bug 8141278 + * @bug 8141278 8141141 * @summary Test for PLAB resizing * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true @@ -117,7 +117,7 @@ .map(item -> { return item.getValue() .get(LogParser.ReportType.SURVIVOR_STATS) - .get("desired_plab_sz"); + .get("actual"); }) .collect(Collectors.toCollection(ArrayList::new)); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/gc/g1/plab/lib/LogParser.java --- a/hotspot/test/gc/g1/plab/lib/LogParser.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/gc/g1/plab/lib/LogParser.java Mon Mar 21 11:21:08 2016 +0100 @@ -35,14 +35,12 @@ * * Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like: * - * [2,244s][info ][gc ] GC(30) Concurrent Mark abort - * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms - * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms - + * [0.330s][debug][gc,plab ] GC(0) Young PLAB allocation: allocated: 1825632B, wasted: 29424B, unused: 2320B, used: 1793888B, undo waste: 0B, + * [0.330s][debug][gc,plab ] GC(0) Young other allocation: region end waste: 0B, regions filled: 2, direct allocated: 271520B, failure used: 0B, failure wasted: 0B + * [0.330s][debug][gc,plab ] GC(0) Young sizing: calculated: 358776B, actual: 358776B + * [0.330s][debug][gc,plab ] GC(0) Old PLAB allocation: allocated: 427248B, wasted: 592B, unused: 368584B, used: 58072B, undo waste: 0B, + * [0.330s][debug][gc,plab ] GC(0) Old other allocation: region end waste: 0B, regions filled: 1, direct allocated: 41704B, failure used: 0B, failure wasted: 0B + * [0.330s][debug][gc,plab ] GC(0) Old sizing: calculated: 11608B, actual: 11608B */ final public class LogParser { @@ -53,7 +51,6 @@ * Type of parsed log element. */ public static enum ReportType { - SURVIVOR_STATS, OLD_STATS } @@ -64,8 +61,8 @@ // GC ID private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)"); - // Pattern for extraction pair = - private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+"); + // Pattern for extraction pair : + private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w* \\w+:\\s+\\d+"); /** * Construct LogParser Object @@ -108,24 +105,29 @@ if (matcher.find()) { Map> oneReportItem; ReportType reportType; - // Second line in log is statistics for Old PLAB allocation - if ( !allocationStatistics.containsKey(gc_id.get()) ) { - oneReportItem = new EnumMap<>(ReportType.class); + + if (!allocationStatistics.containsKey(gc_id.get())) { + allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class)); + } + + if ( line.contains("Young") ) { reportType = ReportType.SURVIVOR_STATS; - allocationStatistics.put(gc_id.get(), oneReportItem); } else { - oneReportItem = allocationStatistics.get(gc_id.get()); reportType = ReportType.OLD_STATS; } + oneReportItem = allocationStatistics.get(gc_id.get()); + if (!oneReportItem.containsKey(reportType)) { + oneReportItem.put(reportType,new HashMap()); + } + // Extract all pairs from log. - HashMap plabStats = new HashMap<>(); + Map plabStats = oneReportItem.get(reportType); do { String pair = matcher.group(); - String[] nameValue = pair.replaceAll(" ", "").split("="); - plabStats.put(nameValue[0], Long.parseLong(nameValue[1])); + String[] nameValue = pair.replaceAll(": ", ":").split(":"); + plabStats.put(nameValue[0].trim(), Long.parseLong(nameValue[1])); } while (matcher.find()); - oneReportItem.put(reportType,plabStats); } } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/native_sanity/JniVersion.java --- a/hotspot/test/native_sanity/JniVersion.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/native_sanity/JniVersion.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,12 @@ */ public class JniVersion { - public static final int JNI_VERSION_1_8 = 0x00010008; + public static final int JNI_VERSION_9 = 0x00090000; public static void main(String... args) throws Exception { System.loadLibrary("JniVersion"); int res = getJniVersion(); - if (res < JNI_VERSION_1_8) { + if (res != JNI_VERSION_9) { throw new Exception("Unexpected value returned from getJniVersion(): 0x" + Integer.toHexString(res)); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/runtime/logging/ItablesTest.java --- a/hotspot/test/runtime/logging/ItablesTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/runtime/logging/ItablesTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -49,7 +49,6 @@ output.shouldContain("invokespecial resolved method: caller-class:ClassB"); output.shouldContain("invokespecial selected method: resolved-class:ClassB"); output.shouldContain("invokeinterface selected method: receiver-class"); - output.shouldContain("Resolving: klass: "); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-Xlog:itables=trace", "ItablesVtableTest"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test ProtectionDomainVerificationTest + * @bug 8149064 + * @library /testlibrary + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.Platform jdk.test.lib.ProcessTools + * @run driver ProtectionDomainVerificationTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +public class ProtectionDomainVerificationTest { + + public static void main(String... args) throws Exception { + + // -Xlog:protectiondomain=trace + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=trace", + "-Xmx64m", + Hello.class.getName()); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldContain("[protectiondomain] Checking package access"); + out.shouldContain("[protectiondomain] pd set count = #"); + + // -Xlog:protectiondomain=debug + pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=debug", + "-Xmx64m", + Hello.class.getName()); + out = new OutputAnalyzer(pb.start()); + out.shouldContain("[protectiondomain] Checking package access"); + out.shouldNotContain("pd set count = #"); + } + + public static class Hello { + public static void main(String[] args) { + System.out.print("Hello!"); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/runtime/logging/ThreadLoggingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/logging/ThreadLoggingTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8149036 8150619 + * @summary os+thread output should contain logging calls for thread start stop attaches detaches + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver ThreadLoggingTest + * @author Thomas Stuefe (SAP) + */ + +import java.io.File; +import java.util.Map; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class ThreadLoggingTest { + + static void analyzeOutputForInfoLevel(OutputAnalyzer output) throws Exception { + output.shouldContain("Thread started"); + output.shouldContain("Thread is alive"); + output.shouldContain("Thread finished"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputForDebugLevel(OutputAnalyzer output) throws Exception { + analyzeOutputForInfoLevel(output); + output.shouldContain("stack dimensions"); + output.shouldContain("stack guard pages"); + } + + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + analyzeOutputForInfoLevel(output); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread=debug", "-version"); + output = new OutputAnalyzer(pb.start()); + analyzeOutputForDebugLevel(output); + + } + +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java --- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -24,25 +24,33 @@ /* * @test CompilerQueueTest * @bug 8054889 - * @library /testlibrary + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * jdk.jvmstat/sun.jvmstat.monitor - * @ignore 8069160 * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @run testng CompilerQueueTest - * @run testng/othervm -XX:-TieredCompilation CompilerQueueTest - * @run testng/othervm -Xint CompilerQueueTest + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -Xmixed -XX:+WhiteBoxAPI CompilerQueueTest + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -Xmixed -XX:-TieredCompilation -XX:+WhiteBoxAPI CompilerQueueTest + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -Xint -XX:+WhiteBoxAPI CompilerQueueTest * @summary Test of diagnostic command Compiler.queue */ +import compiler.testlibrary.CompilerUtils; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; import org.testng.annotations.Test; +import org.testng.Assert; +import sun.hotspot.WhiteBox; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; import java.util.Iterator; public class CompilerQueueTest { @@ -54,70 +62,123 @@ * * Output example: * - * Contents of C1 compile queue - * ---------------------------- - * 73 3 java.lang.AbstractStringBuilder::append (50 bytes) - * 74 1 java.util.TreeMap::size (5 bytes) - * 75 3 java.lang.StringBuilder::append (8 bytes) - * 83 3 java.util.TreeMap$ValueIterator::next (8 bytes) - * 84 1 javax.management.MBeanFeatureInfo::getName (5 bytes) - * ---------------------------- - * Contents of C2 compile queue - * ---------------------------- + * Current compiles: + * C1 CompilerThread14 267 3 java.net.URLStreamHandler::parseURL (1166 bytes) + * C1 CompilerThread13 760 3 javax.management.StandardMBean::getDescription (11 bytes) + * C1 CompilerThread12 757 s 3 com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory::getMapping (27 bytes) + * C1 CompilerThread11 756 s! 3 com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory::mappingForType (110 bytes) + * C1 CompilerThread10 761 3 java.lang.StringLatin1::indexOf (121 bytes) + * C2 CompilerThread7 769 4 CompilerQueueTest::testcaseMethod4 (1 bytes) + * + * C1 compile queue: + * 762 3 java.lang.invoke.MethodType::basicType (8 bytes) + * 763 3 java.util.ArrayList::rangeCheck (22 bytes) + * 764 3 java.util.ArrayList::elementData (7 bytes) + * 765 3 jdk.internal.org.objectweb.asm.MethodVisitor:: (35 bytes) + * 766 1 CompilerQueueTest::testcaseMethod1 (1 bytes) + * 767 2 CompilerQueueTest::testcaseMethod2 (1 bytes) + * 768 3 CompilerQueueTest::testcaseMethod3 (1 bytes) + * 770 3 java.util.Properties::getProperty (46 bytes) + * + * C2 compile queue: * Empty - * ---------------------------- * **/ + protected static final WhiteBox WB = WhiteBox.getWhiteBox(); + public void run(CommandExecutor executor) { + TestCase[] testcases = { + new TestCase(1, "testcaseMethod1"), + new TestCase(2, "testcaseMethod2"), + new TestCase(3, "testcaseMethod3"), + new TestCase(4, "testcaseMethod4"), + }; + + // Lock compilation makes all compiles stay in queue or compile thread before completion + WB.lockCompilation(); + + // Enqueue one test method for each available level + int[] complevels = CompilerUtils.getAvailableCompilationLevels(); + for (int level : complevels) { + TestCase testcase = testcases[level - 1]; + + boolean added = WB.enqueueMethodForCompilation(testcase.method, testcase.level); + // Set results to false for those methods we must to find + // We will also assert if we find any test method we don't expect + Assert.assertTrue(WB.isMethodQueuedForCompilation(testcase.method)); + testcase.check = false; + } + // Get output from dcmd (diagnostic command) OutputAnalyzer output = executor.execute("Compiler.queue"); Iterator lines = output.asLines().iterator(); + // Loop over output set result for all found methods while (lines.hasNext()) { String str = lines.next(); - if (str.startsWith("Contents of C")) { - match(lines.next(), "----------------------------"); - str = lines.next(); - if (!str.equals("Empty")) { - while (str.charAt(0) != '-') { - validateMethodLine(str); - str = lines.next(); + // Fast check for common part of method name + if (str.contains("testcaseMethod")) { + for (TestCase testcase : testcases) { + if (str.contains(testcase.methodName)) { + Assert.assertFalse(testcase.check, "Must not be found or already found."); + testcase.check = true; } - } else { - str = lines.next(); } - match(str,"----------------------------"); - } else { - Assert.fail("Failed parsing dcmd queue, line: " + str); } } - } - private static void validateMethodLine(String str) { - // Skip until package/class name begins. Trim to remove whitespace that - // may differ. - String name = str.substring(14).trim(); - int sep = name.indexOf("::"); - if (sep == -1) { - Assert.fail("Failed dcmd queue, didn't find separator :: in: " + name); + for (TestCase testcase : testcases) { + if (!testcase.check) { + // If this method wasn't found it must have been removed by policy, + // verify that it is now removed from the queue + Assert.assertFalse(WB.isMethodQueuedForCompilation(testcase.method), "Must be found or not in queue"); + } + // Otherwise all good. } - try { - Class.forName(name.substring(0, sep)); - } catch (ClassNotFoundException e) { - Assert.fail("Failed dcmd queue, Class for name: " + str); - } - } - public static void match(String line, String str) { - if (!line.equals(str)) { - Assert.fail("String equals: " + line + ", " + str); - } + // Enable compilations again + WB.unlockCompilation(); } @Test public void jmx() { run(new JMXExecutor()); } + + public void testcaseMethod1() { + } + + public void testcaseMethod2() { + } + + public void testcaseMethod3() { + } + + public void testcaseMethod4() { + } + + public static Method getMethod(Class klass, String name, Class... parameterTypes) { + try { + return klass.getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException("exception on getting method Helper." + name, e); + } + } + + class TestCase { + Method method; + int level; + String methodName; + Boolean check; + + public TestCase(int level, String methodName) { + this.method = getMethod(CompilerQueueTest.class, methodName); + this.level = level; + this.methodName = methodName; + this.check = true; + } + } + } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java --- a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -22,6 +22,10 @@ */ import java.io.*; import java.nio.file.*; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import jdk.test.lib.*; import jdk.test.lib.dcmd.*; import org.testng.annotations.Test; @@ -55,12 +59,7 @@ "'-Dtest.jdk=/path/to/jdk'."); } - Path libpath; - if (Platform.isWindows()) { - libpath = Paths.get(jdkPath, "bin", "instrument.dll"); - } else { - libpath = Paths.get(jdkPath, "lib", Platform.getOsArch(), "libinstrument.so"); - } + Path libpath = Paths.get(jdkPath, Platform.jdkLibPath(), Platform.sharedObjectName("instrument")); if (!libpath.toFile().exists()) { throw new FileNotFoundException( @@ -70,31 +69,62 @@ return libpath.toAbsolutePath().toString(); } + + public void createJarFileForAgent() + throws IOException { + + final String jarName = "agent.jar"; + final String agentClass = "SimpleJvmtiAgent"; + + Manifest manifest = new Manifest(); + + manifest.getMainAttributes().put( + Attributes.Name.MANIFEST_VERSION, "1.0"); + + manifest.getMainAttributes().put( + new Attributes.Name("Agent-Class"), agentClass); + + JarOutputStream target = null; + + try { + target = new + JarOutputStream(new FileOutputStream(jarName), manifest); + JarEntry entry = new JarEntry(agentClass + ".class"); + target.putNextEntry(entry); + target.closeEntry(); + } finally { + target.close(); + } + } + public void run(CommandExecutor executor) { try{ - PrintWriter pw = new PrintWriter("MANIFEST.MF"); - pw.println("Agent-Class: SimpleJvmtiAgent"); - pw.close(); - ProcessBuilder pb = new ProcessBuilder(); - pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), - "cmf", - "MANIFEST.MF", - "agent.jar", - "SimpleJvmtiAgent.class"}); - pb.start().waitFor(); + createJarFileForAgent(); String libpath = getLibInstrumentPath(); + OutputAnalyzer output = null; - // Test 1: No argument - OutputAnalyzer output = executor.execute("JVMTI.agent_load " + - libpath + " agent.jar"); + // Test 1: Native agent, no arguments + output = executor.execute("JVMTI.agent_load " + + libpath + " agent.jar"); output.stderrShouldBeEmpty(); - // Test 2: With argument + // Test 2: Native agent, with arguments + output = executor.execute("JVMTI.agent_load " + + libpath + " \"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + + // Test 3: Java agent, no arguments output = executor.execute("JVMTI.agent_load " + - libpath + " \"agent.jar=foo=bar\""); + "agent.jar"); output.stderrShouldBeEmpty(); + + // Test 4: Java agent, with arguments + output = executor.execute("JVMTI.agent_load " + + "\"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + } catch (Exception e) { throw new RuntimeException(e); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java --- a/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.*; -import jdk.test.lib.*; -import jdk.test.lib.dcmd.*; -import org.testng.annotations.Test; - -/* - * Test to attach JVMTI java agent. - * - * @test - * @bug 8147388 - * @library /testlibrary - * @modules java.base/sun.misc - * java.compiler - * java.instrument - * java.management - * jdk.jvmstat/sun.jvmstat.monitor - * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent - * @run main ClassFileInstaller SimpleJvmtiAgent - * @run testng LoadJavaAgentDcmdTest - */ -public class LoadJavaAgentDcmdTest { - public void run(CommandExecutor executor) { - try{ - PrintWriter pw = new PrintWriter("MANIFEST.MF"); - pw.println("Agent-Class: SimpleJvmtiAgent"); - pw.close(); - - ProcessBuilder pb = new ProcessBuilder(); - pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), - "cmf", - "MANIFEST.MF", - "agent.jar", - "SimpleJvmtiAgent.class"}); - pb.start().waitFor(); - - // Test 1: No argument - OutputAnalyzer output = executor.execute("JVMTI.agent_load " + - "agent.jar"); - output.stderrShouldBeEmpty(); - - // Test 2: With argument - output = executor.execute("JVMTI.agent_load " + - "\"agent.jar=foo=bar\""); - output.stderrShouldBeEmpty(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Test - public void jmx() throws Throwable { - run(new JMXExecutor()); - } - - @Test - public void cli() throws Throwable { - run(new PidJcmdExecutor()); - } -} diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java --- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,6 @@ public class JMapHProfLargeHeapTest { private static final String HEAP_DUMP_FILE_NAME = "heap.hprof"; - private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; private static final long M = 1024L; private static final long G = 1024L * M; @@ -79,8 +78,8 @@ } } - // Small heap 22 megabytes, should create 1.0.1 file format - testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1); + // All heap dumps should create 1.0.2 file format + testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_2); /** * This test was deliberately commented out since the test system lacks diff -r 0dc62e7c6a29 -r 74e9f4b90006 hotspot/test/testlibrary/jdk/test/lib/Platform.java --- a/hotspot/test/testlibrary/jdk/test/lib/Platform.java Mon Mar 21 08:42:00 2016 +0100 +++ b/hotspot/test/testlibrary/jdk/test/lib/Platform.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,4 +203,31 @@ public static boolean canAttachOSX() throws Exception { return userName.equals("root"); } + + /** + * return path to library inside jdk tree + */ + public static String jdkLibPath() { + if (isWindows()) { + return "bin"; + } + if (isOSX()) { + return "lib"; + } + + return "lib/" + getOsArch(); + } + + /** + * Build name of shared object according to platform rules + */ + public static String sharedObjectName(String name) { + if (isWindows()) { + return name + ".dll"; + } + if (isOSX()) { + return "lib" + name + ".dylib"; + } + return "lib" + name + ".so"; + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/.hgtags --- a/jaxp/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -351,3 +351,4 @@ 65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106 781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107 3b9fa8b1491479f7ae18131a34036b58b647493e jdk-9+108 +24e247ee1fffaa625d480b2a4eef2d3a8a59f5cb jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: DOM.java,v 1.2.4.1 2005/08/31 10:18:49 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc; @@ -102,4 +99,5 @@ public int getDocument(); public String getUnparsedEntityURI(String name); public Map getElementsWithIDs(); + public void release(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: ApplyTemplates.java,v 1.2.4.1 2005/09/12 09:59:21 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -122,12 +119,10 @@ final int current = methodGen.getLocalIndex("current"); // check if sorting nodes is required - final Vector sortObjects = new Vector(); - final Iterator children = elements(); - while (children.hasNext()) { - final SyntaxTreeNode child = children.next(); + final Vector sortObjects = new Vector<>(); + for (final SyntaxTreeNode child : getContents()) { if (child instanceof Sort) { - sortObjects.addElement(child); + sortObjects.addElement((Sort)child); } } @@ -193,6 +188,13 @@ applyTemplatesSig); il.append(new INVOKEVIRTUAL(applyTemplates)); + // unmap parameters to release temporary result trees + for (final SyntaxTreeNode child : getContents()) { + if (child instanceof WithParam) { + ((WithParam)child).releaseResultTree(classGen, methodGen); + } + } + // Pop parameter frame if (stylesheet.hasLocalParams() || hasContents()) { il.append(classGen.loadTranslet()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,18 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: CallTemplate.java,v 1.2.4.1 2005/09/12 10:02:41 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import com.sun.org.apache.bcel.internal.generic.ALOAD; -import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionList; -import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; @@ -56,7 +49,7 @@ * this array can be either a WithParam or a Param if no WithParam * exists for a particular parameter. */ - private Object[] _parameters = null; + private SyntaxTreeNode[] _parameters = null; /** * The corresponding template which this CallTemplate calls. @@ -147,11 +140,10 @@ // If calling a simply named template, push actual arguments if (_calleeTemplate != null) { - Vector calleeParams = _calleeTemplate.getParameters(); int numParams = _parameters.length; for (int i = 0; i < numParams; i++) { - SyntaxTreeNode node = (SyntaxTreeNode)_parameters[i]; + SyntaxTreeNode node = _parameters[i]; methodSig.append(OBJECT_SIG); // append Object to signature // Push 'null' if Param to indicate no actual parameter specified @@ -170,6 +162,15 @@ methodName, methodSig.toString()))); + // release temporary result trees + if (_parameters != null) { + for (int i = 0; i < _parameters.length; i++) { + if (_parameters[i] instanceof WithParam) { + ((WithParam)_parameters[i]).releaseResultTree(classGen, methodGen); + } + } + } + // Do not need to call Translet.popParamFrame() if we are // calling a simple named template. if (_calleeTemplate == null && (stylesheet.hasLocalParams() || hasContents())) { @@ -203,9 +204,9 @@ private void buildParameterList() { // Put the parameters from the called template into the array first. // This is to ensure the order of the parameters. - Vector defaultParams = _calleeTemplate.getParameters(); + Vector defaultParams = _calleeTemplate.getParameters(); int numParams = defaultParams.size(); - _parameters = new Object[numParams]; + _parameters = new SyntaxTreeNode[numParams]; for (int i = 0; i < numParams; i++) { _parameters[i] = defaultParams.elementAt(i); } @@ -222,15 +223,15 @@ // Search for a Param with the same name for (int k = 0; k < numParams; k++) { - Object object = _parameters[k]; - if (object instanceof Param - && ((Param)object).getName().equals(name)) { + SyntaxTreeNode parm = _parameters[k]; + if (parm instanceof Param + && ((Param)parm).getName().equals(name)) { withParam.setDoParameterOptimization(true); _parameters[k] = withParam; break; } - else if (object instanceof WithParam - && ((WithParam)object).getName().equals(name)) { + else if (parm instanceof WithParam + && ((WithParam)parm).getName().equals(name)) { withParam.setDoParameterOptimization(true); _parameters[k] = withParam; break; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2005 The Apache Software Foundation. @@ -17,32 +16,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Sort.java,v 1.2.4.1 2005/09/12 11:08:12 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import java.text.Collator; import java.util.ArrayList; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; import java.util.Vector; import com.sun.org.apache.bcel.internal.classfile.Field; -import com.sun.org.apache.bcel.internal.classfile.Method; import com.sun.org.apache.bcel.internal.generic.ALOAD; import com.sun.org.apache.bcel.internal.generic.ANEWARRAY; import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.GETFIELD; -import com.sun.org.apache.bcel.internal.generic.ICONST; import com.sun.org.apache.bcel.internal.generic.ILOAD; import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; -import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; -import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionHandle; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; @@ -76,13 +65,10 @@ private AttributeValue _order; private AttributeValue _caseOrder; private AttributeValue _dataType; - private String _lang; // bug! see 26869 - - private String _data = null; - + private String _lang; // bug! see 26869 private String _className = null; - private ArrayList _closureVars = null; + private ArrayList _closureVars = null; private boolean _needsSortRecordFactory = false; // -- Begin Closure interface -------------------- @@ -115,7 +101,7 @@ */ public void addVariable(VariableRefBase variableRef) { if (_closureVars == null) { - _closureVars = new ArrayList(); + _closureVars = new ArrayList<>(); } // Only one reference per variable @@ -246,7 +232,7 @@ public static void translateSortIterator(ClassGenerator classGen, MethodGenerator methodGen, Expression nodeSet, - Vector sortObjects) + Vector sortObjects) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); @@ -312,7 +298,7 @@ * Compiles code that instantiates a NodeSortRecordFactory object which * will produce NodeSortRecord objects of a specific type. */ - public static void compileSortRecordFactory(Vector sortObjects, + public static void compileSortRecordFactory(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { String sortRecordClass = @@ -321,7 +307,7 @@ boolean needsSortRecordFactory = false; final int nsorts = sortObjects.size(); for (int i = 0; i < nsorts; i++) { - final Sort sort = (Sort) sortObjects.elementAt(i); + final Sort sort = sortObjects.elementAt(i); needsSortRecordFactory |= sort._needsSortRecordFactory; } @@ -429,7 +415,7 @@ + "[" + STRING_SIG + ")V"))); // Initialize closure variables in sortRecordFactory - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { final Sort sort = (Sort) sortObjects.get(j); @@ -437,7 +423,7 @@ sort._closureVars.size(); for (int i = 0; i < length; i++) { - VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); + VariableRefBase varRef = sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; @@ -455,11 +441,11 @@ } } - public static String compileSortRecordFactory(Vector sortObjects, + public static String compileSortRecordFactory(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen, String sortRecordClass) { - final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); + final XSLTC xsltc = (sortObjects.firstElement()).getXSLTC(); final String className = xsltc.getHelperClassName(); final NodeSortRecordFactGenerator sortRecordFactory = @@ -474,15 +460,15 @@ // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { - final Sort sort = (Sort) sortObjects.get(j); + final Sort sort = sortObjects.get(j); final int length = (sort._closureVars == null) ? 0 : sort._closureVars.size(); for (int i = 0; i < length; i++) { - final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); + final VariableRefBase varRef = sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; @@ -600,10 +586,10 @@ /** * Create a new auxillary class extending NodeSortRecord. */ - private static String compileSortRecord(Vector sortObjects, + private static String compileSortRecord(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { - final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); + final XSLTC xsltc = sortObjects.firstElement().getXSLTC(); final String className = xsltc.getHelperClassName(); // This generates a new class for handling this specific sort @@ -619,10 +605,10 @@ // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { - final Sort sort = (Sort) sortObjects.get(j); + final Sort sort = sortObjects.get(j); // Set the name of the inner class in this sort object sort.setInnerClassName(className); @@ -644,8 +630,7 @@ } } - MethodGenerator init = compileInit(sortObjects, sortRecord, - cpg, className); + MethodGenerator init = compileInit(sortRecord, cpg, className); MethodGenerator extract = compileExtract(sortObjects, sortRecord, cpg, className); sortRecord.addMethod(init); @@ -660,8 +645,7 @@ * collator in the super calls only when the stylesheet specifies a new * language in xsl:sort. */ - private static MethodGenerator compileInit(Vector sortObjects, - NodeSortRecordGenerator sortRecord, + private static MethodGenerator compileInit(NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) { @@ -688,7 +672,7 @@ /** * Compiles a method that overloads NodeSortRecord.extractValueFromDOM() */ - private static MethodGenerator compileExtract(Vector sortObjects, + private static MethodGenerator compileExtract(Vector sortObjects, NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) { @@ -730,7 +714,7 @@ // Append all the cases for the switch statment for (int level = 0; level < levels; level++) { match[level] = level; - final Sort sort = (Sort)sortObjects.elementAt(level); + final Sort sort = sortObjects.elementAt(level); target[level] = il.append(NOP); sort.translateSelect(sortRecord, extractMethod); il.append(ARETURN); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SyntaxTreeNode.java,v 1.6 2006/06/06 22:34:33 spericas Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -519,9 +516,9 @@ // references falling out-of-scope inside the for-each element. // (the cause of which being 'lazy' register allocation for references) for (int i = 0; i < n; i++) { - if( _contents.get(i) instanceof VariableBase) { + if ( _contents.get(i) instanceof VariableBase) { final VariableBase var = (VariableBase)_contents.get(i); - var.unmapRegister(methodGen); + var.unmapRegister(classGen, methodGen); } } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Template.java,v 1.2.4.1 2005/09/12 11:30:11 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -63,7 +60,7 @@ // The list of parameters in this template. This is only used // for simple named templates. - private Vector _parameters = new Vector(); + private Vector _parameters = new Vector<>(); public boolean hasParams() { return _parameters.size() > 0; @@ -85,7 +82,7 @@ _parameters.addElement(param); } - public Vector getParameters() { + public Vector getParameters() { return _parameters; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,18 +16,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: VariableBase.java,v 1.5 2005/09/28 13:48:18 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; import java.util.Vector; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.Instruction; import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; +import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.bcel.internal.generic.NEW; import com.sun.org.apache.bcel.internal.generic.PUSH; @@ -36,6 +35,7 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import com.sun.org.apache.xml.internal.utils.XML11Char; @@ -49,21 +49,18 @@ */ class VariableBase extends TopLevelElement { - protected QName _name; // The name of the variable. - protected String _escapedName; // The escaped qname of the variable. - protected Type _type; // The type of this variable. - protected boolean _isLocal; // True if the variable is local. - protected LocalVariableGen _local; // Reference to JVM variable - protected Instruction _loadInstruction; // Instruction to load JVM variable + protected QName _name; // The name of the variable. + protected String _escapedName; // The escaped qname of the variable. + protected Type _type; // The type of this variable. + protected boolean _isLocal; // True if the variable is local. + protected LocalVariableGen _local; // Reference to JVM variable + protected Instruction _loadInstruction; // Instruction to load JVM variable protected Instruction _storeInstruction; // Instruction to load JVM variable - protected Expression _select; // Reference to variable expression - protected String select; // Textual repr. of variable expr. + protected Expression _select; // Reference to variable expression + protected String select; // Textual repr. of variable expr. // References to this variable (when local) - protected Vector _refs = new Vector(2); - - // Dependencies to other variables/parameters (for globals only) - protected Vector _dependencies = null; + protected Vector _refs = new Vector<>(2); // Used to make sure parameter field is not added twice protected boolean _ignore = false; @@ -92,7 +89,7 @@ public void copyReferences(VariableBase var) { final int size = _refs.size(); for (int i = 0; i < size; i++) { - var.addReference((VariableRefBase) _refs.get(i)); + var.addReference(_refs.get(i)); } } @@ -112,8 +109,24 @@ * Remove the mapping of this variable to a register. * Called when we leave the AST scope of the variable's declaration */ - public void unmapRegister(MethodGenerator methodGen) { + public void unmapRegister(ClassGenerator classGen, MethodGenerator methodGen) { if (_local != null) { + if (_type instanceof ResultTreeType) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + if (classGen.getStylesheet().callsNodeset() && classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeDA = cpg.addMethodref(MULTI_DOM_CLASS, "removeDOMAdapter", "(" + DOM_ADAPTER_SIG + ")V"); + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(loadInstruction()); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeDA)); + } + final int release = cpg.addInterfaceMethodref(DOM_IMPL_CLASS, "release", "()V"); + il.append(loadInstruction()); + il.append(new INVOKEINTERFACE(release, 1)); + } + _local.setEnd(methodGen.getInstructionList().getEnd()); methodGen.removeLocalVariable(_local); _refs = null; @@ -126,7 +139,6 @@ * the JVM stack. */ public Instruction loadInstruction() { - final Instruction instr = _loadInstruction; if (_loadInstruction == null) { _loadInstruction = _type.LOAD(_local.getIndex()); } @@ -138,7 +150,6 @@ * into this variable. */ public Instruction storeInstruction() { - final Instruction instr = _storeInstruction; if (_storeInstruction == null) { _storeInstruction = _type.STORE(_local.getIndex()); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,15 +16,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: WithParam.java,v 1.2.4.1 2005/09/12 11:38:01 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ASTORE; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.bcel.internal.generic.PUSH; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; @@ -60,6 +61,11 @@ private Expression _select; /** + * Reference to JVM variable holding temporary result tree. + */ + private LocalVariableGen _domAdapter; + + /** * %OPT% This is set to true when the WithParam is used in a CallTemplate * for a simple named template. If this is true, the parameters are * passed to the named template through method arguments rather than @@ -164,8 +170,13 @@ _select.startIterator(classGen, methodGen); } // If not, compile result tree from parameter body if present. + // Store result tree into local variable for releasing it later else if (hasContents()) { + final InstructionList il = methodGen.getInstructionList(); compileResultTree(classGen, methodGen); + _domAdapter = methodGen.addLocalVariable2("@" + _escapedName, Type.ResultTree.toJCType(), il.getEnd()); + il.append(DUP); + il.append(new ASTORE(_domAdapter.getIndex())); } // If neither are present then store empty string in parameter slot else { @@ -208,4 +219,26 @@ ADD_PARAMETER_SIG))); il.append(POP); // cleanup stack } + + /** + * Release the compiled result tree. + */ + public void releaseResultTree(ClassGenerator classGen, MethodGenerator methodGen) { + if (_domAdapter != null) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + if (classGen.getStylesheet().callsNodeset() && classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeDA = cpg.addMethodref(MULTI_DOM_CLASS, "removeDOMAdapter", "(" + DOM_ADAPTER_SIG + ")V"); + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(new ALOAD(_domAdapter.getIndex())); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeDA)); + } + final int release = cpg.addInterfaceMethodref(DOM_IMPL_CLASS, "release", "()V"); + il.append(new ALOAD(_domAdapter.getIndex())); + il.append(new INVOKEINTERFACE(release, 1)); + _domAdapter = null; + } + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: AdaptiveResultTreeImpl.java,v 1.2.4.1 2005/09/06 05:52:18 pvedula Exp $ - */ + package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.DOM; @@ -1338,4 +1336,11 @@ } } + public void release() { + if (_dom != null) { + _dom.release(); + _dom = null; + } + super.release(); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: DOMAdapter.java,v 1.2.4.1 2005/09/06 06:07:28 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.dom; @@ -56,8 +53,6 @@ private short[] _NSmapping = null; private short[] _NSreverse = null; - private StripFilter _filter = null; - private int _multiDOMMask; public DOMAdapter(DOM dom, @@ -165,9 +160,7 @@ } } - public void setFilter(StripFilter filter) { - _filter = filter; - } + public void setFilter(StripFilter filter) {} public DTMAxisIterator getTypedChildren(final int type) { final int[] reverse = getReverse(); @@ -464,4 +457,8 @@ public Map getElementsWithIDs() { return _dom.getElementsWithIDs(); } + + public void release() { + _dom.release(); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,7 +1,6 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -30,8 +29,8 @@ import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.dtm.DTMManager; import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase; +import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIterNodeList; import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; -import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIterNodeList; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector; import java.util.HashMap; @@ -671,4 +670,51 @@ public Map getElementsWithIDs() { return _main.getElementsWithIDs(); } + + public void release() { + _main.release(); + } + + private boolean isMatchingAdapterEntry(DOM entry, DOMAdapter adapter) { + DOM dom = adapter.getDOMImpl(); + + return (entry == adapter) || ( + /* + * Method addDOMAdapter overwrites for AdaptiveResultTreeImpl + * objects the usual entry with an adapter to the nested + * DOM, so we must check this here. See last 'if' statement + * of addDOMAdapter. + */ + (dom instanceof AdaptiveResultTreeImpl) && + (entry instanceof DOMAdapter) && + (((AdaptiveResultTreeImpl)dom).getNestedDOM() == ((DOMAdapter)entry).getDOMImpl()) + ); + } + + public void removeDOMAdapter(DOMAdapter adapter) { + _documents.remove(adapter.getDocumentURI(0)); + DOM dom = adapter.getDOMImpl(); + + if (dom instanceof DTMDefaultBase) { + SuballocatedIntVector ids = ((DTMDefaultBase) dom).getDTMIDs(); + int idsSize = ids.size(); + for (int i = 0; i < idsSize; i++) { + _adapters[ids.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS] = null; + } + } else { + int id = dom.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS; + if ((id > 0) && (id < _adapters.length) && isMatchingAdapterEntry(_adapters[id], adapter)) { + _adapters[id] = null; + } else { + boolean found = false; + for (int i = 0; i < _adapters.length; i++) { + if (isMatchingAdapterEntry(_adapters[id], adapter)) { + _adapters[i] = null; + found = true; + break; + } + } + } + } + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SAXImpl.java,v 1.5 2005/09/28 13:48:37 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.dom; @@ -82,7 +79,7 @@ // Namespace prefix-to-uri mapping stuff private int _uriCount = 0; - private int _prefixCount = 0; + // private int _prefixCount = 0; // Stack used to keep track of what whitespace text nodes are protected // by xml:space="preserve" attributes and which nodes that are not. @@ -90,11 +87,11 @@ private int _idx = 1; private boolean _preserve = false; - private static final String XML_STRING = "xml:"; + // private static final String XML_STRING = "xml:"; private static final String XML_PREFIX = "xml"; private static final String XMLSPACE_STRING = "xml:space"; private static final String PRESERVE_STRING = "preserve"; - private static final String XMLNS_PREFIX = "xmlns"; + // private static final String XMLNS_PREFIX = "xmlns"; private static final String XML_URI = "http://www.w3.org/XML/1998/namespace"; private boolean _escaping = true; @@ -123,7 +120,7 @@ private BitArray _dontEscape = null; // The URI to this document - private String _documentURI = null; + // private String _documentURI = null; static private int _documentURIIndex = 0; // The owner Document when the input source is DOMSource. @@ -143,8 +140,7 @@ // Support for access/navigation through org.w3c.dom API private Node[] _nodes; private NodeList[] _nodeLists; - private final static String XML_LANG_ATTRIBUTE = - "http://www.w3.org/XML/1998/namespace:@lang"; + // private final static String XML_LANG_ATTRIBUTE = "http://www.w3.org/XML/1998/namespace:@lang"; /** * Define the origin of the document from which the tree was built @@ -491,6 +487,7 @@ /** * Sets up a translet-to-dom type mapping table */ + /* private int[] setupMapping(String[] names, String[] uris, int[] types, int nNames) { // Padding with number of names, because they // may need to be added, i.e for RTFs. See copy03 @@ -502,6 +499,7 @@ } return result; } + */ /** * Returns the internal type associated with an expanded QName @@ -1230,9 +1228,6 @@ */ public DTMAxisIterator getNamespaceAxisIterator(int axis, int ns) { - - DTMAxisIterator iterator = null; - if (ns == NO_TYPE) { return EMPTYITERATOR; } @@ -1546,7 +1541,6 @@ */ public DTMAxisIterator getNthDescendant(int type, int n, boolean includeself) { - DTMAxisIterator source = (DTMAxisIterator) new TypedDescendantIterator(type); return new NthDescendantIterator(n); } @@ -1882,4 +1876,7 @@ } } + public void release() { + _dtmManager.release(this, true); + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 1999-2004 The Apache Software Foundation. @@ -17,15 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SimpleResultTreeImpl.java,v 1.2.4.1 2005/09/06 10:09:25 pvedula Exp $ - */ + package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.StripFilter; import com.sun.org.apache.xalan.internal.xsltc.TransletException; - import com.sun.org.apache.xml.internal.dtm.Axis; import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; @@ -1014,4 +1010,12 @@ public void migrateTo(DTMManager manager) { } + + public void release() + { + if (_documentID != 0) { + _dtmManager.release(this, true); + _documentID = 0; + } + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ - - -10016 -Wed May 29 12:45:00 PDT 2002 - -ABC -XYZ -1234 Anywhere Street -Palo Alto -California -USA -94303 -NULL -NULL - - - - - \ No newline at end of file diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.net.URL; import javax.xml.parsers.SAXParser; @@ -45,16 +46,27 @@ * @summary Test transform with external dtd. */ public class Bug4693341Test { + // save dtd file to current working directory to avoid writing into source repository + public void copyDTDtoWorkDir() throws IOException { + try (FileInputStream dtdres = new FileInputStream(getClass().getResource("Bug4693341.dtd").getPath()); + FileOutputStream dtdwork = new FileOutputStream("Bug4693341.dtd");) { + int n; + byte[] buffer = new byte[1024]; + while((n = dtdres.read(buffer)) > -1) { + dtdwork.write(buffer, 0, n); + } + } + } @Test public void test() { - boolean status = false; - try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); - String out = getClass().getResource("Bug4693341.out").getPath(); - StreamResult result = new StreamResult(new FileOutputStream(out)); + copyDTDtoWorkDir(); + + File outf = new File("Bug4693341.out"); + StreamResult result = new StreamResult(new FileOutputStream(outf)); String in = getClass().getResource("Bug4693341.xml").getPath(); File file = new File(in); @@ -63,7 +75,7 @@ transformer.transform(source, result); //URL inputsource = new URL("file", "", golden); - URL output = new URL("file", "", out); + URL output = new URL("file", "", outf.getPath()); // error happens when trying to parse output String systemId = output.toExternalForm(); @@ -71,10 +83,8 @@ InputSource is = new InputSource(systemId); SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); parser.parse(is, new DefaultHandler()); - } catch (Exception ex) { Assert.fail(ex.getMessage()); } } - } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ - - - -10016 -Wed May 29 12:45:00 PDT 2002 - -ABC -XYZ -1234 Anywhere Street -Palo Alto -California -USA -94303 -NULL -NULL - - - - - diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package transform; - -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; - -import org.testng.Assert; -import org.testng.annotations.Test; - -/* - * @bug 6505031 - * @summary Test transformer parses keys and their values coming from different xml documents. - */ -public class Bug6505031 { - - private String getResource(String s) { - return getClass().getResource(s).toString(); - - } - - @Test - public void test() { - Map params = new HashMap(); - - params.put("config", getResource("config.xml")); - params.put("mapsFile", getResource("maps.xml")); - generate(getResource("template.xml"), getResource("transform.xsl"), params); - } - - private void generate(String in, String xsl, Map params) { - try { - Transformer transformer = getTransformer(xsl); - - for (Iterator i = params.entrySet().iterator(); i.hasNext();) { - Map.Entry entry = (Map.Entry) i.next(); - - transformer.setParameter((String) entry.getKey(), entry.getValue()); - } - transform(in, transformer); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - - private Transformer getTransformer(String transform) throws Exception { - TransformerFactory tfactory = TransformerFactory.newInstance(); - - try { - // tfactory.setAttribute("generate-translet", Boolean.TRUE); - } catch (Exception e) { - // Ignore - } - - Transformer transformer = tfactory.newTransformer(new StreamSource(transform)); - return (transformer); - } - - private void transform(String in, Transformer transformer) throws Exception { - StringWriter sw = new StringWriter(); - transformer.transform(new StreamSource(in), new StreamResult(sw)); - String s = sw.toString(); - Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); - } - -} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,1 @@ +................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,5 @@ + + + + . + diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,83 @@ +0fto-erech 200amos-batch 00000000X/ +1FB01 20150709 EWF 2016021207USD 0000,9302122026623 ////////91284422 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007366,71//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D8OOoOOooooOoooooO////15/07 P0480715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40090597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150630 EWF 2016021206USD 0000,9302122026624 ////////1500006837 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000003844,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////b3oooooooooooooooo////15/07 R1683315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40127254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207CHF 0001,0000022026625 ////////94043801 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000438,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0CooOooooooooooOOo////15/07 P0472115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30092874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150702 EWF 2016021207EUR 0001,0468822026626 ////////TL152062 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000661,30//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3coooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150617 EWF 2016021206EUR 0001,0468822026627 ////////TKL100216 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000699,92//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////55oooooOoOooooOoOo////15/07 L0032815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2014686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150702 EWF 2016021207EUR 0001,0468822026628 ////////TL152063 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001983,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9boooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207EUR 0001,0468822026629 ////////000359084 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002230,76//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////51oOoOoOoOoooooOOO////15/07 R1735915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207CHF 0001,0000022026630 ////////90864081 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001893,20//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////acoooooooooooooooo////15/07 P0470615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026631 ////////123939 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007896,34//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////09oooooooooooooooo////15/07 P0400015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207USD 0000,9302122026633 ////////000358117 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000006810,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////f5oooooooooooooooo////15/07 P0462815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207CHF 0001,0000022026635 ////////M90257500 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000016300,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////C3oOOOooOoOooOOOoo////15/07 R1488615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207USD 0000,9302122026637 ////////M90257457 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000831,90//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////60ooooOooOOOoOoOoo////15/07 P0463815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000055,22//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0463815 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207USD 0000,9302122026638 ////////M90257509 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002218,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////60OoooooOOooooOooo////15/07 P0491115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000055,22//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0491115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207CHF 0001,0000022026639 ////////M90257515 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000005833,20//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////A6OOooOoOoOooOoooo////15/07 R1575215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026642 ////////C/5 335835 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////16OooooOooOOoOoooo////15/07 R1612715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026643 ////////C/5 335833 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////58OOoOOooooOooOOoo////15/07 R1441715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026644 ////////C/5 336036 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6BooooOOoooOooOooo////15/07 R1659015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026645 ////////C/5 335836 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6DoOoooOooOOoOooOo////15/07 R1613415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026646 ////////C/5 336201 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////74ooOoOooooooooOoO////15/07 R1728915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026647 ////////C/5 336035 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////86OoooOOoooOoooOOo////15/07 R1612615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026648 ////////C/5 336034 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////99OOooooooOooOoooo////15/07 R1445115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026649 ////////C/5 335834 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D8OOoooOOOooooOOoo////15/07 R1445315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026650 ////////351732 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000192,80//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4BooOooooOOOoOOOOo////15/07 P0448015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026651 ////////351730 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000057,25//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////69ooOoOooooooooooO////15/07 P0451715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000007,02//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0451715 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026652 ////////351731 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000100,05//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////A9oooooooOoOooOOOo////15/07 P0448015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207EUR 0001,0468822026653 ////////05/91014407 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000225,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////22oooOooooOooOooOO////15/07 R1727915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207EUR 0001,0468822026654 ////////05/91015508 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000225,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////24OooooOOoOooOoOoO////15/07 R1728015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207EUR 0001,0468822026655 ////////05/91015531 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000768,45//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////76oOOOOooOoOooooOO////15/07 W0054415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026656 ////////SI156008034 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000261,79//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////96OooooOoOoooOOOoo////15/07 P0479215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207EUR 0001,0468822026657 ////////05/91015509 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000705,35//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////99ooOoOOoooooOoooo////15/07 R1625015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207EUR 0001,0468822026662 ////////55941607 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000725,60//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4BOoooOOOoOoooooOo////15/07 P0486115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40091085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207CHF 0001,0000022026663 ////////100-120606 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000004229,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0boooooooooooooooo////15/07 P0474115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30094003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000430,56//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0474115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000054,38//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0474115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207CHF 0001,0000022026664 ////////13143106 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000318,65//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6eoooooooooooooooo////15/07 P0468115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30092269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000014,04//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0468115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207EUR 0001,0468822026665 ////////TL152315 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001983,90//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////74oooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150710 EWF 2016021207EUR 0001,0468822026667 ////////11321 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000840,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////caoooooooooooooooo////15/07 P0471915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40129316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150401 EWF 2016021204EUR 0001,0553176278995 ////////76278995 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007833,33//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////15/04 S0026415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VERB05001 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20110209 EWF 2016021202CHF 0001,0000090149059 ////////M90149059 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001077,30//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////11/03 S0080410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20110209 EWF 2016021202USD 0000,9570290149062 ////////90149062 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002185,78//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////11/03 S0125011 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,2438 @@ + + + + 22026623 + + + CRX + CHF + + OPEN + I + V0409 + CAGE1 + 40090597 + + 91284422 + 2015-07-09 + + 2015-07-15 + 2015-07-15 + D8OOoOOooooOoooooOOOOooOoooOoOoo + + 7366.71 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0480715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026624 + + + CRX + CHF + + OPEN + I + V0307 + CAGE2 + 40127254 + + 1500006837 + 2015-06-30 + + 2015-07-16 + 2015-07-16 + b3oooooooooooooooooooooooooooooo + + 3844.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1683315 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-30 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026625 + + + CRX + CHF + + CLOSED + I + V0568 + 30092874 + + 94043801 + 2015-07-09 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 0CooOooooooooooOOoooOooOoOOoooOo + + 438.5 + 190.008 + 0.0 + 0.0 + + 4V + 32.48 + + + + P + P0472115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026626 + + + CRX + CHF + + OPEN + I + V0316 + CAGE3 + 40099751 + + TL152062 + 2015-07-02 + + 2015-07-16 + 2015-07-16 + 3coooooooooooooooooooooooooooooo + + 661.3 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-01 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026627 + + + CRX + CHF + + OPEN + I + V0440 + 2014686 + + TKL100216 + 2015-06-17 + + 2015-07-16 + 2015-07-16 + 55oooooOoOooooOoOoOOOoOOOoooOOoo + + 699.92 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + L + L0032815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-17 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026628 + + + CRX + CHF + + OPEN + I + V0316 + CAGE4 + 40099751 + + TL152063 + 2015-07-02 + + 2015-07-16 + 2015-07-16 + 9boooooooooooooooooooooooooooooo + + 1983.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-01 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026629 + + + CRX + CHF + + OPEN + I + V0506 + 40128088 + + 000359084 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + 51oOoOoOoOoooooOOOoOooooOOoooOoO + + 2230.76 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1735915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026630 + + + CRX + CHF + + OPEN + I + V0497 + 30090668 + + 90864081 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + acoooooooooooooooooooooooooooooo + + 1893.2 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0470615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026631 + + + CRX + CHF + + OPEN + I + V0512 + 40128846 + + 123939 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 09oooooooooooooooooooooooooooooo + + 7896.34 + 0.0 + 0.0 + 0.0 + + TAX + 0.0 + + + + P + P0400015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026633 + + + CRX + CHF + + CLOSED + I + V0202 + 40128088 + + 000358117 + 2015-07-07 + 2015-07-16 + 2015-07-16 + 2015-07-16 + f5oooooooooooooooooooooooooooooo + + 6810.0 + 3187.08 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0462815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026635 + + + CRX + CHF + + OPEN + I + V0011 + 30124373 + + M90257500 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + C3oOOOooOoOooOOOoooOOOoOOoooOoOO + + 16300.5 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1488615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026637 + + + CRX + CHF + + CLOSED + I + V0139 + 30124373 + + M90257457 + 2015-07-13 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 60ooooOooOOOoOoOoooooooOOOOoooOO + + 831.9 + 334.1052 + 118.0 + 0.0 + + V0 + 0.0 + + + + P + P0463815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 55.224 + 55.224 + + V0 + V0 + 0.0 + + + D + + + + 22026638 + + + CRX + CHF + + CLOSED + I + V0139 + 30124373 + + M90257509 + 2015-07-13 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 60OoooooOOooooOoooooooooOOooOOOO + + 2218.0 + 982.8 + 118.0 + 0.0 + + V0 + 0.0 + + + + P + P0491115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 55.224 + 55.224 + + V0 + V0 + 0.0 + + + D + + + + 22026639 + + + CRX + CHF + + OPEN + I + V0162 + 30124373 + + M90257515 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + A6OOooOoOoOooOoooooooooOooooOOoo + + 5833.2 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1575215 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026642 + + + CRX + CHF + + OPEN + I + V0400 + CAGE5 + 40126141 + + C/5 335835 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 16OooooOooOOoOooooOoooooooooooOO + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1612715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026643 + + + CRX + CHF + + OPEN + I + V0400 + CAGE6 + 40126141 + + C/5 335833 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 58OOoOOooooOooOOooOoooOooooOOoOo + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1441715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026644 + + + CRX + CHF + + OPEN + I + V0400 + CAGE7 + 40126141 + + C/5 336036 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 6BooooOOoooOooOooooOooooOoOOoooo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1659015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026645 + + + CRX + CHF + + OPEN + I + V0400 + CAGE8 + 40126141 + + C/5 335836 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 6DoOoooOooOOoOooOoOoOoOOOoOoOooo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1613415 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026646 + + + CRX + CHF + + OPEN + I + V0400 + CAGE9 + 40126141 + + C/5 336201 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 74ooOoOooooooooOoOOOoOoOooOoooOO + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1728915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026647 + + + CRX + CHF + + OPEN + I + V0400 + CAGEA + 40126141 + + C/5 336035 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 86OoooOOoooOoooOOoOooOoooOOoOoOo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1612615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026648 + + + CRX + CHF + + OPEN + I + V0400 + CAGEB + 40126141 + + C/5 336034 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 99OOooooooOooOooooOooOooOoOOoOoo + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1445115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026649 + + + CRX + CHF + + OPEN + I + V0400 + CAGEC + 40126141 + + C/5 335834 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + D8OOoooOOOooooOOoooOOoOoooOoOOOO + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1445315 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026650 + + + CRX + CHF + + OPEN + I + V0429 + 30090682 + + 351732 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 4BooOooooOOOoOOOOooo + + 192.8 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0448015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026651 + + + CRX + CHF + + CLOSED + I + V0429 + 30090682 + + 351730 + 2015-07-06 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 69ooOoOooooooooooOoOooOOOOoooOoO + + 57.25 + 17.784 + 15.0 + 0.0 + + 4V + 4.24 + + + + P + P0451715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 7.02 + 7.02 + + 4V + 4V + 0.5616 + + + D + + + + 22026652 + + + CRX + CHF + + OPEN + I + V0429 + 30090682 + + 351731 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + A9oooooooOoOooOOOoOO + + 100.05 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0448015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026653 + + + CRX + CHF + + OPEN + I + V0028 + CAGED + 40096899 + + 05/91014407 + 2015-07-07 + + 2015-07-16 + 2015-07-16 + 22oooOooooOooOooOOoOooOoooooOooO + + 225.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1727915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026654 + + + CRX + CHF + + OPEN + I + V0028 + CAGEE + 40096899 + + 05/91015508 + 2015-07-07 + + 2015-07-16 + 2015-07-16 + 24OooooOOoOooOoOoOoOoooOOoOOooOo + + 225.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1728015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026655 + + + CRX + CHF + + CLOSED + I + V0028 + CAGEF + 40096899 + + 05/91015531 + 2015-07-01 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 76oOOOOooOoOooooOOoOoOOooOooOoOO + + 768.45 + 359.6346 + 0.0 + 0.0 + + V0 + 0.0 + + + + W + W0054415 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026656 + + + CRX + CHF + + OPEN + I + V0651 + 40126601 + + SI156008034 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 96OooooOoOoooOOOoooOOoooOoOOOOoO + + 261.79 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0479215 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026657 + + + CRX + CHF + + CLOSED + I + V0028 + CAGEG + 40096899 + + 05/91015509 + 2015-07-09 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 99ooOoOOoooooOooooOOOOoooOOoOOoO + + 705.35 + 330.1038 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1625015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026662 + + + CRX + CHF + + OPEN + I + V0495 + CAGEH + 40091085 + + 55941607 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + 4BOoooOOOoOoooooOoOOooOooooOoOoo + + 725.6 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0486115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026663 + + + CRX + CHF + + CLOSED + I + V0604 + 30094003 + + 100-120606 + 2015-07-08 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 0boooooooooooooooooooooooooooooo + + 4229.5 + 1347.84 + 1036.2 + 0.0 + + TAX + 313.3 + + + + P + P0474115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 430.56 + 430.56 + + 4V + 4V + 34.4448 + + + D + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 54.3816 + 54.3816 + + 4V + 4V + 4.3524 + + + D + + + + 22026664 + + + CRX + CHF + + CLOSED + I + V0634 + 30092269 + + 13143106 + 2015-07-07 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 6eoooooooooooooooooooooooooooooo + + 318.65 + 124.0434 + 30.0 + 0.0 + + 4V + 23.599999999999998 + + + + P + P0468115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 14.04 + 14.04 + + 4V + 4V + 1.1232 + + + D + + + + 22026665 + + + CRX + CHF + + OPEN + I + V0316 + CAGEI + 40099751 + + TL152315 + 2015-07-09 + + 2015-07-16 + 2015-07-16 + 74oooooooooooooooooooooooooooooo + + 1983.9 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026667 + + + CRX + CHF + + OPEN + I + V0642 + 40129316 + + 11321 + 2015-07-10 + + 2015-07-16 + 2015-07-16 + caoooooooooooooooooooooooooooooo + + 840.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0471915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-09 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 76278995 + + + CRX + CHF + + CLOSED + I + V0166 + CAGEJ + VERB05001 + + 76278995 + 2015-04-01 + 2015-04-17 + 2015-04-17 + 2015-04-17 + + 7833.33 + 3394.4414 + 0.0 + 0.0 + + V0 + 580.25 + + + + S + S0026415 + + + 2016-02-12 + + Y + + + + + + + + + + 2015-04-01 + 0 + Y + + + 04 + 2015 + + + EUR + CHF + 1.05531 + + + + + 90149059 + + + CRX + CHF + + CLOSED + I + V0016 + 30124373 + + M90149059 + 2011-02-09 + 2011-02-18 + 2011-02-18 + 2011-02-18 + + 1077.3 + 504.1764 + 0.0 + 0.0 + + TAX + 0.0 + + + + S + S0080410 + + + 2016-02-12 + + N + + + + 5 + + + + + + 2011-02-09 + 0 + N + + + 03 + 2011 + + + CHF + CHF + 1.0 + + + + + 90149062 + + + CRX + CHF + + CLOSED + I + V0016 + 30124374 + + 90149062 + 2011-02-09 + 2011-02-21 + 2011-02-21 + 2011-02-21 + + 2185.78 + 1022.945 + 0.0 + 0.0 + + TAX + 0.0 + + + + S + S0125011 + + + 2016-02-12 + + N + + + + 6 + + + + + + 2011-02-09 + 0 + N + + + 03 + 2011 + + + USD + CHF + 0.95702 + + + + + diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,1935 @@ + + + + + + + + + +0 +fto-erech +200 +amos-batch +00000000 +X + + +FB01 +TP +EWF + + +566 +950 + + +2w + +V0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + + + + + + + + + + + + + + + +KA +EA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/ + + + +/ +/ +/ +/ +/ +X +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + +2 +BBSEG + +31 +21 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + + +/ +/ + + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +INVALID ALIGN + + + + \ No newline at end of file diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java --- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,13 @@ package transform; +import com.sun.org.apache.xml.internal.serialize.OutputFormat; +import com.sun.org.apache.xml.internal.serialize.XMLSerializer; + +import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; @@ -55,56 +61,67 @@ import org.xml.sax.helpers.AttributesImpl; /* - * @summary Test Transformer. + * @summary Transformer Tests + * @bug 6272879 6305029 6505031 8150704 */ public class TransformerTest { - - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - private static final String XML_DOCUMENT = "" + ""; + private Transformer createTransformer() throws TransformerException { + return TransformerFactory.newInstance().newTransformer(); + } - //Test for JDK-6305029 - @Test - public final void testTransform() throws TransformerException { - - // test SAXSource - SAXSource saxSource = new SAXSource(new MyXMLReader(), new InputSource()); + private Transformer createTransformerFromInputstream(InputStream xslStream) throws TransformerException { + return TransformerFactory.newInstance().newTransformer(new StreamSource(xslStream)); + } - StringWriter builder = new StringWriter(); - TransformerFactory.newInstance().newTransformer().transform(saxSource, new StreamResult(builder)); - - AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, builder.toString()); + private Transformer createTransformerFromResource(String xslResource) throws TransformerException { + return TransformerFactory.newInstance().newTransformer(new StreamSource(getClass().getResource(xslResource).toString())); + } - // test StreamSource - StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); + private Document transformInputStreamToDocument(Transformer transformer, InputStream sourceStream) throws TransformerException { + DOMResult response = new DOMResult(); + transformer.transform(new StreamSource(sourceStream), response); + return (Document)response.getNode(); + } - StringWriter streamResult = new StringWriter(); - - TransformerFactory.newInstance().newTransformer().transform(streamSource, new StreamResult(streamResult)); - - AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, streamResult.toString()); + private StringWriter transformResourceToStringWriter(Transformer transformer, String xmlResource) throws TransformerException { + StringWriter sw = new StringWriter(); + transformer.transform(new StreamSource(getClass().getResource(xmlResource).toString()), new StreamResult(sw)); + return sw; } - private static class MyXMLReader implements XMLReader { - - private static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; - - private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; - - private boolean namespaces = true; + /** + * Reads the contents of the given file into a string. + * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one. + * + * @param f + * The file to read + * @return The content of the file as a string, with line terminators as \"n" + * for all platforms + * @throws IOException + * If there was an error reading + */ + private String getFileContentAsString(File f) throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(f))) { + String line; + StringBuilder sb = new StringBuilder(); + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + return sb.toString(); + } + } + private class XMLReaderFor6305029 implements XMLReader { + private static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; + private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; + private boolean namespaces = true; private boolean namespacePrefixes = false; - private EntityResolver resolver; - private DTDHandler dtdHandler; - private ContentHandler contentHandler; - private ErrorHandler errorHandler; public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { - if (name.equals(NAMESPACES)) { return namespaces; } else if (name.equals(NAMESPACE_PREFIXES)) { @@ -115,7 +132,6 @@ } public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { - if (name.equals(NAMESPACES)) { namespaces = value; } else if (name.equals(NAMESPACE_PREFIXES)) { @@ -165,12 +181,10 @@ } public void parse(final InputSource input) throws IOException, SAXException { - parse(); } public void parse(final String systemId) throws IOException, SAXException { - parse(); } @@ -190,30 +204,50 @@ } } + /* + * @bug 6272879 + * @summary Test for JDK-6272879 + */ @Test - public final void testCR6272879() { + public final void testBug6272879() throws IOException, TransformerException { + final String LINE_SEPARATOR = System.getProperty("line.separator"); - final String xsl = "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + " " - + LINE_SEPARATOR + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + ""; + final String xsl = + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + ""; - final String sourceXml = "" - + LINE_SEPARATOR + final String sourceXml = + "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "]>" + // LINE_SEPARATOR + - + "" + LINE_SEPARATOR + " " + LINE_SEPARATOR + " Valeur 1" + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + " Valeur 2" + LINE_SEPARATOR - + " " + LINE_SEPARATOR + ""; + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " Valeur 1" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " Valeur 2" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + ""; Document document; Node node; @@ -230,9 +264,12 @@ System.out.println("Source file after transformation:"); System.out.println("================================="); - document = getTransformation(xsl, sourceXml); - - System.out.println(document); + document = transformInputStreamToDocument(createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), + new ByteArrayInputStream(sourceXml.getBytes())); + OutputFormat format = new OutputFormat(); + format.setIndenting(true); + new XMLSerializer(System.out, format).serialize(document); + System.out.println(); System.out.println("Node content for element valeur2:"); System.out.println("================================="); @@ -248,25 +285,60 @@ } } - private static Document getTransformation(final String xsl, final String sourceXml) { + /* + * @bug 6305029 + * @summary Test for JDK-6305029 + */ + @Test + public final void testBug6305029() throws TransformerException { + final String XML_DOCUMENT = "" + ""; - Transformer transformer; - DOMResult reponse; - Document document = null; + // test SAXSource + SAXSource saxSource = new SAXSource(new XMLReaderFor6305029(), new InputSource()); + StringWriter resultWriter = new StringWriter(); + createTransformer().transform(saxSource, new StreamResult(resultWriter)); + AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, resultWriter.toString()); - try { - InputStream in = new ByteArrayInputStream(xsl.getBytes()); - transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(in)); + // test StreamSource + StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); + resultWriter = new StringWriter(); + createTransformer().transform(streamSource, new StreamResult(resultWriter)); + AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, resultWriter.toString()); + } - reponse = new DOMResult(); - transformer.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), reponse); - document = (Document) reponse.getNode(); - } catch (Exception e) { - String msg = "Exception in getTransformation: " + e; - System.err.println(msg); - Assert.fail(msg); - } + /* + * @bug 6505031 + * @summary Test transformer parses keys and their values coming from different xml documents. + */ + @Test + public final void testBug6505031() throws TransformerException { + Transformer transformer = createTransformerFromResource("transform.xsl"); + transformer.setParameter("config", getClass().getResource("config.xml").toString()); + transformer.setParameter("mapsFile", getClass().getResource("maps.xml").toString()); + String s = transformResourceToStringWriter(transformer, "template.xml").toString(); + Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); + } - return (document); + /* + * @bug 8150704 + * @summary Test that XSL transformation with lots of temporary result trees will not run out of DTM IDs. + */ + @Test + public final void testBug8150704() throws TransformerException, IOException { + System.out.println("Testing transformation of Bug8150704-1.xml..."); + Transformer transformer = createTransformerFromResource("Bug8150704-1.xsl"); + StringWriter result = transformResourceToStringWriter(transformer, "Bug8150704-1.xml"); + String resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); + String reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-1.ref").getPath())); + Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-1.xml does not match reference"); + System.out.println("Passed."); + + System.out.println("Testing transformation of Bug8150704-2.xml..."); + transformer = createTransformerFromResource("Bug8150704-2.xsl"); + result = transformResourceToStringWriter(transformer, "Bug8150704-2.xml"); + resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); + reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-2.ref").getPath())); + Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference"); + System.out.println("Passed."); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jaxws/.hgtags --- a/jaxws/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/jaxws/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -354,3 +354,4 @@ c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106 fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 513eb2e432f64f85992442da9acdfcfbb36555d9 jdk-9+108 +4b0697e4ce8940b1599af274ff02296d7f59aded jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/.hgtags --- a/jdk/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -352,3 +352,4 @@ 8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107 42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108 1c7bad0798900fe58f4db01ae7ffdc84f5baee8c jdk-9+109 +9417e1bcded6af5532c3b26235437ab227758877 jdk-9+110 diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/make/mapfiles/libawt/mapfile-mawt-vers --- a/jdk/make/mapfiles/libawt/mapfile-mawt-vers Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/make/mapfiles/libawt/mapfile-mawt-vers Mon Mar 21 11:21:08 2016 +0100 @@ -200,6 +200,7 @@ Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/make/mapfiles/libawt_headless/mapfile-vers --- a/jdk/make/mapfiles/libawt_headless/mapfile-vers Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/make/mapfiles/libawt_headless/mapfile-vers Mon Mar 21 11:21:08 2016 +0100 @@ -73,6 +73,7 @@ Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/make/mapfiles/libawt_xawt/mapfile-vers --- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers Mon Mar 21 11:21:08 2016 +0100 @@ -439,6 +439,7 @@ Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Mon Mar 21 11:21:08 2016 +0100 @@ -99,13 +99,16 @@ *

* As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} * of this lookup object will be {@link java.lang.Object}. + * Consequently, the lookup context of this lookup object will be the bootstrap + * class loader, which means it cannot find user classes. * *

* Discussion: * The lookup class can be changed to any other class {@code C} using an expression of the form * {@link Lookup#in publicLookup().in(C.class)}. * Since all classes have equal access to public names, - * such a change would confer no new access rights. + * such a change would confer no new access rights, + * but may change the lookup context by virtue of changing the class loader. * A public lookup object is always subject to * security manager checks. * Also, it cannot access @@ -641,6 +644,11 @@ * then no members, not even public members, will be accessible. * (In all other cases, public members will continue to be accessible.) * + *

+ * The resulting lookup's capabilities for loading classes + * (used during {@link #findClass} invocations) + * are determined by the lookup class' loader, + * which may change due to this operation. * * @param requestedLookupClass the desired lookup class for the new lookup object * @return a lookup object which reports the desired lookup class @@ -939,13 +947,17 @@ /** * Looks up a class by name from the lookup context defined by this {@code Lookup} object. The static * initializer of the class is not run. + *

+ * The lookup context here is determined by the {@linkplain #lookupClass() lookup class}, its class + * loader, and the {@linkplain #lookupModes() lookup modes}. In particular, the method first attempts to + * load the requested class, and then determines whether the class is accessible to this lookup object. * * @param targetName the fully qualified name of the class to be looked up. * @return the requested class. * @exception SecurityException if a security manager is present and it * refuses access * @throws LinkageError if the linkage fails - * @throws ClassNotFoundException if the class does not exist. + * @throws ClassNotFoundException if the class cannot be loaded by the lookup class' loader. * @throws IllegalAccessException if the class is not accessible, using the allowed access * modes. * @exception SecurityException if a security manager is present and it @@ -960,6 +972,9 @@ /** * Determines if a class can be accessed from the lookup context defined by this {@code Lookup} object. The * static initializer of the class is not run. + *

+ * The lookup context here is determined by the {@linkplain #lookupClass() lookup class} and the + * {@linkplain #lookupModes() lookup modes}. * * @param targetClass the class to be access-checked * diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Mon Mar 21 11:21:08 2016 +0100 @@ -91,7 +91,7 @@ * can call with more than 255 slots. This limits the number of static and * dynamic arguments one can pass to bootstrap method. Since there are potential * concatenation strategies that use {@code MethodHandle} combinators, we need - * to reserve a few empty slots on the parameter lists to to capture the + * to reserve a few empty slots on the parameter lists to capture the * temporal results. This is why bootstrap methods in this factory do not accept * more than 200 argument slots. Users requiring more than 200 argument slots in * concatenation are expected to split the large concatenation in smaller diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Mon Mar 21 11:21:08 2016 +0100 @@ -619,6 +619,9 @@ * The returned formatter has a chronology of ISO set to ensure dates in * other calendar systems are correctly converted. * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style. + * The {@code FULL} and {@code LONG} styles typically require a time-zone. + * When formatting using these styles, a {@code ZoneId} must be available, + * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}. * * @param timeStyle the formatter style to obtain, not null * @return the time formatter, not null @@ -647,6 +650,9 @@ * The returned formatter has a chronology of ISO set to ensure dates in * other calendar systems are correctly converted. * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style. + * The {@code FULL} and {@code LONG} styles typically require a time-zone. + * When formatting using these styles, a {@code ZoneId} must be available, + * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}. * * @param dateTimeStyle the formatter style to obtain, not null * @return the date-time formatter, not null @@ -675,6 +681,9 @@ * The returned formatter has a chronology of ISO set to ensure dates in * other calendar systems are correctly converted. * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style. + * The {@code FULL} and {@code LONG} styles typically require a time-zone. + * When formatting using these styles, a {@code ZoneId} must be available, + * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}. * * @param dateStyle the date formatter style to obtain, not null * @param timeStyle the time formatter style to obtain, not null diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Mon Mar 21 11:21:08 2016 +0100 @@ -1256,6 +1256,9 @@ * During formatting, the chronology is obtained from the temporal object * being formatted, which may have been overridden by * {@link DateTimeFormatter#withChronology(Chronology)}. + * The {@code FULL} and {@code LONG} styles typically require a time-zone. + * When formatting using these styles, a {@code ZoneId} must be available, + * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}. *

* During parsing, if a chronology has already been parsed, then it is used. * Otherwise the default from {@code DateTimeFormatter.withChronology(Chronology)} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java --- a/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java Mon Mar 21 11:21:08 2016 +0100 @@ -218,6 +218,13 @@ } return query.queryFrom(this); } + + @Override + public String toString() { + return temporal + + (effectiveChrono != null ? " with chronology " + effectiveChrono : "") + + (effectiveZone != null ? " with zone " + effectiveZone : ""); + } }; } @@ -279,7 +286,8 @@ R getValue(TemporalQuery query) { R result = temporal.query(query); if (result == null && optional == 0) { - throw new DateTimeException("Unable to extract value: " + temporal.getClass()); + throw new DateTimeException("Unable to extract " + + query + " from temporal " + temporal); } return result; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/time/temporal/TemporalQueries.java --- a/jdk/src/java.base/share/classes/java/time/temporal/TemporalQueries.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/time/temporal/TemporalQueries.java Mon Mar 21 11:21:08 2016 +0100 @@ -341,58 +341,118 @@ /** * A strict query for the {@code ZoneId}. */ - static final TemporalQuery ZONE_ID = (temporal) -> - temporal.query(TemporalQueries.ZONE_ID); + static final TemporalQuery ZONE_ID = new TemporalQuery<>() { + @Override + public ZoneId queryFrom(TemporalAccessor temporal) { + return temporal.query(TemporalQueries.ZONE_ID); + } + + @Override + public String toString() { + return "ZoneId"; + } + }; /** * A query for the {@code Chronology}. */ - static final TemporalQuery CHRONO = (temporal) -> - temporal.query(TemporalQueries.CHRONO); + static final TemporalQuery CHRONO = new TemporalQuery<>() { + @Override + public Chronology queryFrom(TemporalAccessor temporal) { + return temporal.query(TemporalQueries.CHRONO); + } + + @Override + public String toString() { + return "Chronology"; + } + }; + /** * A query for the smallest supported unit. */ - static final TemporalQuery PRECISION = (temporal) -> - temporal.query(TemporalQueries.PRECISION); + static final TemporalQuery PRECISION = new TemporalQuery<>() { + @Override + public TemporalUnit queryFrom(TemporalAccessor temporal) { + return temporal.query(TemporalQueries.PRECISION); + } + + @Override + public String toString() { + return "Precision"; + } + }; //----------------------------------------------------------------------- /** * A query for {@code ZoneOffset} returning null if not found. */ - static final TemporalQuery OFFSET = (temporal) -> { - if (temporal.isSupported(OFFSET_SECONDS)) { - return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS)); + static final TemporalQuery OFFSET = new TemporalQuery<>() { + @Override + public ZoneOffset queryFrom(TemporalAccessor temporal) { + if (temporal.isSupported(OFFSET_SECONDS)) { + return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS)); + } + return null; } - return null; + + @Override + public String toString() { + return "ZoneOffset"; + } }; /** * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}. */ - static final TemporalQuery ZONE = (temporal) -> { - ZoneId zone = temporal.query(ZONE_ID); - return (zone != null ? zone : temporal.query(OFFSET)); + static final TemporalQuery ZONE = new TemporalQuery<>() { + @Override + public ZoneId queryFrom(TemporalAccessor temporal) { + ZoneId zone = temporal.query(ZONE_ID); + return (zone != null ? zone : temporal.query(OFFSET)); + } + + @Override + public String toString() { + return "Zone"; + } }; /** * A query for {@code LocalDate} returning null if not found. */ - static final TemporalQuery LOCAL_DATE = (temporal) -> { - if (temporal.isSupported(EPOCH_DAY)) { - return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY)); + static final TemporalQuery LOCAL_DATE = new TemporalQuery<>() { + @Override + public LocalDate queryFrom(TemporalAccessor temporal) { + if (temporal.isSupported(EPOCH_DAY)) { + return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY)); + } + return null; } - return null; + + @Override + public String toString() { + return "LocalDate"; + } }; /** * A query for {@code LocalTime} returning null if not found. */ - static final TemporalQuery LOCAL_TIME = (temporal) -> { - if (temporal.isSupported(NANO_OF_DAY)) { - return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY)); + static final TemporalQuery LOCAL_TIME = new TemporalQuery<>() { + @Override + public LocalTime queryFrom(TemporalAccessor temporal) { + if (temporal.isSupported(NANO_OF_DAY)) { + return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY)); + } + return null; } - return null; + + @Override + public String toString() { + return "LocalTime"; + } }; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/util/EnumMap.java --- a/jdk/src/java.base/share/classes/java/util/EnumMap.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/EnumMap.java Mon Mar 21 11:21:08 2016 +0100 @@ -718,7 +718,7 @@ } /** - * Returns a shallow copy of this enum map. (The values themselves + * Returns a shallow copy of this enum map. The values themselves * are not cloned. * * @return a shallow copy of this enum map diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/java/util/stream/PipelineHelper.java --- a/jdk/src/java.base/share/classes/java/util/stream/PipelineHelper.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/stream/PipelineHelper.java Mon Mar 21 11:21:08 2016 +0100 @@ -98,7 +98,7 @@ * @implSpec * The implementation behaves as if: *

{@code
-     *     intoWrapped(wrapSink(sink), spliterator);
+     *     copyInto(wrapSink(sink), spliterator);
      * }
* * @param sink the {@code Sink} to receive the results diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java --- a/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java Mon Mar 21 11:21:08 2016 +0100 @@ -106,10 +106,28 @@ return decExponentRounded - 1; } + /** + * Returns the mantissa as a {@code char[]}. Note that the returned value + * is a reference to the internal {@code char[]} containing the mantissa, + * therefore code invoking this method should not pass the return value to + * external code but should in that case make a copy. + * + * @return a reference to the internal {@code char[]} representing the + * mantissa. + */ public char[] getMantissa(){ return mantissa; } + /** + * Returns the exponent as a {@code char[]}. Note that the returned value + * is a reference to the internal {@code char[]} containing the exponent, + * therefore code invoking this method should not pass the return value to + * external code but should in that case make a copy. + * + * @return a reference to the internal {@code char[]} representing the + * exponent. + */ public char[] getExponent(){ return exponent; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java Mon Mar 21 11:21:08 2016 +0100 @@ -195,7 +195,7 @@ public ClassReader(final byte[] b, final int off, final int len) { this.b = b; // checks the class version - if (readShort(off + 6) > Opcodes.V1_8) { + if (readShort(off + 6) > Opcodes.V1_9) { throw new IllegalArgumentException(); } // parses the constant pool @@ -1199,7 +1199,14 @@ if (labels[label] == null) { readLabel(label, labels).status |= Label.DEBUG; } - labels[label].line = readUnsignedShort(v + 12); + Label l = labels[label]; + while (l.line > 0) { + if (l.next == null) { + l.next = new Label(); + } + l = l.next; + } + l.line = readUnsignedShort(v + 12); v += 4; } } @@ -1314,9 +1321,15 @@ // visits the label and line number for this offset, if any Label l = labels[offset]; if (l != null) { + Label next = l.next; + l.next = null; mv.visitLabel(l); if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { mv.visitLineNumber(l.line, l); + while (next != null) { + mv.visitLineNumber(next.line, l); + next = next.next; + } } } @@ -1857,8 +1870,7 @@ v += 2; break; case 'B': // pointer to CONSTANT_Byte - av.visit(name, - (byte) readInt(items[readUnsignedShort(v)])); + av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'Z': // pointer to CONSTANT_Boolean @@ -1868,13 +1880,11 @@ v += 2; break; case 'S': // pointer to CONSTANT_Short - av.visit(name, - (short) readInt(items[readUnsignedShort(v)])); + av.visit(name, (short) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'C': // pointer to CONSTANT_Char - av.visit(name, - (char) readInt(items[readUnsignedShort(v)])); + av.visit(name, (char) readInt(items[readUnsignedShort(v)])); v += 2; break; case 's': // pointer to CONSTANT_Utf8 @@ -2515,11 +2525,12 @@ int tag = readByte(index); int[] items = this.items; int cpIndex = items[readUnsignedShort(index + 1)]; + boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; String owner = readClass(cpIndex, buf); cpIndex = items[readUnsignedShort(cpIndex + 2)]; String name = readUTF8(cpIndex, buf); String desc = readUTF8(cpIndex + 2, buf); - return new Handle(tag, owner, name, desc); + return new Handle(tag, owner, name, desc, itf); } } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -1081,7 +1081,7 @@ } } else if (cst instanceof Handle) { Handle h = (Handle) cst; - return newHandleItem(h.tag, h.owner, h.name, h.desc); + return newHandleItem(h.tag, h.owner, h.name, h.desc, h.itf); } else { throw new IllegalArgumentException("value " + cst); } @@ -1216,10 +1216,12 @@ * the name of the field or method. * @param desc * the descriptor of the field or method. + * @param itf + * true if the owner is an interface. * @return a new or an already existing method type reference item. */ Item newHandleItem(final int tag, final String owner, final String name, - final String desc) { + final String desc, final boolean itf) { key4.set(HANDLE_BASE + tag, owner, name, desc); Item result = get(key4); if (result == null) { @@ -1228,8 +1230,7 @@ } else { put112(HANDLE, tag, - newMethod(owner, name, desc, - tag == Opcodes.H_INVOKEINTERFACE)); + newMethod(owner, name, desc, itf)); } result = new Item(index++, key4); put(result); @@ -1259,10 +1260,44 @@ * the descriptor of the field or method. * @return the index of a new or already existing method type reference * item. + * + * @deprecated this method is superseded by + * {@link #newHandle(int, String, String, String, boolean)}. + */ + @Deprecated + public int newHandle(final int tag, final String owner, final String name, + final String desc) { + return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); + } + + /** + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. + * @param itf + * true if the owner is an interface. + * @return the index of a new or already existing method type reference + * item. */ public int newHandle(final int tag, final String owner, final String name, - final String desc) { - return newHandleItem(tag, owner, name, desc).index; + final String desc, final boolean itf) { + return newHandleItem(tag, owner, name, desc, itf).index; } /** @@ -1294,7 +1329,7 @@ int hashCode = bsm.hashCode(); bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, - bsm.desc)); + bsm.desc, bsm.isInterface())); int argsLength = bsmArgs.length; bootstrapMethods.putShort(argsLength); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Frame.java Mon Mar 21 11:21:08 2016 +0100 @@ -192,7 +192,7 @@ private static final int LOCAL = 0x2000000; /** - * Kind of the types that are relative to the stack of an input stack + * Kind of the the types that are relative to the stack of an input stack * map frame. The value of such types is a position relatively to the top of * this stack. */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Handle.java Mon Mar 21 11:21:08 2016 +0100 @@ -93,6 +93,12 @@ */ final String desc; + + /** + * Indicate if the owner is an interface or not. + */ + final boolean itf; + /** * Constructs a new field or method handle. * @@ -113,12 +119,44 @@ * @param desc * the descriptor of the field or method designated by this * handle. + * + * @deprecated this constructor has been superseded + * by {@link #Handle(int, String, String, String, boolean)}. */ + @Deprecated public Handle(int tag, String owner, String name, String desc) { + this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); + } + + /** + * Constructs a new field or method handle. + * + * @param tag + * the kind of field or method designated by this Handle. Must be + * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the class that owns the field or method + * designated by this handle. + * @param name + * the name of the field or method designated by this handle. + * @param desc + * the descriptor of the field or method designated by this + * handle. + * @param itf + * true if the owner is an interface. + */ + public Handle(int tag, String owner, String name, String desc, boolean itf) { this.tag = tag; this.owner = owner; this.name = name; this.desc = desc; + this.itf = itf; } /** @@ -164,6 +202,17 @@ return desc; } + /** + * Returns true if the owner of the field or method designated + * by this handle is an interface. + * + * @return true if the owner of the field or method designated + * by this handle is an interface. + */ + public boolean isInterface() { + return itf; + } + @Override public boolean equals(Object obj) { if (obj == this) { @@ -173,13 +222,13 @@ return false; } Handle h = (Handle) obj; - return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) - && desc.equals(h.desc); + return tag == h.tag && itf == h.itf && owner.equals(h.owner) + && name.equals(h.name) && desc.equals(h.desc); } @Override public int hashCode() { - return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); + return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode(); } /** @@ -187,13 +236,16 @@ * representation is: * *
+     * for a reference to a class:
      * owner '.' name desc ' ' '(' tag ')'
+     * for a reference to an interface:
+     * owner '.' name desc ' ' '(' tag ' ' itf ')'
      * 
* * . As this format is unambiguous, it can be parsed if necessary. */ @Override public String toString() { - return owner + '.' + name + desc + " (" + tag + ')'; + return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')'; } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Label.java Mon Mar 21 11:21:08 2016 +0100 @@ -160,7 +160,11 @@ int status; /** - * The line number corresponding to this label, if known. + * The line number corresponding to this label, if known. If there are + * several lines, each line is stored in a separate label, all linked via + * their next field (these links are created in ClassReader and removed just + * before visitLabel is called, so that this does not impact the rest of the + * code). */ int line; @@ -268,7 +272,8 @@ * The next basic block in the basic block stack. This stack is used in the * main loop of the fix point algorithm used in the second step of the * control flow analysis algorithms. It is also used in - * {@link #visitSubroutine} to avoid using a recursive method. + * {@link #visitSubroutine} to avoid using a recursive method, and in + * ClassReader to temporarily store multiple source lines for a label. * * @see MethodWriter#visitMaxs */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java Mon Mar 21 11:21:08 2016 +0100 @@ -62,15 +62,16 @@ * A visitor to visit a Java method. The methods of this class must be called in * the following order: ( visitParameter )* [ * visitAnnotationDefault ] ( visitAnnotation | - * visitTypeAnnotation | visitAttribute )* [ - * visitCode ( visitFrame | visitXInsn | - * visitLabel | visitInsnAnnotation | - * visitTryCatchBlock | visitTryCatchBlockAnnotation | - * visitLocalVariable | visitLocalVariableAnnotation | - * visitLineNumber )* visitMaxs ] visitEnd. In - * addition, the visitXInsn and visitLabel methods must - * be called in the sequential order of the bytecode instructions of the visited - * code, visitInsnAnnotation must be called after the annotated + * visitParameterAnnotation visitTypeAnnotation | + * visitAttribute )* [ visitCode ( visitFrame | + * visitXInsn | visitLabel | + * visitInsnAnnotation | visitTryCatchBlock | + * visitTryCatchAnnotation | visitLocalVariable | + * visitLocalVariableAnnotation | visitLineNumber )* + * visitMaxs ] visitEnd. In addition, the + * visitXInsn and visitLabel methods must be called in + * the sequential order of the bytecode instructions of the visited code, + * visitInsnAnnotation must be called after the annotated * instruction, visitTryCatchBlock must be called before the * labels passed as arguments have been visited, * visitTryCatchBlockAnnotation must be called after the diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -2061,7 +2061,7 @@ } int size = 8; if (code.length > 0) { - if (code.length > 65536) { + if (code.length > 65535) { throw new RuntimeException("Method code too large!"); } cw.newUTF8("Code"); @@ -2735,11 +2735,13 @@ l = l.successor; } // Update the offsets in the uninitialized types - for (i = 0; i < cw.typeTable.length; ++i) { - Item item = cw.typeTable[i]; - if (item != null && item.type == ClassWriter.TYPE_UNINIT) { - item.intVal = getNewOffset(allIndexes, allSizes, 0, - item.intVal); + if (cw.typeTable != null) { + for (i = 0; i < cw.typeTable.length; ++i) { + Item item = cw.typeTable[i]; + if (item != null && item.type == ClassWriter.TYPE_UNINIT) { + item.intVal = getNewOffset(allIndexes, allSizes, 0, + item.intVal); + } } } // The stack map frames are not serialized yet, so we don't need diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java Mon Mar 21 11:21:08 2016 +0100 @@ -87,6 +87,7 @@ int V1_6 = 0 << 16 | 50; int V1_7 = 0 << 16 | 51; int V1_8 = 0 << 16 | 52; + int V1_9 = 0 << 16 | 53; // access flags diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java Mon Mar 21 11:21:08 2016 +0100 @@ -654,7 +654,7 @@ * @return the descriptor corresponding to this Java type. */ public String getDescriptor() { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); getDescriptor(buf); return buf.toString(); } @@ -672,7 +672,7 @@ */ public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append('('); for (int i = 0; i < argumentTypes.length; ++i) { argumentTypes[i].getDescriptor(buf); @@ -689,7 +689,7 @@ * @param buf * the string buffer to which the descriptor must be appended. */ - private void getDescriptor(final StringBuffer buf) { + private void getDescriptor(final StringBuilder buf) { if (this.buf == null) { // descriptor is in byte 3 of 'off' for primitive types (buf == // null) @@ -729,7 +729,7 @@ * @return the descriptor corresponding to the given class. */ public static String getDescriptor(final Class c) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); getDescriptor(buf, c); return buf.toString(); } @@ -743,7 +743,7 @@ */ public static String getConstructorDescriptor(final Constructor c) { Class[] parameters = c.getParameterTypes(); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append('('); for (int i = 0; i < parameters.length; ++i) { getDescriptor(buf, parameters[i]); @@ -760,7 +760,7 @@ */ public static String getMethodDescriptor(final Method m) { Class[] parameters = m.getParameterTypes(); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append('('); for (int i = 0; i < parameters.length; ++i) { getDescriptor(buf, parameters[i]); @@ -778,7 +778,7 @@ * @param c * the class whose descriptor must be computed. */ - private static void getDescriptor(final StringBuffer buf, final Class c) { + private static void getDescriptor(final StringBuilder buf, final Class c) { Class d = c; while (true) { if (d.isPrimitive()) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypePath.java Mon Mar 21 11:21:08 2016 +0100 @@ -71,25 +71,25 @@ * A type path step that steps into the element type of an array type. See * {@link #getStep getStep}. */ - public static final int ARRAY_ELEMENT = 0; + public final static int ARRAY_ELEMENT = 0; /** * A type path step that steps into the nested type of a class type. See * {@link #getStep getStep}. */ - public static final int INNER_TYPE = 1; + public final static int INNER_TYPE = 1; /** * A type path step that steps into the bound of a wildcard type. See * {@link #getStep getStep}. */ - public static final int WILDCARD_BOUND = 2; + public final static int WILDCARD_BOUND = 2; /** * A type path step that steps into a type argument of a generic type. See * {@link #getStep getStep}. */ - public static final int TYPE_ARGUMENT = 3; + public final static int TYPE_ARGUMENT = 3; /** * The byte array where the path is stored, in Java class file format. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/TypeReference.java Mon Mar 21 11:21:08 2016 +0100 @@ -74,133 +74,133 @@ * The sort of type references that target a type parameter of a generic * class. See {@link #getSort getSort}. */ - public static final int CLASS_TYPE_PARAMETER = 0x00; + public final static int CLASS_TYPE_PARAMETER = 0x00; /** * The sort of type references that target a type parameter of a generic * method. See {@link #getSort getSort}. */ - public static final int METHOD_TYPE_PARAMETER = 0x01; + public final static int METHOD_TYPE_PARAMETER = 0x01; /** * The sort of type references that target the super class of a class or one * of the interfaces it implements. See {@link #getSort getSort}. */ - public static final int CLASS_EXTENDS = 0x10; + public final static int CLASS_EXTENDS = 0x10; /** * The sort of type references that target a bound of a type parameter of a * generic class. See {@link #getSort getSort}. */ - public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11; + public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; /** * The sort of type references that target a bound of a type parameter of a * generic method. See {@link #getSort getSort}. */ - public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12; + public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; /** * The sort of type references that target the type of a field. See * {@link #getSort getSort}. */ - public static final int FIELD = 0x13; + public final static int FIELD = 0x13; /** * The sort of type references that target the return type of a method. See * {@link #getSort getSort}. */ - public static final int METHOD_RETURN = 0x14; + public final static int METHOD_RETURN = 0x14; /** * The sort of type references that target the receiver type of a method. * See {@link #getSort getSort}. */ - public static final int METHOD_RECEIVER = 0x15; + public final static int METHOD_RECEIVER = 0x15; /** * The sort of type references that target the type of a formal parameter of * a method. See {@link #getSort getSort}. */ - public static final int METHOD_FORMAL_PARAMETER = 0x16; + public final static int METHOD_FORMAL_PARAMETER = 0x16; /** * The sort of type references that target the type of an exception declared * in the throws clause of a method. See {@link #getSort getSort}. */ - public static final int THROWS = 0x17; + public final static int THROWS = 0x17; /** * The sort of type references that target the type of a local variable in a * method. See {@link #getSort getSort}. */ - public static final int LOCAL_VARIABLE = 0x40; + public final static int LOCAL_VARIABLE = 0x40; /** * The sort of type references that target the type of a resource variable * in a method. See {@link #getSort getSort}. */ - public static final int RESOURCE_VARIABLE = 0x41; + public final static int RESOURCE_VARIABLE = 0x41; /** * The sort of type references that target the type of the exception of a * 'catch' clause in a method. See {@link #getSort getSort}. */ - public static final int EXCEPTION_PARAMETER = 0x42; + public final static int EXCEPTION_PARAMETER = 0x42; /** * The sort of type references that target the type declared in an * 'instanceof' instruction. See {@link #getSort getSort}. */ - public static final int INSTANCEOF = 0x43; + public final static int INSTANCEOF = 0x43; /** * The sort of type references that target the type of the object created by * a 'new' instruction. See {@link #getSort getSort}. */ - public static final int NEW = 0x44; + public final static int NEW = 0x44; /** * The sort of type references that target the receiver type of a * constructor reference. See {@link #getSort getSort}. */ - public static final int CONSTRUCTOR_REFERENCE = 0x45; + public final static int CONSTRUCTOR_REFERENCE = 0x45; /** * The sort of type references that target the receiver type of a method * reference. See {@link #getSort getSort}. */ - public static final int METHOD_REFERENCE = 0x46; + public final static int METHOD_REFERENCE = 0x46; /** * The sort of type references that target the type declared in an explicit * or implicit cast instruction. See {@link #getSort getSort}. */ - public static final int CAST = 0x47; + public final static int CAST = 0x47; /** * The sort of type references that target a type parameter of a generic * constructor in a constructor call. See {@link #getSort getSort}. */ - public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; + public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; /** * The sort of type references that target a type parameter of a generic * method in a method call. See {@link #getSort getSort}. */ - public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; + public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; /** * The sort of type references that target a type parameter of a generic * constructor in a constructor reference. See {@link #getSort getSort}. */ - public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; + public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; /** * The sort of type references that target a type parameter of a generic * method in a method reference. See {@link #getSort getSort}. */ - public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; + public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; /** * The type reference value in Java class file format. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -389,9 +389,9 @@ break; case PUTFIELD: popValue(); + popValue(); if (longOrDouble) { popValue(); - popValue(); } break; // case GETFIELD: @@ -619,7 +619,7 @@ } /** - * Called at the beginning of the method or after super class class call in + * Called at the beginning of the method or after super class call in * the constructor.
*
* diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/AnnotationRemapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,108 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jdk.internal.org.objectweb.asm.commons; + +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +/** + * An {@link AnnotationVisitor} adapter for type remapping. + * + * @author Eugene Kuleshov + */ +public class AnnotationRemapper extends AnnotationVisitor { + + protected final Remapper remapper; + + public AnnotationRemapper(final AnnotationVisitor av, + final Remapper remapper) { + this(Opcodes.ASM5, av, remapper); + } + + protected AnnotationRemapper(final int api, final AnnotationVisitor av, + final Remapper remapper) { + super(api, av); + this.remapper = remapper; + } + + @Override + public void visit(String name, Object value) { + av.visit(name, remapper.mapValue(value)); + } + + @Override + public void visitEnum(String name, String desc, String value) { + av.visitEnum(name, remapper.mapDesc(desc), value); + } + + @Override + public AnnotationVisitor visitAnnotation(String name, String desc) { + AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc)); + return v == null ? null : (v == av ? this : new AnnotationRemapper(v, + remapper)); + } + + @Override + public AnnotationVisitor visitArray(String name) { + AnnotationVisitor v = av.visitArray(name); + return v == null ? null : (v == av ? this : new AnnotationRemapper(v, + remapper)); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/ClassRemapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,161 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jdk.internal.org.objectweb.asm.commons; + +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; + +/** + * A {@link ClassVisitor} for type remapping. + * + * @author Eugene Kuleshov + */ +public class ClassRemapper extends ClassVisitor { + + protected final Remapper remapper; + + protected String className; + + public ClassRemapper(final ClassVisitor cv, final Remapper remapper) { + this(Opcodes.ASM5, cv, remapper); + } + + protected ClassRemapper(final int api, final ClassVisitor cv, + final Remapper remapper) { + super(api, cv); + this.remapper = remapper; + } + + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + this.className = name; + super.visit(version, access, remapper.mapType(name), remapper + .mapSignature(signature, false), remapper.mapType(superName), + interfaces == null ? null : remapper.mapTypes(interfaces)); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), + visible); + return av == null ? null : createAnnotationRemapper(av); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? null : createAnnotationRemapper(av); + } + + @Override + public FieldVisitor visitField(int access, String name, String desc, + String signature, Object value) { + FieldVisitor fv = super.visitField(access, + remapper.mapFieldName(className, name, desc), + remapper.mapDesc(desc), remapper.mapSignature(signature, true), + remapper.mapValue(value)); + return fv == null ? null : createFieldRemapper(fv); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, + String signature, String[] exceptions) { + String newDesc = remapper.mapMethodDesc(desc); + MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName( + className, name, desc), newDesc, remapper.mapSignature( + signature, false), + exceptions == null ? null : remapper.mapTypes(exceptions)); + return mv == null ? null : createMethodRemapper(mv); + } + + @Override + public void visitInnerClass(String name, String outerName, + String innerName, int access) { + // TODO should innerName be changed? + super.visitInnerClass(remapper.mapType(name), outerName == null ? null + : remapper.mapType(outerName), innerName, access); + } + + @Override + public void visitOuterClass(String owner, String name, String desc) { + super.visitOuterClass(remapper.mapType(owner), name == null ? null + : remapper.mapMethodName(owner, name, desc), + desc == null ? null : remapper.mapMethodDesc(desc)); + } + + protected FieldVisitor createFieldRemapper(FieldVisitor fv) { + return new FieldRemapper(fv, remapper); + } + + protected MethodVisitor createMethodRemapper(MethodVisitor mv) { + return new MethodRemapper(mv, remapper); + } + + protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) { + return new AnnotationRemapper(av, remapper); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/FieldRemapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,100 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jdk.internal.org.objectweb.asm.commons; + +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; + +/** + * A {@link FieldVisitor} adapter for type remapping. + * + * @author Eugene Kuleshov + */ +public class FieldRemapper extends FieldVisitor { + + private final Remapper remapper; + + public FieldRemapper(final FieldVisitor fv, final Remapper remapper) { + this(Opcodes.ASM5, fv, remapper); + } + + protected FieldRemapper(final int api, final FieldVisitor fv, + final Remapper remapper) { + super(api, fv); + this.remapper = remapper; + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc), + visible); + return av == null ? null : new AnnotationRemapper(av, remapper); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? null : new AnnotationRemapper(av, remapper); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -73,7 +73,7 @@ */ public class InstructionAdapter extends MethodVisitor { - public static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;"); + public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;"); /** * Creates a new {@link InstructionAdapter}. Subclasses must not use this diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java Mon Mar 21 11:21:08 2016 +0100 @@ -105,11 +105,6 @@ protected int nextLocal; /** - * Indicates if at least one local variable has moved due to remapping. - */ - private boolean changed; - - /** * Creates a new {@link LocalVariablesSorter}. Subclasses must not use * this constructor. Instead, they must use the * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version. @@ -228,11 +223,6 @@ "ClassReader.accept() should be called with EXPAND_FRAMES flag"); } - if (!changed) { // optimization for the case where mapping = identity - mv.visitFrame(type, nLocal, local, nStack, stack); - return; - } - // creates a copy of newLocals Object[] oldLocals = new Object[newLocals.length]; System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length); @@ -328,7 +318,6 @@ int local = newLocalMapping(type); setLocalType(local, type); setFrameLocal(local, t); - changed = true; return local; } @@ -396,9 +385,6 @@ } else { value--; } - if (value != var) { - changed = true; - } return value; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/MethodRemapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,252 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jdk.internal.org.objectweb.asm.commons; + +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.Handle; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.TypePath; + +/** + * A {@link LocalVariablesSorter} for type mapping. + * + * @author Eugene Kuleshov + */ +public class MethodRemapper extends MethodVisitor { + + protected final Remapper remapper; + + public MethodRemapper(final MethodVisitor mv, final Remapper remapper) { + this(Opcodes.ASM5, mv, remapper); + } + + protected MethodRemapper(final int api, final MethodVisitor mv, + final Remapper remapper) { + super(api, mv); + this.remapper = remapper; + } + + @Override + public AnnotationVisitor visitAnnotationDefault() { + AnnotationVisitor av = super.visitAnnotationDefault(); + return av == null ? av : new AnnotationRemapper(av, remapper); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), + visible); + return av == null ? av : new AnnotationRemapper(av, remapper); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? av : new AnnotationRemapper(av, remapper); + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int parameter, + String desc, boolean visible) { + AnnotationVisitor av = super.visitParameterAnnotation(parameter, + remapper.mapDesc(desc), visible); + return av == null ? av : new AnnotationRemapper(av, remapper); + } + + @Override + public void visitFrame(int type, int nLocal, Object[] local, int nStack, + Object[] stack) { + super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack, + remapEntries(nStack, stack)); + } + + private Object[] remapEntries(int n, Object[] entries) { + for (int i = 0; i < n; i++) { + if (entries[i] instanceof String) { + Object[] newEntries = new Object[n]; + if (i > 0) { + System.arraycopy(entries, 0, newEntries, 0, i); + } + do { + Object t = entries[i]; + newEntries[i++] = t instanceof String ? remapper + .mapType((String) t) : t; + } while (i < n); + return newEntries; + } + } + return entries; + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, + String desc) { + super.visitFieldInsn(opcode, remapper.mapType(owner), + remapper.mapFieldName(owner, name, desc), + remapper.mapDesc(desc)); + } + + @Deprecated + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + // Calling super.visitMethodInsn requires to call the correct version + // depending on this.api (otherwise infinite loops can occur). To + // simplify and to make it easier to automatically remove the backward + // compatibility code, we inline the code of the overridden method here. + // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN + // LocalVariableSorter. + if (mv != null) { + mv.visitMethodInsn(opcode, remapper.mapType(owner), + remapper.mapMethodName(owner, name, desc), + remapper.mapMethodDesc(desc), itf); + } + } + + @Override + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, + Object... bsmArgs) { + for (int i = 0; i < bsmArgs.length; i++) { + bsmArgs[i] = remapper.mapValue(bsmArgs[i]); + } + super.visitInvokeDynamicInsn( + remapper.mapInvokeDynamicMethodName(name, desc), + remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm), + bsmArgs); + } + + @Override + public void visitTypeInsn(int opcode, String type) { + super.visitTypeInsn(opcode, remapper.mapType(type)); + } + + @Override + public void visitLdcInsn(Object cst) { + super.visitLdcInsn(remapper.mapValue(cst)); + } + + @Override + public void visitMultiANewArrayInsn(String desc, int dims) { + super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims); + } + + @Override + public AnnotationVisitor visitInsnAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? av : new AnnotationRemapper(av, remapper); + } + + @Override + public void visitTryCatchBlock(Label start, Label end, Label handler, + String type) { + super.visitTryCatchBlock(start, end, handler, type == null ? null + : remapper.mapType(type)); + } + + @Override + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, + TypePath typePath, String desc, boolean visible) { + AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath, + remapper.mapDesc(desc), visible); + return av == null ? av : new AnnotationRemapper(av, remapper); + } + + @Override + public void visitLocalVariable(String name, String desc, String signature, + Label start, Label end, int index) { + super.visitLocalVariable(name, remapper.mapDesc(desc), + remapper.mapSignature(signature, true), start, end, index); + } + + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, + TypePath typePath, Label[] start, Label[] end, int[] index, + String desc, boolean visible) { + AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef, + typePath, start, end, index, remapper.mapDesc(desc), visible); + return av == null ? av : new AnnotationRemapper(av, remapper); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -168,17 +168,19 @@ Handle h = (Handle) value; return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName( h.getOwner(), h.getName(), h.getDesc()), - mapMethodDesc(h.getDesc())); + mapMethodDesc(h.getDesc()), h.isInterface()); } return value; } /** - * + * @param signature + * signature for mapper * @param typeSignature * true if signature is a FieldTypeSignature, such as the * signature parameter of the ClassVisitor.visitField or * MethodVisitor.visitLocalVariable methods + * @return signature rewritten as a string */ public String mapSignature(String signature, boolean typeSignature) { if (signature == null) { @@ -186,7 +188,7 @@ } SignatureReader r = new SignatureReader(signature); SignatureWriter w = new SignatureWriter(); - SignatureVisitor a = createRemappingSignatureAdapter(w); + SignatureVisitor a = createSignatureRemapper(w); if (typeSignature) { r.acceptType(a); } else { @@ -195,9 +197,18 @@ return w.toString(); } + /** + * @deprecated use {@link #createSignatureRemapper} instead. + */ + @Deprecated protected SignatureVisitor createRemappingSignatureAdapter( SignatureVisitor v) { - return new RemappingSignatureAdapter(v, this); + return new SignatureRemapper(v, this); + } + + protected SignatureVisitor createSignatureRemapper( + SignatureVisitor v) { + return createRemappingSignatureAdapter(v); } /** @@ -245,6 +256,10 @@ /** * Map type name to the new name. Subclasses can override. + * + * @param typeName + * the type name + * @return new name, default implementation is the identity. */ public String map(String typeName) { return typeName; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -65,8 +65,10 @@ /** * An {@link AnnotationVisitor} adapter for type remapping. * + * //@deprecated use {@link AnnotationRemapper} instead. * @author Eugene Kuleshov */ +//@Deprecated public class RemappingAnnotationAdapter extends AnnotationVisitor { protected final Remapper remapper; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingClassAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -69,8 +69,10 @@ /** * A {@link ClassVisitor} for type remapping. * + * @deprecated use {@link ClassRemapper} instead. * @author Eugene Kuleshov */ +@Deprecated public class RemappingClassAdapter extends ClassVisitor { protected final Remapper remapper; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingFieldAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -67,8 +67,10 @@ /** * A {@link FieldVisitor} adapter for type remapping. * + * @deprecated use {@link FieldRemapper} instead. * @author Eugene Kuleshov */ +@Deprecated public class RemappingFieldAdapter extends FieldVisitor { private final Remapper remapper; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -69,8 +69,10 @@ /** * A {@link LocalVariablesSorter} for type mapping. * + * //@deprecated use {@link MethodRemapper} instead. * @author Eugene Kuleshov */ +//@Deprecated public class RemappingMethodAdapter extends LocalVariablesSorter { protected final Remapper remapper; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -65,8 +65,10 @@ /** * A {@link SignatureVisitor} adapter for type mapping. * + * @deprecated use {@link SignatureRemapper} instead. * @author Eugene Kuleshov */ +@Deprecated public class RemappingSignatureAdapter extends SignatureVisitor { private final SignatureVisitor v; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java Mon Mar 21 11:21:08 2016 +0100 @@ -234,7 +234,7 @@ public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { - computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0; + computeSVUID = (access & Opcodes.ACC_ENUM) == 0; if (computeSVUID) { this.name = name; @@ -396,6 +396,11 @@ /* * 2. The class modifiers written as a 32-bit integer. */ + int access = this.access; + if ((access & Opcodes.ACC_INTERFACE) != 0) { + access = (svuidMethods.size() > 0) ? (access | Opcodes.ACC_ABSTRACT) + : (access & ~Opcodes.ACC_ABSTRACT); + } dos.writeInt(access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT)); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SignatureRemapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,188 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jdk.internal.org.objectweb.asm.commons; + +import java.util.Stack; + +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.signature.SignatureVisitor; + +/** + * A {@link SignatureVisitor} adapter for type mapping. + * + * @author Eugene Kuleshov + */ +public class SignatureRemapper extends SignatureVisitor { + + private final SignatureVisitor v; + + private final Remapper remapper; + + private Stack classNames = new Stack(); + + public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) { + this(Opcodes.ASM5, v, remapper); + } + + protected SignatureRemapper(final int api, final SignatureVisitor v, + final Remapper remapper) { + super(api); + this.v = v; + this.remapper = remapper; + } + + @Override + public void visitClassType(String name) { + classNames.push(name); + v.visitClassType(remapper.mapType(name)); + } + + @Override + public void visitInnerClassType(String name) { + String outerClassName = classNames.pop(); + String className = outerClassName + '$' + name; + classNames.push(className); + String remappedOuter = remapper.mapType(outerClassName) + '$'; + String remappedName = remapper.mapType(className); + int index = remappedName.startsWith(remappedOuter) ? remappedOuter + .length() : remappedName.lastIndexOf('$') + 1; + v.visitInnerClassType(remappedName.substring(index)); + } + + @Override + public void visitFormalTypeParameter(String name) { + v.visitFormalTypeParameter(name); + } + + @Override + public void visitTypeVariable(String name) { + v.visitTypeVariable(name); + } + + @Override + public SignatureVisitor visitArrayType() { + v.visitArrayType(); + return this; + } + + @Override + public void visitBaseType(char descriptor) { + v.visitBaseType(descriptor); + } + + @Override + public SignatureVisitor visitClassBound() { + v.visitClassBound(); + return this; + } + + @Override + public SignatureVisitor visitExceptionType() { + v.visitExceptionType(); + return this; + } + + @Override + public SignatureVisitor visitInterface() { + v.visitInterface(); + return this; + } + + @Override + public SignatureVisitor visitInterfaceBound() { + v.visitInterfaceBound(); + return this; + } + + @Override + public SignatureVisitor visitParameterType() { + v.visitParameterType(); + return this; + } + + @Override + public SignatureVisitor visitReturnType() { + v.visitReturnType(); + return this; + } + + @Override + public SignatureVisitor visitSuperclass() { + v.visitSuperclass(); + return this; + } + + @Override + public void visitTypeArgument() { + v.visitTypeArgument(); + } + + @Override + public SignatureVisitor visitTypeArgument(char wildcard) { + v.visitTypeArgument(wildcard); + return this; + } + + @Override + public void visitEnd() { + v.visitEnd(); + classNames.pop(); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SimpleRemapper.java Mon Mar 21 11:21:08 2016 +0100 @@ -86,6 +86,12 @@ } @Override + public String mapInvokeDynamicMethodName(String name, String desc) { + String s = map('.' + name + desc); + return s == null ? name : s; + } + + @Override public String mapFieldName(String owner, String name, String desc) { String s = map(owner + '.' + name); return s == null ? name : s; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureVisitor.java Mon Mar 21 11:21:08 2016 +0100 @@ -68,7 +68,7 @@ *
    *
  • ClassSignature = ( visitFormalTypeParameter * visitClassBound? visitInterfaceBound* )* ( - * visitSuperClass visitInterface* )
  • + * visitSuperclass visitInterface* ) *
  • MethodSignature = ( visitFormalTypeParameter * visitClassBound? visitInterfaceBound* )* ( * visitParameterType* visitReturnType @@ -88,17 +88,17 @@ /** * Wildcard for an "extends" type argument. */ - public static final char EXTENDS = '+'; + public final static char EXTENDS = '+'; /** * Wildcard for a "super" type argument. */ - public static final char SUPER = '-'; + public final static char SUPER = '-'; /** * Wildcard for a normal type argument. */ - public static final char INSTANCEOF = '='; + public final static char INSTANCEOF = '='; /** * The ASM API version implemented by this visitor. The value of this field diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/signature/SignatureWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -69,9 +69,9 @@ public class SignatureWriter extends SignatureVisitor { /** - * Buffer used to construct the signature. + * Builder used to construct the signature. */ - private final StringBuffer buf = new StringBuffer(); + private final StringBuilder buf = new StringBuilder(); /** * Indicates if the signature contains formal type parameters. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/tree/InsnList.java Mon Mar 21 11:21:08 2016 +0100 @@ -205,6 +205,9 @@ /** * Returns an iterator over the instructions in this list. * + * @param index + * index of instruction for the iterator to start at + * * @return an iterator over the instructions in this list. */ @SuppressWarnings("unchecked") diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java Mon Mar 21 11:21:08 2016 +0100 @@ -856,7 +856,11 @@ buf.append("{\n").append("av0 = ").append(name) .append(".visitLocalVariableAnnotation("); buf.append(typeRef); - buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); + if (typePath == null) { + buf.append(", null, "); + } else { + buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); + } buf.append("new Label[] {"); for (int i = 0; i < start.length; ++i) { buf.append(i == 0 ? " " : ", "); @@ -934,7 +938,11 @@ buf.append("{\n").append("av0 = ").append(name).append(".") .append(method).append("("); buf.append(typeRef); - buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); + if (typePath == null) { + buf.append(", null, "); + } else { + buf.append(", TypePath.fromString(\"").append(typePath).append("\"), "); + } appendConstant(desc); buf.append(", ").append(visible).append(");\n"); text.add(buf.toString()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java Mon Mar 21 11:21:08 2016 +0100 @@ -437,6 +437,9 @@ * will not perform any data flow check (see * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}). * + * @param api + * the ASM API version implemented by this CheckMethodAdapter. + * Must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * @param mv * the method visitor to which this adapter must delegate calls. * @param labels diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/Printer.java Mon Mar 21 11:21:08 2016 +0100 @@ -171,6 +171,10 @@ /** * Constructs a new {@link Printer}. + * + * @param api + * the ASM API version implemented by this printer. Must be one + * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. */ protected Printer(final int api) { this.api = api; @@ -179,34 +183,103 @@ } /** - * Class header. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit}. + * Class header. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visit}. + * + * @param version + * the class version. + * @param access + * the class's access flags (see {@link Opcodes}). This parameter + * also indicates if the class is deprecated. + * @param name + * the internal name of the class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param signature + * the signature of this class. May be null if the class + * is not a generic one, and does not extend or implement generic + * classes or interfaces. + * @param superName + * the internal of name of the super class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * For interfaces, the super class is {@link Object}. May be + * null, but only for the {@link Object} class. + * @param interfaces + * the internal names of the class's interfaces (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * May be null. */ public abstract void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces); /** - * Class source. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitSource}. + * Class source. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitSource}. + * + * @param source + * the name of the source file from which the class was compiled. + * May be null. + * @param debug + * additional debug information to compute the correspondance + * between source and compiled elements of the class. May be + * null. */ - public abstract void visitSource(final String file, final String debug); + public abstract void visitSource(final String source, final String debug); /** - * Class outer class. See - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitOuterClass}. + * Class outer class. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitOuterClass}. + * + * Visits the enclosing class of the class. This method must be called only + * if the class has an enclosing class. + * + * @param owner + * internal name of the enclosing class of the class. + * @param name + * the name of the method that contains the class, or + * null if the class is not enclosed in a method of its + * enclosing class. + * @param desc + * the descriptor of the method that contains the class, or + * null if the class is not enclosed in a method of its + * enclosing class. */ public abstract void visitOuterClass(final String owner, final String name, final String desc); /** - * Class annotation. See - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitAnnotation}. + * Class annotation. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitAnnotation}. + * + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public abstract Printer visitClassAnnotation(final String desc, final boolean visible); /** - * Class type annotation. See - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitTypeAnnotation}. + * Class type annotation. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitTypeAnnotation}. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be + * {@link jdk.internal.org.objectweb.asm.TypeReference#CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} + * or {@link jdk.internal.org.objectweb.asm.TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. + * See {@link jdk.internal.org.objectweb.asm.TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public Printer visitClassTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { @@ -214,26 +287,85 @@ } /** - * Class attribute. See - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitAttribute}. + * Class attribute. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitAttribute}. + * + * @param attr + * an attribute. */ public abstract void visitClassAttribute(final Attribute attr); /** - * Class inner name. See - * {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitInnerClass}. + * Class inner name. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitInnerClass}. + * + * @param name + * the internal name of an inner class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param outerName + * the internal name of the class to which the inner class + * belongs (see {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * May be null for not member classes. + * @param innerName + * the (simple) name of the inner class inside its enclosing + * class. May be null for anonymous inner classes. + * @param access + * the access flags of the inner class as originally declared in + * the enclosing class. */ public abstract void visitInnerClass(final String name, final String outerName, final String innerName, final int access); /** - * Class field. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitField}. + * Class field. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitField}. + * + * @param access + * the field's access flags (see {@link Opcodes}). This parameter + * also indicates if the field is synthetic and/or deprecated. + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). + * @param signature + * the field's signature. May be null if the field's + * type does not use generic types. + * @param value + * the field's initial value. This parameter, which may be + * null if the field does not have an initial value, + * must be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String} (for int, + * float, long or String fields + * respectively). This parameter is only used for static + * fields. Its value is ignored for non static fields, which + * must be initialized through bytecode instructions in + * constructors or methods. + * @return the printer */ public abstract Printer visitField(final int access, final String name, final String desc, final String signature, final Object value); /** - * Class method. See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitMethod}. + * Class method. + * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitMethod}. + * + * @param access + * the method's access flags (see {@link Opcodes}). This + * parameter also indicates if the method is synthetic and/or + * deprecated. + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). + * @param signature + * the method's signature. May be null if the method + * parameters, return type and exceptions do not use generic + * types. + * @param exceptions + * the internal names of the method's exception classes (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). May be + * null. + * @return the printer */ public abstract Printer visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions); @@ -248,26 +380,64 @@ // ------------------------------------------------------------------------ /** - * Annotation value. See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visit}. + * Annotation value. + * See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visit}. + * + * @param name + * the value name. + * @param value + * the actual value, whose type must be {@link Byte}, + * {@link Boolean}, {@link Character}, {@link Short}, + * {@link Integer} , {@link Long}, {@link Float}, {@link Double}, + * {@link String} or {@link jdk.internal.org.objectweb.asm.Type} + * or OBJECT or ARRAY sort. + * This value can also be an array of byte, boolean, short, char, int, + * long, float or double values (this is equivalent to using + * {@link #visitArray visitArray} and visiting each array element + * in turn, but is more convenient). */ public abstract void visit(final String name, final Object value); /** - * Annotation enum value. See - * {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitEnum}. + * Annotation enum value. + * See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitEnum}. + * + * Visits an enumeration value of the annotation. + * + * @param name + * the value name. + * @param desc + * the class descriptor of the enumeration class. + * @param value + * the actual enumeration value. */ public abstract void visitEnum(final String name, final String desc, final String value); /** - * Nested annotation value. See - * {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitAnnotation}. + * Nested annotation value. + * See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitAnnotation}. + * + * @param name + * the value name. + * @param desc + * the class descriptor of the nested annotation class. + * @return the printer */ public abstract Printer visitAnnotation(final String name, final String desc); /** - * Annotation array value. See - * {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitArray}. + * Annotation array value. + * See {@link jdk.internal.org.objectweb.asm.AnnotationVisitor#visitArray}. + * + * Visits an array value of the annotation. Note that arrays of primitive + * types (such as byte, boolean, short, char, int, long, float or double) + * can be passed as value to {@link #visit visit}. This is what + * {@link jdk.internal.org.objectweb.asm.ClassReader} does. + * + * @param name + * the value name. + * @return the printer */ public abstract Printer visitArray(final String name); @@ -281,15 +451,35 @@ // ------------------------------------------------------------------------ /** - * Field annotation. See - * {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitAnnotation}. + * Field annotation. + * See {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitAnnotation}. + * + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public abstract Printer visitFieldAnnotation(final String desc, final boolean visible); /** - * Field type annotation. See - * {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitTypeAnnotation}. + * Field type annotation. + * See {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitTypeAnnotation}. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link jdk.internal.org.objectweb.asm.TypeReference#FIELD FIELD}. + * See {@link jdk.internal.org.objectweb.asm.TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public Printer visitFieldTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { @@ -297,13 +487,17 @@ } /** - * Field attribute. See - * {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitAttribute}. + * Field attribute. + * See {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitAttribute}. + * + * @param attr + * an attribute. */ public abstract void visitFieldAttribute(final Attribute attr); /** - * Field end. See {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitEnd}. + * Field end. + * See {@link jdk.internal.org.objectweb.asm.FieldVisitor#visitEnd}. */ public abstract void visitFieldEnd(); @@ -312,29 +506,58 @@ // ------------------------------------------------------------------------ /** - * Method parameter. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitParameter(String, int)}. + * Method parameter. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitParameter(String, int)}. + * + * @param name + * parameter name or null if none is provided. + * @param access + * the parameter's access flags, only ACC_FINAL, + * ACC_SYNTHETIC or/and ACC_MANDATED are + * allowed (see {@link Opcodes}). */ public void visitParameter(String name, int access) { throw new RuntimeException("Must be overriden"); } /** - * Method default annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAnnotationDefault}. + * Method default annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAnnotationDefault}. + * + * @return the printer */ public abstract Printer visitAnnotationDefault(); /** - * Method annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAnnotation}. + * Method annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAnnotation}. + * + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public abstract Printer visitMethodAnnotation(final String desc, final boolean visible); /** - * Method type annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTypeAnnotation}. + * Method type annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTypeAnnotation}. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link jdk.internal.org.objectweb.asm.TypeReference#FIELD FIELD}. + * See {@link jdk.internal.org.objectweb.asm.TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public Printer visitMethodTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { @@ -342,64 +565,225 @@ } /** - * Method parameter annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitParameterAnnotation}. + * Method parameter annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitParameterAnnotation}. + * + * @param parameter + * the parameter index. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public abstract Printer visitParameterAnnotation(final int parameter, final String desc, final boolean visible); /** - * Method attribute. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAttribute}. + * Method attribute. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitAttribute}. + * + * @param attr + * an attribute. */ public abstract void visitMethodAttribute(final Attribute attr); /** - * Method start. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitCode}. + * Method start. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitCode}. */ public abstract void visitCode(); /** - * Method stack frame. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitFrame}. + * Method stack frame. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitFrame}. + * + * Visits the current state of the local variables and operand stack + * elements. This method must(*) be called just before any + * instruction i that follows an unconditional branch instruction + * such as GOTO or THROW, that is the target of a jump instruction, or that + * starts an exception handler block. The visited types must describe the + * values of the local variables and of the operand stack elements just + * before i is executed.
    + *
    + * (*) this is mandatory only for classes whose version is greater than or + * equal to {@link Opcodes#V1_6 V1_6}.
    + *
    + * The frames of a method must be given either in expanded form, or in + * compressed form (all frames must use the same format, i.e. you must not + * mix expanded and compressed frames within a single method): + *
      + *
    • In expanded form, all frames must have the F_NEW type.
    • + *
    • In compressed form, frames are basically "deltas" from the state of + * the previous frame: + *
        + *
      • {@link Opcodes#F_SAME} representing frame with exactly the same + * locals as the previous frame and with the empty stack.
      • + *
      • {@link Opcodes#F_SAME1} representing frame with exactly the same + * locals as the previous frame and with single value on the stack ( + * nStack is 1 and stack[0] contains value for the + * type of the stack item).
      • + *
      • {@link Opcodes#F_APPEND} representing frame with current locals are + * the same as the locals in the previous frame, except that additional + * locals are defined (nLocal is 1, 2 or 3 and + * local elements contains values representing added types).
      • + *
      • {@link Opcodes#F_CHOP} representing frame with current locals are the + * same as the locals in the previous frame, except that the last 1-3 locals + * are absent and with the empty stack (nLocals is 1, 2 or 3).
      • + *
      • {@link Opcodes#F_FULL} representing complete frame data.
      • + *
      + *
    • + *
    + *
    + * In both cases the first frame, corresponding to the method's parameters + * and access flags, is implicit and must not be visited. Also, it is + * illegal to visit two or more frames for the same code location (i.e., at + * least one instruction must be visited between two calls to visitFrame). + * + * @param type + * the type of this stack map frame. Must be + * {@link Opcodes#F_NEW} for expanded frames, or + * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, + * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or + * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for + * compressed frames. + * @param nLocal + * the number of local variables in the visited frame. + * @param local + * the local variable types in this frame. This array must not be + * modified. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, + * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are + * represented by a single element). Reference types are + * represented by String objects (representing internal names), + * and uninitialized types by Label objects (this label + * designates the NEW instruction that created this uninitialized + * value). + * @param nStack + * the number of operand stack elements in the visited frame. + * @param stack + * the operand stack types in this frame. This array must not be + * modified. Its content has the same format as the "local" + * array. + * @throws IllegalStateException + * if a frame is visited just after another one, without any + * instruction between the two (unless this frame is a + * Opcodes#F_SAME frame, in which case it is silently ignored). */ public abstract void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack); /** - * Method instruction. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInsn} - * . + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInsn} + * + * @param opcode + * the opcode of the instruction to be visited. This opcode is + * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, + * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, + * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, + * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, + * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, + * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, + * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, + * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, + * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, + * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, + * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, + * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, + * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, + * or MONITOREXIT. */ public abstract void visitInsn(final int opcode); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIntInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIntInsn}. + * + * @param opcode + * the opcode of the instruction to be visited. This opcode is + * either BIPUSH, SIPUSH or NEWARRAY. + * @param operand + * the operand of the instruction to be visited.
    + * When opcode is BIPUSH, operand value should be between + * Byte.MIN_VALUE and Byte.MAX_VALUE.
    + * When opcode is SIPUSH, operand value should be between + * Short.MIN_VALUE and Short.MAX_VALUE.
    + * When opcode is NEWARRAY, operand value should be one of + * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, + * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, + * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, + * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. */ public abstract void visitIntInsn(final int opcode, final int operand); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitVarInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitVarInsn}. + * + * @param opcode + * the opcode of the local variable instruction to be visited. + * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, + * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. + * @param var + * the operand of the instruction to be visited. This operand is + * the index of a local variable. */ public abstract void visitVarInsn(final int opcode, final int var); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTypeInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTypeInsn}. + * + /** + * Visits a type instruction. A type instruction is an instruction that + * takes the internal name of a class as parameter. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. + * @param type + * the operand of the instruction to be visited. This operand + * must be the internal name of an object or array class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). */ public abstract void visitTypeInsn(final int opcode, final String type); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitFieldInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitFieldInsn}. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. + * @param owner + * the internal name of the field's owner class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param name + * the field's name. + * @param desc + * the field's descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). */ public abstract void visitFieldInsn(final int opcode, final String owner, final String name, final String desc); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). */ @Deprecated public void visitMethodInsn(final int opcode, final String owner, @@ -413,8 +797,22 @@ } /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMethodInsn}. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). + * @param itf + * if the method's owner class is an interface. */ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) { @@ -430,59 +828,181 @@ } /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn}. + * + * Visits an invokedynamic instruction. + * + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). + * @param bsm + * the bootstrap method. + * @param bsmArgs + * the bootstrap method constant arguments. Each argument must be + * an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double}, {@link String}, {@link jdk.internal.org.objectweb.asm.Type} or {@link Handle} + * value. This method is allowed to modify the content of the + * array so a caller should expect that this array may change. */ public abstract void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitJumpInsn}. + * Method jump instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitJumpInsn}. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, + * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, + * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. + * @param label + * the operand of the instruction to be visited. This operand is + * a label that designates the instruction to which the jump + * instruction may jump. */ public abstract void visitJumpInsn(final int opcode, final Label label); /** - * Method label. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLabel}. + * Method label. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLabel}. + * + * @param label + * a {@link Label Label} object. */ public abstract void visitLabel(final Label label); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLdcInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLdcInsn}. + * + * Visits a LDC instruction. Note that new constant types may be added in + * future versions of the Java Virtual Machine. To easily detect new + * constant types, implementations of this method should check for + * unexpected constant types, like this: + * + *
    +     * if (cst instanceof Integer) {
    +     *     // ...
    +     * } else if (cst instanceof Float) {
    +     *     // ...
    +     * } else if (cst instanceof Long) {
    +     *     // ...
    +     * } else if (cst instanceof Double) {
    +     *     // ...
    +     * } else if (cst instanceof String) {
    +     *     // ...
    +     * } else if (cst instanceof Type) {
    +     *     int sort = ((Type) cst).getSort();
    +     *     if (sort == Type.OBJECT) {
    +     *         // ...
    +     *     } else if (sort == Type.ARRAY) {
    +     *         // ...
    +     *     } else if (sort == Type.METHOD) {
    +     *         // ...
    +     *     } else {
    +     *         // throw an exception
    +     *     }
    +     * } else if (cst instanceof Handle) {
    +     *     // ...
    +     * } else {
    +     *     // throw an exception
    +     * }
    +     * 
    + * + * @param cst + * the constant to be loaded on the stack. This parameter must be + * a non null {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double}, a {@link String}, a {@link jdk.internal.org.objectweb.asm.Type} + * of OBJECT or ARRAY sort for .class constants, for classes whose + * version is 49.0, a {@link jdk.internal.org.objectweb.asm.Type} of METHOD sort or a + * {@link Handle} for MethodType and MethodHandle constants, for + * classes whose version is 51.0. */ public abstract void visitLdcInsn(final Object cst); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIincInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitIincInsn}. + * + * @param var + * index of the local variable to be incremented. + * @param increment + * amount to increment the local variable by. */ public abstract void visitIincInsn(final int var, final int increment); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTableSwitchInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTableSwitchInsn}. + * + * @param min + * the minimum key value. + * @param max + * the maximum key value. + * @param dflt + * beginning of the default handler block. + * @param labels + * beginnings of the handler blocks. labels[i] is the + * beginning of the handler block for the min + i key. */ public abstract void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn}. + * + * @param dflt + * beginning of the default handler block. + * @param keys + * the values of the keys. + * @param labels + * beginnings of the handler blocks. labels[i] is the + * beginning of the handler block for the keys[i] key. */ public abstract void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels); /** - * Method instruction. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn}. + * Method instruction. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn}. + * + * @param desc + * an array type descriptor (see {@link jdk.internal.org.objectweb.asm.Type Type}). + * @param dims + * number of dimensions of the array to allocate. */ public abstract void visitMultiANewArrayInsn(final String desc, final int dims); /** - * Instruction type annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInsnAnnotation}. + * Instruction type annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitInsnAnnotation}. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link jdk.internal.org.objectweb.asm.TypeReference#INSTANCEOF INSTANCEOF}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#NEW NEW}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#METHOD_REFERENCE METHOD_REFERENCE}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#CAST CAST}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link jdk.internal.org.objectweb.asm.TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, + * or {@link jdk.internal.org.objectweb.asm.TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. + * See {@link jdk.internal.org.objectweb.asm.TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public Printer visitInsnAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { @@ -490,15 +1010,44 @@ } /** - * Method exception handler. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchBlock}. + * Method exception handler. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchBlock}. + * + * @param start + * beginning of the exception handler's scope (inclusive). + * @param end + * end of the exception handler's scope (exclusive). + * @param handler + * beginning of the exception handler's code. + * @param type + * internal name of the type of exceptions handled by the + * handler, or null to catch any exceptions (for + * "finally" blocks). + * @throws IllegalArgumentException + * if one of the labels has already been visited by this visitor + * (by the {@link #visitLabel visitLabel} method). */ public abstract void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type); /** - * Try catch block type annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchAnnotation}. + * Try catch block type annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchAnnotation}. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link jdk.internal.org.objectweb.asm.TypeReference#EXCEPTION_PARAMETER + * EXCEPTION_PARAMETER}. + * See {@link jdk.internal.org.objectweb.asm.TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public Printer visitTryCatchAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { @@ -506,16 +1055,62 @@ } /** - * Method debug info. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLocalVariable}. + * Method debug info. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLocalVariable}. + * + * @param name + * the name of a local variable. + * @param desc + * the type descriptor of this local variable. + * @param signature + * the type signature of this local variable. May be + * null if the local variable type does not use generic + * types. + * @param start + * the first instruction corresponding to the scope of this local + * variable (inclusive). + * @param end + * the last instruction corresponding to the scope of this local + * variable (exclusive). + * @param index + * the local variable's index. + * @throws IllegalArgumentException + * if one of the labels has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). */ public abstract void visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index); /** - * Local variable type annotation. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchAnnotation}. + * Local variable type annotation. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitTryCatchAnnotation}. + * + * @param typeRef + * a reference to the annotated type. The sort of this type + * reference must be {@link jdk.internal.org.objectweb.asm.TypeReference#LOCAL_VARIABLE + * LOCAL_VARIABLE} or {@link jdk.internal.org.objectweb.asm.TypeReference#RESOURCE_VARIABLE + * RESOURCE_VARIABLE}. + * See {@link jdk.internal.org.objectweb.asm.TypeReference}. + * @param typePath + * the path to the annotated type argument, wildcard bound, array + * element type, or static inner type within 'typeRef'. May be + * null if the annotation targets 'typeRef' as a whole. + * @param start + * the fist instructions corresponding to the continuous ranges + * that make the scope of this local variable (inclusive). + * @param end + * the last instructions corresponding to the continuous ranges + * that make the scope of this local variable (exclusive). This + * array must have the same size as the 'start' array. + * @param index + * the local variable's index in each range. This array must have + * the same size as the 'start' array. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return the printer */ public Printer visitLocalVariableAnnotation(final int typeRef, final TypePath typePath, final Label[] start, final Label[] end, @@ -524,19 +1119,34 @@ } /** - * Method debug info. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLineNumber}. + * Method debug info. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitLineNumber}. + * + * @param line + * a line number. This number refers to the source file from + * which the class was compiled. + * @param start + * the first instruction corresponding to this line number. + * @throws IllegalArgumentException + * if start has not already been visited by this + * visitor (by the {@link #visitLabel visitLabel} method). */ public abstract void visitLineNumber(final int line, final Label start); /** - * Method max stack and max locals. See - * {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMaxs}. + * Method max stack and max locals. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitMaxs}. + * + * @param maxStack + * maximum stack size of the method. + * @param maxLocals + * maximum number of local variables for the method. */ public abstract void visitMaxs(final int maxStack, final int maxLocals); /** - * Method end. See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitEnd}. + * Method end. + * See {@link jdk.internal.org.objectweb.asm.MethodVisitor#visitEnd}. */ public abstract void visitMethodEnd(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java Mon Mar 21 11:21:08 2016 +0100 @@ -74,34 +74,36 @@ * visitor chain to trace the class that is visited at a given point in this * chain. This may be useful for debugging purposes. *

    - * The trace printed when visiting the {@code Hello} class is the following: + * The trace printed when visiting the Hello class is the following: + *

    *

    * - *
    {@code
    + * 
      * // class version 49.0 (49) // access flags 0x21 public class Hello {
      *
      * // compiled from: Hello.java
      *
    - * // access flags 0x1 public  ()V ALOAD 0 INVOKESPECIAL
    - * java/lang/Object  ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
    + * // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL
    + * java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
      *
      * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
    - * java/lang/System out Ljava/io/PrintStream; LDC "hello"
    + * java/lang/System out Ljava/io/PrintStream; LDC "hello"
      * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
      * MAXSTACK = 2 MAXLOCALS = 1 }
    - * }
    + *
    * - *
    where {@code Hello} is defined by: + * where Hello is defined by: + *

    *

    * - *
    {@code
    + * 
      * public class Hello {
      *
      *     public static void main(String[] args) {
    - *         System.out.println("hello");
    + *         System.out.println("hello");
      *     }
      * }
    - * }
    + *
    * *
    * @@ -135,7 +137,7 @@ * * @param cv * the {@link ClassVisitor} to which this visitor delegates - * calls. May be {@code null}. + * calls. May be null. * @param pw * the print writer to be used to print the class. */ @@ -148,7 +150,7 @@ * * @param cv * the {@link ClassVisitor} to which this visitor delegates - * calls. May be {@code null}. + * calls. May be null. * @param p * the object that actually converts visit events into text. * @param pw diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceSignatureVisitor.java Mon Mar 21 11:21:08 2016 +0100 @@ -70,7 +70,7 @@ */ public final class TraceSignatureVisitor extends SignatureVisitor { - private final StringBuffer declaration; + private final StringBuilder declaration; private boolean isInterface; @@ -82,9 +82,9 @@ private boolean seenInterface; - private StringBuffer returnType; + private StringBuilder returnType; - private StringBuffer exceptions; + private StringBuilder exceptions; /** * Stack used to keep track of class types that have arguments. Each element @@ -106,10 +106,10 @@ public TraceSignatureVisitor(final int access) { super(Opcodes.ASM5); isInterface = (access & Opcodes.ACC_INTERFACE) != 0; - this.declaration = new StringBuffer(); + this.declaration = new StringBuilder(); } - private TraceSignatureVisitor(final StringBuffer buf) { + private TraceSignatureVisitor(final StringBuilder buf) { super(Opcodes.ASM5); this.declaration = buf; } @@ -175,14 +175,14 @@ declaration.append('('); } declaration.append(')'); - returnType = new StringBuffer(); + returnType = new StringBuilder(); return new TraceSignatureVisitor(returnType); } @Override public SignatureVisitor visitExceptionType() { if (exceptions == null) { - exceptions = new StringBuffer(); + exceptions = new StringBuilder(); } else { exceptions.append(", "); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/version.txt Mon Mar 21 11:21:08 2016 +0100 @@ -1,12 +1,12 @@ Path: . -Working Copy Root Path: /hudson/jobs/objectweb-init/workspace/asm-svn-2014-10-15 +Working Copy Root Path: /hudson/jobs/objectweb-init/workspace/asm-svn-2016-01-25 URL: file:///svnroot/asm/trunk/asm Repository Root: file:///svnroot/asm Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9 -Revision: 1772 +Revision: 1795 Node Kind: directory Schedule: normal Last Changed Author: ebruneton -Last Changed Rev: 1772 -Last Changed Date: 2014-09-06 09:13:07 +0200 (Sat, 06 Sep 2014) +Last Changed Rev: 1795 +Last Changed Date: 2016-01-24 14:17:10 +0100 (Sun, 24 Jan 2016) diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -700,7 +700,7 @@ * OCSP response data is provided. */ CertificateStatus(StatusRequestType type, X509Certificate[] chain, - Map responses) throws SSLException { + Map responses) { statusType = type; encodedResponsesLen = 0; encodedResponses = new ArrayList<>(chain.length); @@ -715,7 +715,7 @@ encodedResponses.add(respDER); encodedResponsesLen = 3 + respDER.length; } else { - throw new SSLHandshakeException("Zero-length or null " + + throw new IllegalArgumentException("Zero-length or null " + "OCSP Response"); } } else if (statusType == StatusRequestType.OCSP_MULTI) { @@ -732,8 +732,8 @@ } } } else { - throw new SSLHandshakeException("Unsupported StatusResponseType: " + - statusType); + throw new IllegalArgumentException( + "Unsupported StatusResponseType: " + statusType); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Mon Mar 21 11:21:08 2016 +0100 @@ -36,7 +36,6 @@ import java.math.BigInteger; import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.*; import sun.security.action.GetLongAction; @@ -67,7 +66,6 @@ // our authentication info private X509Certificate[] certs; - private Map responseMap; private PrivateKey privateKey; private Object serviceCreds; @@ -118,7 +116,6 @@ LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS, new SSLAlgorithmDecomposer()); - private boolean staplingActive = false; private long statusRespTimeout; static { @@ -578,16 +575,6 @@ } } - // Check if the client has asserted the status_request[_v2] extension(s) - CertStatusReqExtension statReqExt = (CertStatusReqExtension) - mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST); - CertStatusReqListV2Extension statReqExtV2 = - (CertStatusReqListV2Extension)mesg.extensions.get( - ExtensionType.EXT_STATUS_REQUEST_V2); - // Keep stapling active if at least one of the extensions has been set - staplingActive = sslContext.isStaplingEnabled(false) && - (statReqExt != null || statReqExtV2 != null); - /* * FIRST, construct the ServerHello using the options and priorities * from the ClientHello. Update the (pending) cipher spec as we do @@ -883,79 +870,17 @@ m1.extensions.add(maxFragLenExt); } - StatusRequestType statReqType = null; - StatusRequest statReqData = null; - if (staplingActive && !resumingSession) { - ExtensionType statusRespExt = ExtensionType.EXT_STATUS_REQUEST; - - // Determine which type of stapling we are doing and assert the - // proper extension in the server hello. - // Favor status_request_v2 over status_request and ocsp_multi - // over ocsp. - // If multiple ocsp or ocsp_multi types exist, select the first - // instance of a given type - if (statReqExtV2 != null) { // RFC 6961 stapling - statusRespExt = ExtensionType.EXT_STATUS_REQUEST_V2; - List reqItems = - statReqExtV2.getRequestItems(); - int ocspIdx = -1; - int ocspMultiIdx = -1; - for (int pos = 0; pos < reqItems.size(); pos++) { - CertStatusReqItemV2 item = reqItems.get(pos); - if (ocspIdx < 0 && item.getType() == - StatusRequestType.OCSP) { - ocspIdx = pos; - } else if (ocspMultiIdx < 0 && item.getType() == - StatusRequestType.OCSP_MULTI) { - ocspMultiIdx = pos; - } - } - if (ocspMultiIdx >= 0) { - statReqType = reqItems.get(ocspMultiIdx).getType(); - statReqData = reqItems.get(ocspMultiIdx).getRequest(); - } else if (ocspIdx >= 0) { - statReqType = reqItems.get(ocspIdx).getType(); - statReqData = reqItems.get(ocspIdx).getRequest(); - } else { - // Some unknown type. We will not do stapling for - // this connection since we cannot understand the - // requested type. - staplingActive = false; - } - } else { // RFC 6066 stapling - statReqType = StatusRequestType.OCSP; - statReqData = statReqExt.getRequest(); - } - - if (statReqType != null && statReqData != null) { - StatusResponseManager statRespMgr = - sslContext.getStatusResponseManager(); - if (statRespMgr != null) { - responseMap = statRespMgr.get(statReqType, statReqData, - certs, statusRespTimeout, TimeUnit.MILLISECONDS); - if (!responseMap.isEmpty()) { - // We now can safely assert status_request[_v2] in our - // ServerHello, and know for certain that we can provide - // responses back to this client for this connection. - if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { - m1.extensions.add(new CertStatusReqExtension()); - } else if (statusRespExt == - ExtensionType.EXT_STATUS_REQUEST_V2) { - m1.extensions.add( - new CertStatusReqListV2Extension()); - } - } - } else { - // This should not happen if stapling is active, but - // if lazy initialization of the StatusResponseManager - // doesn't occur we should turn off stapling. - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Warning: lazy initialization " + - "of the StatusResponseManager failed. " + - "Stapling has been disabled."); - staplingActive = false; - } - } + StaplingParameters staplingParams = processStapling(mesg); + if (staplingParams != null) { + // We now can safely assert status_request[_v2] in our + // ServerHello, and know for certain that we can provide + // responses back to this client for this connection. + if (staplingParams.statusRespExt == + ExtensionType.EXT_STATUS_REQUEST) { + m1.extensions.add(new CertStatusReqExtension()); + } else if (staplingParams.statusRespExt == + ExtensionType.EXT_STATUS_REQUEST_V2) { + m1.extensions.add(new CertStatusReqListV2Extension()); } } @@ -1031,24 +956,15 @@ * supports status stapling and there is at least one response to * return to the client. */ - if (staplingActive && !responseMap.isEmpty()) { - try { - CertificateStatus csMsg = new CertificateStatus(statReqType, - certs, responseMap); - if (debug != null && Debug.isOn("handshake")) { - csMsg.print(System.out); - } - csMsg.write(output); - handshakeState.update(csMsg, resumingSession); - responseMap = null; - } catch (SSLException ssle) { - // We don't want the exception to be fatal, we just won't - // send the message if we fail on construction. - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Failed during CertificateStatus " + - "construction: " + ssle); - } + if (staplingParams != null) { + CertificateStatus csMsg = new CertificateStatus( + staplingParams.statReqType, certs, + staplingParams.responseMap); + if (debug != null && Debug.isOn("handshake")) { + csMsg.print(System.out); } + csMsg.write(output); + handshakeState.update(csMsg, resumingSession); } /* @@ -2078,4 +1994,121 @@ session.setPeerCertificates(peerCerts); } + + private StaplingParameters processStapling(ClientHello mesg) { + StaplingParameters params = null; + ExtensionType ext; + StatusRequestType type = null; + StatusRequest req = null; + Map responses; + + // If this feature has not been enabled, then no more processing + // is necessary. Also we will only staple if we're doing a full + // handshake. + if (!sslContext.isStaplingEnabled(false) || resumingSession) { + return null; + } + + // Check if the client has asserted the status_request[_v2] extension(s) + CertStatusReqExtension statReqExt = (CertStatusReqExtension) + mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST); + CertStatusReqListV2Extension statReqExtV2 = + (CertStatusReqListV2Extension)mesg.extensions.get( + ExtensionType.EXT_STATUS_REQUEST_V2); + // Keep processing only if either status_request or status_request_v2 + // has been sent in the ClientHello. + if (statReqExt == null && statReqExtV2 == null) { + return null; + } + + // Determine which type of stapling we are doing and assert the + // proper extension in the server hello. + // Favor status_request_v2 over status_request and ocsp_multi + // over ocsp. + // If multiple ocsp or ocsp_multi types exist, select the first + // instance of a given type + ext = ExtensionType.EXT_STATUS_REQUEST; + if (statReqExtV2 != null) { // RFC 6961 stapling + ext = ExtensionType.EXT_STATUS_REQUEST_V2; + List reqItems = + statReqExtV2.getRequestItems(); + int ocspIdx = -1; + int ocspMultiIdx = -1; + for (int pos = 0; pos < reqItems.size(); pos++) { + CertStatusReqItemV2 item = reqItems.get(pos); + if (ocspIdx < 0 && item.getType() == + StatusRequestType.OCSP) { + ocspIdx = pos; + } else if (ocspMultiIdx < 0 && item.getType() == + StatusRequestType.OCSP_MULTI) { + ocspMultiIdx = pos; + } + } + if (ocspMultiIdx >= 0) { + type = reqItems.get(ocspMultiIdx).getType(); + req = reqItems.get(ocspMultiIdx).getRequest(); + } else if (ocspIdx >= 0) { + type = reqItems.get(ocspIdx).getType(); + req = reqItems.get(ocspIdx).getRequest(); + } + } else { // RFC 6066 stapling + type = StatusRequestType.OCSP; + req = statReqExt.getRequest(); + } + + // If, after walking through the extensions we were unable to + // find a suitable StatusRequest, then stapling is disabled. + // Both statReqType and statReqData must have been set to continue. + if (type == null || req == null) { + return null; + } + + // Get the OCSP responses from the StatusResponseManager + StatusResponseManager statRespMgr = + sslContext.getStatusResponseManager(); + if (statRespMgr != null) { + responses = statRespMgr.get(type, req, certs, statusRespTimeout, + TimeUnit.MILLISECONDS); + if (!responses.isEmpty()) { + // If this RFC 6066-style stapling (SSL cert only) then the + // response cannot be zero length + if (type == StatusRequestType.OCSP) { + byte[] respDER = responses.get(certs[0]); + if (respDER == null || respDER.length <= 0) { + return null; + } + } + params = new StaplingParameters(ext, type, req, responses); + } + } else { + // This should not happen, but if lazy initialization of the + // StatusResponseManager doesn't occur we should turn off stapling. + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Warning: lazy initialization " + + "of the StatusResponseManager failed. " + + "Stapling has been disabled."); + } + } + + return params; + } + + /** + * Inner class used to hold stapling parameters needed by the handshaker + * when stapling is active. + */ + private class StaplingParameters { + private final ExtensionType statusRespExt; + private final StatusRequestType statReqType; + private final StatusRequest statReqData; + private final Map responseMap; + + StaplingParameters(ExtensionType ext, StatusRequestType type, + StatusRequest req, Map responses) { + statusRespExt = ext; + statReqType = type; + statReqData = req; + responseMap = responses; + } + } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c --- a/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,6 @@ * questions. */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - #include #include #include @@ -77,21 +73,6 @@ static jfieldID backupResult_context; -/** - * Win32 APIs not available in Windows XP - */ -typedef HANDLE (WINAPI* FindFirstStream_Proc)(LPCWSTR, STREAM_INFO_LEVELS, LPVOID, DWORD); -typedef BOOL (WINAPI* FindNextStream_Proc)(HANDLE, LPVOID); - -typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD); -typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD); - -static FindFirstStream_Proc FindFirstStream_func; -static FindNextStream_Proc FindNextStream_func; - -static CreateSymbolicLinkProc CreateSymbolicLink_func; -static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func; - static void throwWindowsException(JNIEnv* env, DWORD lastError) { jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException", "(I)V", lastError); @@ -108,7 +89,6 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this) { jclass clazz; - HMODULE h; clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile"); CHECK_NULL(clazz); @@ -175,24 +155,6 @@ CHECK_NULL(backupResult_bytesTransferred); backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J"); CHECK_NULL(backupResult_context); - - // get handle to kernel32 - if (GetModuleHandleExW((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), - (LPCWSTR)&CreateFileW, &h) != 0) - { - // requires Windows Server 2003 or newer - FindFirstStream_func = - (FindFirstStream_Proc)GetProcAddress(h, "FindFirstStreamW"); - FindNextStream_func = - (FindNextStream_Proc)GetProcAddress(h, "FindNextStreamW"); - - // requires Windows Vista or newer - CreateSymbolicLink_func = - (CreateSymbolicLinkProc)GetProcAddress(h, "CreateSymbolicLinkW"); - GetFinalPathNameByHandle_func = - (GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW"); - } } JNIEXPORT jlong JNICALL @@ -404,12 +366,7 @@ LPCWSTR lpFileName = jlong_to_ptr(address); HANDLE handle; - if (FindFirstStream_func == NULL) { - JNU_ThrowInternalError(env, "Should not get here"); - return; - } - - handle = (*FindFirstStream_func)(lpFileName, FindStreamInfoStandard, &data, 0); + handle = FindFirstStreamW(lpFileName, FindStreamInfoStandard, &data, 0); if (handle != INVALID_HANDLE_VALUE) { jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName)); if (name == NULL) @@ -433,12 +390,7 @@ WIN32_FIND_STREAM_DATA data; HANDLE h = (HANDLE)jlong_to_ptr(handle); - if (FindNextStream_func == NULL) { - JNU_ThrowInternalError(env, "Should not get here"); - return NULL; - } - - if ((*FindNextStream_func)(h, &data) != 0) { + if (FindNextStreamW(h, &data) != 0) { return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName)); } else { if (GetLastError() != ERROR_HANDLE_EOF) @@ -1087,13 +1039,8 @@ LPCWSTR link = jlong_to_ptr(linkAddress); LPCWSTR target = jlong_to_ptr(targetAddress); - if (CreateSymbolicLink_func == NULL) { - JNU_ThrowInternalError(env, "Should not get here"); - return; - } - /* On Windows 64-bit this appears to succeed even when there is insufficient privileges */ - if ((*CreateSymbolicLink_func)(link, target, (DWORD)flags) == 0) + if (CreateSymbolicLinkW(link, target, (DWORD)flags) == 0) throwWindowsException(env, GetLastError()); } @@ -1155,12 +1102,7 @@ HANDLE h = (HANDLE)jlong_to_ptr(handle); DWORD len; - if (GetFinalPathNameByHandle_func == NULL) { - JNU_ThrowInternalError(env, "Should not get here"); - return NULL; - } - - len = (*GetFinalPathNameByHandle_func)(h, path, MAX_PATH, 0); + len = GetFinalPathNameByHandleW(h, path, MAX_PATH, 0); if (len > 0) { if (len < MAX_PATH) { rv = (*env)->NewString(env, (const jchar *)path, (jsize)len); @@ -1168,7 +1110,7 @@ len += 1; /* return length does not include terminator */ lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR)); if (lpBuf != NULL) { - len = (*GetFinalPathNameByHandle_func)(h, lpBuf, len, 0); + len = GetFinalPathNameByHandleW(h, lpBuf, len, 0); if (len > 0) { rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len); } else { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java Mon Mar 21 11:21:08 2016 +0100 @@ -40,6 +40,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaInternalFrameBorderMetrics; +import java.awt.geom.AffineTransform; public class AquaInternalFrameBorder implements Border, UIResource { private static final int kCloseButton = 0; @@ -309,18 +310,40 @@ return isInsideYButtonArea(i, y) && x >= startX && x <= endX; } - protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, final int x, final int y) { - Icon icon = frame.getFrameIcon(); - if (icon == null) icon = UIManager.getIcon("InternalFrame.icon"); - if (icon == null) return; + protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, + final int x, final int y) { - // Resize to 16x16 if necessary. - if (icon instanceof ImageIcon && (icon.getIconWidth() > sMaxIconWidth || icon.getIconHeight() > sMaxIconHeight)) { - final Image img = ((ImageIcon)icon).getImage(); - ((ImageIcon)icon).setImage(img.getScaledInstance(sMaxIconWidth, sMaxIconHeight, Image.SCALE_SMOOTH)); + Icon icon = frame.getFrameIcon(); + if (icon == null) { + icon = UIManager.getIcon("InternalFrame.icon"); + } + + if (icon == null) { + return; } - icon.paintIcon(frame, g, x, y); + if (icon.getIconWidth() > sMaxIconWidth + || icon.getIconHeight() > sMaxIconHeight) { + final Graphics2D g2 = (Graphics2D) g; + final AffineTransform savedAT = g2.getTransform(); + double xScaleFactor = (double) sMaxIconWidth / icon.getIconWidth(); + double yScaleFactor = (double) sMaxIconHeight / icon.getIconHeight(); + + //Coordinates are after a translation hence relative origin shifts + g2.translate(x, y); + + //scaling factor is needed to scale while maintaining aspect ratio + double scaleMaintainAspectRatio = Math.min(xScaleFactor, yScaleFactor); + + //minimum value is taken to set to a maximum Icon Dimension + g2.scale(scaleMaintainAspectRatio, scaleMaintainAspectRatio); + + icon.paintIcon(frame, g2, 0, 0); + g2.setTransform(savedAT); + + } else { + icon.paintIcon(frame, g, x, y); + } } protected int getIconWidth(final JInternalFrame frame) { @@ -330,9 +353,7 @@ if (icon == null) { icon = UIManager.getIcon("InternalFrame.icon"); } - - if (icon != null && icon instanceof ImageIcon) { - // Resize to 16x16 if necessary. + if (icon != null) { width = Math.min(icon.getIconWidth(), sMaxIconWidth); } @@ -346,9 +367,7 @@ if (icon == null) { icon = UIManager.getIcon("InternalFrame.icon"); } - - if (icon != null && icon instanceof ImageIcon) { - // Resize to 16x16 if necessary. + if (icon != null) { height = Math.min(icon.getIconHeight(), sMaxIconHeight); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java Mon Mar 21 11:21:08 2016 +0100 @@ -128,14 +128,17 @@ // Modify the table "border" to draw smaller, and with the titles in the right position // and sort indicators, just like an NSSave/Open panel. final AquaTableHeaderBorder cellBorder = AquaTableHeaderBorder.getListHeaderBorder(); - final boolean thisColumnSelected = localTable.getColumnModel().getColumn(column).getModelIndex() == sortColumn; + cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE); + + if (localTable != null) { + final boolean thisColumnSelected = localTable.getColumnModel().getColumn(column).getModelIndex() == sortColumn; - cellBorder.setSelected(thisColumnSelected); - if (thisColumnSelected) { - cellBorder.setSortOrder(sortOrder); - } else { - cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE); + cellBorder.setSelected(thisColumnSelected); + if (thisColumnSelected) { + cellBorder.setSortOrder(sortOrder); + } } + setBorder(cellBorder); return this; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m Mon Mar 21 11:21:08 2016 +0100 @@ -134,7 +134,7 @@ {0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks - {0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x40, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F17}, {0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL}, {0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY}, @@ -149,8 +149,8 @@ {0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER}, {0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT}, - {0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, - {0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x4F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F18}, + {0x50, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F19}, {0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS}, {0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0}, {0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1}, @@ -160,7 +160,7 @@ {0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5}, {0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6}, {0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7}, - {0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x5A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F20}, {0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8}, {0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9}, {0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -624,7 +624,8 @@ { NSString *selectedText = [self accessibleSelectedText]; NSAttributedString *styledText = [[NSAttributedString alloc] initWithString:selectedText]; - NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) documentAttributes:nil]; + NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) + documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]; [styledText release]; return rtfdData; } @@ -681,7 +682,7 @@ if ([[pboard types] containsObject:NSRTFDPboardType]) { NSData *rtfdData = [pboard dataForType:NSRTFDPboardType]; - NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:nil]; + NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:NULL]; NSString *text = [styledText string]; [styledText release]; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -743,9 +743,10 @@ JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { OSXAPP_SetJavaVM(vm); - // We need to let Foundation know that this is a multithreaded application, if it isn't already. + // We need to let Foundation know that this is a multithreaded application, + // if it isn't already. if (![NSThread isMultiThreaded]) { - [NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]; + [[[[NSThread alloc] init] autorelease] start]; } return JNI_VERSION_1_4; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/macosx/native/libosx/CFileManager.m --- a/jdk/src/java.desktop/macosx/native/libosx/CFileManager.m Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/macosx/native/libosx/CFileManager.m Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,25 +213,23 @@ */ JNIEXPORT jboolean JNICALL Java_com_apple_eio_FileManager__1moveToTrash -(JNIEnv *env, jclass clz, jstring url) +(JNIEnv *env, jclass clz, jstring fileName) { - __block jboolean returnValue = JNI_FALSE; + __block BOOL returnValue = NO; JNF_COCOA_ENTER(env); - NSString *path = JNFNormalizedNSStringForPath(env, url); + NSString * path = JNFNormalizedNSStringForPath(env, fileName); + NSURL *url = [NSURL fileURLWithPath:path]; [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - NSInteger res = 0; - [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation - source:[path stringByDeletingLastPathComponent] - destination:nil - files:[NSArray arrayWithObject:[path lastPathComponent]] - tag:&res]; - returnValue = (res == 0); + + returnValue = [[NSFileManager defaultManager] trashItemAtURL:url + resultingItemURL:nil + error:nil]; }]; JNF_COCOA_EXIT(env); - return returnValue; + return returnValue ? JNI_TRUE: JNI_FALSE; } /* diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,16 +86,16 @@ /** * Whether to write abbreviated JPEG streams (default == false). - * A subclass which sets this to true should also + * A subclass which sets this to {@code true} should also * initialized {@link #JPEGStreamMetadata}. */ protected boolean writeAbbreviatedStream = false; /** * Stream metadata equivalent to a tables-only stream such as in - * the JPEGTables. Default value is null. + * the {@code JPEGTables}. Default value is {@code null}. * This should be set by any subclass which sets - * {@link writeAbbreviatedStream} to true. + * {@link writeAbbreviatedStream} to {@code true}. */ protected IIOMetadata JPEGStreamMetadata = null; @@ -108,15 +108,15 @@ /** * Removes nonessential nodes from a JPEG native image metadata tree. * All nodes derived from JPEG marker segments other than DHT, DQT, - * SOF, SOS segments are removed unless pruneTables is - * true in which case the nodes derived from the DHT and + * SOF, SOS segments are removed unless {@code pruneTables} is + * {@code true} in which case the nodes derived from the DHT and * DQT marker segments are also removed. * * @param tree A javax_imageio_jpeg_image_1.0 tree. * @param pruneTables Whether to prune Huffman and quantization tables. - * @throws NullPointerException if tree is - * null. - * @throws IllegalArgumentException if tree is not the root + * @throws NullPointerException if {@code tree} is + * {@code null}. + * @throws IllegalArgumentException if {@code tree} is not the root * of a JPEG native image metadata tree. */ private static void pruneNodes(Node tree, boolean pruneTables) { @@ -182,8 +182,8 @@ } /** - * A ByteArrayOutputStream which allows writing to an - * ImageOutputStream. + * A {@code ByteArrayOutputStream} which allows writing to an + * {@code ImageOutputStream}. */ private static class IIOByteArrayOutputStream extends ByteArrayOutputStream { IIOByteArrayOutputStream() { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,39 +31,39 @@ public abstract class TIFFColorConverter { /** - * Constructs an instance of a TIFFColorConverter. + * Constructs an instance of a {@code TIFFColorConverter}. */ public TIFFColorConverter() {} /** * Converts an RGB triple into the native color space of this * TIFFColorConverter, and stores the result in the first three - * entries of the result array. + * entries of the {@code result} array. * * @param r the red value. * @param g the green value. * @param b the blue value. - * @param result an array of floats containing three elements. - * @throws NullPointerException if result is - * null. + * @param result an array of {@code float}s containing three elements. + * @throws NullPointerException if {@code result} is + * {@code null}. * @throws ArrayIndexOutOfBoundsException if - * result.length < 3. + * {@code result.length < 3}. */ public abstract void fromRGB(float r, float g, float b, float[] result); /** * Converts a triple in the native color space of this * TIFFColorConverter into an RGB triple, and stores the result in - * the first three entries of the rgb array. + * the first three entries of the {@code rgb} array. * * @param x0 the value of channel 0. * @param x1 the value of channel 1. * @param x2 the value of channel 2. - * @param rgb an array of floats containing three elements. - * @throws NullPointerException if rgb is - * null. + * @param rgb an array of {@code float}s containing three elements. + * @throws NullPointerException if {@code rgb} is + * {@code null}. * @throws ArrayIndexOutOfBoundsException if - * rgb.length < 3. + * {@code rgb.length < 3}. */ public abstract void toRGB(float x0, float x1, float x2, float[] rgb); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,13 @@ public abstract class TIFFCompressor { /** - * The ImageWriter calling this - * TIFFCompressor. + * The {@code ImageWriter} calling this + * {@code TIFFCompressor}. */ protected ImageWriter writer; /** - * The IIOMetadata object containing metadata for the + * The {@code IIOMetadata} object containing metadata for the * current image. */ protected IIOMetadata metadata; @@ -63,7 +63,7 @@ protected boolean isCompressionLossless; /** - * The ImageOutputStream to be written. + * The {@code ImageOutputStream} to be written. */ protected ImageOutputStream stream; @@ -75,26 +75,26 @@ * to provide the implementation of the compression algorithm of an * unsupported compression type. * - *

    The parameters compressionTagValue and - * isCompressionLossless are provided to accomodate + *

    The parameters {@code compressionTagValue} and + * {@code isCompressionLossless} are provided to accomodate * compression types which are unknown. A compression type is * "known" if it is either among those already supported by the * TIFF writer (see {@link TIFFImageWriteParam}), or is listed in * the TIFF 6.0 specification but not supported. If the compression - * type is unknown, the compressionTagValue and - * isCompressionLossless parameters are ignored.

    + * type is unknown, the {@code compressionTagValue} and + * {@code isCompressionLossless} parameters are ignored.

    * * @param compressionType The name of the compression type. * @param compressionTagValue The value to be assigned to the TIFF * Compression tag in the TIFF image metadata; ignored if - * compressionType is a known type. + * {@code compressionType} is a known type. * @param isCompressionLossless Whether the compression is lossless; - * ignored if compressionType is a known type. + * ignored if {@code compressionType} is a known type. * - * @throws NullPointerException if compressionType is - * null. - * @throws IllegalArgumentException if compressionTagValue is - * less 1. + * @throws NullPointerException if {@code compressionType} is + * {@code null}. + * @throws IllegalArgumentException if {@code compressionTagValue} is + * less {@code 1}. */ public TIFFCompressor(String compressionType, int compressionTagValue, @@ -163,9 +163,9 @@ } /** - * Sets the ImageOutputStream to be written. + * Sets the {@code ImageOutputStream} to be written. * - * @param stream an ImageOutputStream to be written. + * @param stream an {@code ImageOutputStream} to be written. * * @see #getStream */ @@ -174,9 +174,9 @@ } /** - * Returns the ImageOutputStream that will be written. + * Returns the {@code ImageOutputStream} that will be written. * - * @return an ImageOutputStream. + * @return an {@code ImageOutputStream}. * * @see #setStream(ImageOutputStream) */ @@ -185,9 +185,9 @@ } /** - * Sets the value of the writer field. + * Sets the value of the {@code writer} field. * - * @param writer the current ImageWriter. + * @param writer the current {@code ImageWriter}. * * @see #getWriter() */ @@ -196,9 +196,9 @@ } /** - * Returns the current ImageWriter. + * Returns the current {@code ImageWriter}. * - * @return an ImageWriter. + * @return an {@code ImageWriter}. * * @see #setWriter(ImageWriter) */ @@ -207,9 +207,9 @@ } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -219,9 +219,9 @@ } /** - * Returns the current IIOMetadata object. + * Returns the current {@code IIOMetadata} object. * - * @return the IIOMetadata object for the image being + * @return the {@code IIOMetadata} object for the image being * written. * * @see #setMetadata(IIOMetadata) @@ -232,15 +232,15 @@ /** * Encodes the supplied image data, writing to the currently set - * ImageOutputStream. + * {@code ImageOutputStream}. * - * @param b an array of bytes containing the packed + * @param b an array of {@code byte}s containing the packed * but uncompressed image data. * @param off the starting offset of the data to be written in the - * array b. + * array {@code b}. * @param width the width of the rectangle of pixels to be written. * @param height the height of the rectangle of pixels to be written. - * @param bitsPerSample an array of ints indicting + * @param bitsPerSample an array of {@code int}s indicting * the number of bits used to represent each image sample within * a pixel. * @param scanlineStride the number of bytes separating each @@ -249,7 +249,7 @@ * @return the number of bytes written. * * @throws IOException if the supplied data cannot be encoded by - * this TIFFCompressor, or if any I/O error occurs + * this {@code TIFFCompressor}, or if any I/O error occurs * during writing. */ public abstract int encode(byte[] b, int off, diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,7 @@ * *

    Decompressors may be written with various levels of complexity. * The most complex decompressors will override the - * decode method, and will perform all the work of + * {@code decode} method, and will perform all the work of * decoding, subsampling, offsetting, clipping, and format conversion. * This approach may be the most efficient, since it is possible to * avoid the use of extra image buffers, and it may be possible to @@ -89,35 +89,35 @@ * the destination. * *

    Less ambitious decompressors may override the - * decodeRaw method, which is responsible for + * {@code decodeRaw} method, which is responsible for * decompressing the entire tile or strip into a byte array (or other * appropriate datatype). The default implementation of - * decode will perform all necessary setup of buffers, - * call decodeRaw to perform the actual decoding, perform + * {@code decode} will perform all necessary setup of buffers, + * call {@code decodeRaw} to perform the actual decoding, perform * subsampling, and copy the results into the final destination image. * Where possible, it will pass the real image buffer to - * decodeRaw in order to avoid making an extra copy. + * {@code decodeRaw} in order to avoid making an extra copy. * *

    Slightly more ambitious decompressors may override - * decodeRaw, but avoid writing pixels that will be + * {@code decodeRaw}, but avoid writing pixels that will be * discarded in the subsampling phase. */ public abstract class TIFFDecompressor { /** - * The ImageReader calling this - * TIFFDecompressor. + * The {@code ImageReader} calling this + * {@code TIFFDecompressor}. */ protected ImageReader reader; /** - * The IIOMetadata object containing metadata for the + * The {@code IIOMetadata} object containing metadata for the * current image. */ protected IIOMetadata metadata; /** - * The value of the PhotometricInterpretation tag. + * The value of the {@code PhotometricInterpretation} tag. * Legal values are {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO }, * {@link @@ -135,7 +135,7 @@ protected int photometricInterpretation; /** - * The value of the Compression tag. Legal values are + * The value of the {@code Compression} tag. Legal values are * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link @@ -151,23 +151,23 @@ protected int compression; /** - * true if the image is encoded using separate planes. + * {@code true} if the image is encoded using separate planes. */ protected boolean planar; /** - * The value of the SamplesPerPixel tag. + * The value of the {@code SamplesPerPixel} tag. */ protected int samplesPerPixel; /** - * The value of the BitsPerSample tag. + * The value of the {@code BitsPerSample} tag. * */ protected int[] bitsPerSample; /** - * The value of the SampleFormat tag. Legal values + * The value of the {@code SampleFormat} tag. Legal values * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER}, * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link @@ -178,7 +178,7 @@ new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER}; /** - * The value of the ExtraSamples tag. Legal values + * The value of the {@code ExtraSamples} tag. Legal values * are {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNSPECIFIED}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_ASSOCIATED_ALPHA}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNASSOCIATED_ALPHA}, @@ -187,7 +187,7 @@ protected int[] extraSamples; /** - * The value of the ColorMap tag. + * The value of the {@code ColorMap} tag. * */ protected char[] colorMap; @@ -195,20 +195,20 @@ // Region of input stream containing the data /** - * The ImageInputStream containing the TIFF source + * The {@code ImageInputStream} containing the TIFF source * data. */ protected ImageInputStream stream; /** - * The offset in the source ImageInputStream of the + * The offset in the source {@code ImageInputStream} of the * start of the data to be decompressed. */ protected long offset; /** * The number of bytes of data from the source - * ImageInputStream to be decompressed. + * {@code ImageInputStream} to be decompressed. */ protected int byteCount; @@ -244,15 +244,15 @@ // Subsampling to be performed /** - * The source X offset used, along with dstXOffset - * and subsampleX, to map between horizontal source + * The source X offset used, along with {@code dstXOffset} + * and {@code subsampleX}, to map between horizontal source * and destination pixel coordinates. */ protected int sourceXOffset; /** * The horizontal destination offset used, along with - * sourceXOffset and subsampleX, to map + * {@code sourceXOffset} and {@code subsampleX}, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceXOffset sourceXOffset} for * the mapping equations. @@ -260,15 +260,15 @@ protected int dstXOffset; /** - * The source Y offset used, along with dstYOffset - * and subsampleY, to map between vertical source and + * The source Y offset used, along with {@code dstYOffset} + * and {@code subsampleY}, to map between vertical source and * destination pixel coordinates. */ protected int sourceYOffset; /** * The vertical destination offset used, along with - * sourceYOffset and subsampleY, to map + * {@code sourceYOffset} and {@code subsampleY}, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceYOffset sourceYOffset} for * the mapping equations. @@ -305,7 +305,7 @@ // Destination for decodeRaw /** - * A BufferedImage for the decodeRaw + * A {@code BufferedImage} for the {@code decodeRaw} * method to write into. */ protected BufferedImage rawImage; @@ -345,15 +345,15 @@ * The X coordinate of the upper-left source pixel that will * actually be copied into the destination image, taking into * account all subsampling, offsetting, and clipping. That is, - * the pixel at (activeSrcMinX, - * activeSrcMinY) is to be copied into the - * destination pixel at (dstMinX, - * dstMinY). + * the pixel at ({@code activeSrcMinX}, + * {@code activeSrcMinY}) is to be copied into the + * destination pixel at ({@code dstMinX}, + * {@code dstMinY}). * *

    The pixels in the source region to be copied are - * those with X coordinates of the form activeSrcMinX + - * k*subsampleX, where k is an integer such - * that 0 ≤ k < dstWidth. + * those with X coordinates of the form {@code activeSrcMinX + + * k*subsampleX}, where {@code k} is an integer such + * that {@code 0 ≤ k < dstWidth}. */ protected int activeSrcMinX; @@ -363,9 +363,9 @@ * all subsampling, offsetting, and clipping. * *

    The pixels in the source region to be copied are - * those with Y coordinates of the form activeSrcMinY + - * k*subsampleY, where k is an integer such - * that 0 ≤ k < dstHeight. + * those with Y coordinates of the form {@code activeSrcMinY + + * k*subsampleY}, where {@code k} is an integer such + * that {@code 0 ≤ k < dstHeight}. */ protected int activeSrcMinY; @@ -375,7 +375,7 @@ * susbampling, offsetting, and clipping. * *

    The active source width will always be equal to - * (dstWidth - 1)*subsampleX + 1. + * {@code (dstWidth - 1)*subsampleX + 1}. */ protected int activeSrcWidth; @@ -385,13 +385,13 @@ * susbampling, offsetting, and clipping. * *

    The active source height will always be equal to - * (dstHeight - 1)*subsampleY + 1. + * {@code (dstHeight - 1)*subsampleY + 1}. */ protected int activeSrcHeight; /** - * A TIFFColorConverter object describing the color space of - * the encoded pixel data, or null. + * A {@code TIFFColorConverter} object describing the color space of + * the encoded pixel data, or {@code null}. */ protected TIFFColorConverter colorConverter; @@ -420,13 +420,13 @@ // to exactly those dest pixels that are present in the source region. /** - * Create a PixelInterleavedSampleModel for use in creating - * an ImageTypeSpecifier. Its dimensions will be 1x1 and + * Create a {@code PixelInterleavedSampleModel} for use in creating + * an {@code ImageTypeSpecifier}. Its dimensions will be 1x1 and * it will have ascending band offsets as {0, 1, 2, ..., numBands}. * * @param dataType The data type (DataBuffer.TYPE_*). * @param numBands The number of bands. - * @return A PixelInterleavedSampleModel. + * @return A {@code PixelInterleavedSampleModel}. */ static SampleModel createInterleavedSM(int dataType, int numBands) { @@ -443,8 +443,8 @@ } /** - * Create a ComponentColorModel for use in creating - * an ImageTypeSpecifier. + * Create a {@code ComponentColorModel} for use in creating + * an {@code ImageTypeSpecifier}. */ // This code was copied from javax.imageio.ImageTypeSpecifier. static ColorModel createComponentCM(ColorSpace colorSpace, @@ -518,8 +518,8 @@ } /** - * Return the number of bits occupied by dataType - * which must be one of the DataBuffer TYPEs. + * Return the number of bits occupied by {@code dataType} + * which must be one of the {@code DataBuffer} {@code TYPE}s. */ private static int getDataTypeSize(int dataType) throws IIOException { int dataTypeSize = 0; @@ -578,7 +578,7 @@ } /** - * Determines whether the DataBuffer is filled without + * Determines whether the {@code DataBuffer} is filled without * any interspersed padding bits. */ private static boolean isDataBufferBitContiguous(SampleModel sm) @@ -678,8 +678,8 @@ } /** - * Reformats bit-discontiguous data into the DataBuffer - * of the supplied WritableRaster. + * Reformats bit-discontiguous data into the {@code DataBuffer} + * of the supplied {@code WritableRaster}. */ private static void reformatDiscontiguousData(byte[] buf, int stride, @@ -715,21 +715,21 @@ /** * A utility method that returns an - * ImageTypeSpecifier suitable for decoding an image + * {@code ImageTypeSpecifier} suitable for decoding an image * with the given parameters. * * @param photometricInterpretation the value of the - * PhotometricInterpretation field. - * @param compression the value of the Compression field. + * {@code PhotometricInterpretation} field. + * @param compression the value of the {@code Compression} field. * @param samplesPerPixel the value of the - * SamplesPerPixel field. - * @param bitsPerSample the value of the BitsPerSample field. - * @param sampleFormat the value of the SampleFormat field. - * @param extraSamples the value of the ExtraSamples field. - * @param colorMap the value of the ColorMap field. + * {@code SamplesPerPixel} field. + * @param bitsPerSample the value of the {@code BitsPerSample} field. + * @param sampleFormat the value of the {@code SampleFormat} field. + * @param extraSamples the value of the {@code ExtraSamples} field. + * @param colorMap the value of the {@code ColorMap} field. * - * @return a suitable ImageTypeSpecifier, or - * null if it is not possible to create one. + * @return a suitable {@code ImageTypeSpecifier}, or + * {@code null} if it is not possible to create one. */ public static ImageTypeSpecifier getRawImageTypeSpecifier(int photometricInterpretation, @@ -1216,26 +1216,26 @@ } /** - * Sets the value of the reader field. + * Sets the value of the {@code reader} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param reader the current ImageReader. + * @param reader the current {@code ImageReader}. */ public void setReader(ImageReader reader) { this.reader = reader; } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being read. */ public void setMetadata(IIOMetadata metadata) { @@ -1243,10 +1243,10 @@ } /** - * Sets the value of the photometricInterpretation + * Sets the value of the {@code photometricInterpretation} * field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1258,9 +1258,9 @@ } /** - * Sets the value of the compression field. + * Sets the value of the {@code compression} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1271,13 +1271,13 @@ } /** - * Sets the value of the planar field. + * Sets the value of the {@code planar} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param planar true if the image to be decoded is + * @param planar {@code true} if the image to be decoded is * stored in planar format. */ public void setPlanar(boolean planar) { @@ -1285,9 +1285,9 @@ } /** - * Sets the value of the samplesPerPixel field. + * Sets the value of the {@code samplesPerPixel} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1299,9 +1299,9 @@ } /** - * Sets the value of the bitsPerSample field. + * Sets the value of the {@code bitsPerSample} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1314,9 +1314,9 @@ } /** - * Sets the value of the sampleFormat field. + * Sets the value of the {@code sampleFormat} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1330,9 +1330,9 @@ } /** - * Sets the value of the extraSamples field. + * Sets the value of the {@code extraSamples} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1346,14 +1346,14 @@ } /** - * Sets the value of the colorMap field. + * Sets the value of the {@code colorMap} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param colorMap the color map to apply to the source data, - * as an array of chars. + * as an array of {@code char}s. */ public void setColorMap(char[] colorMap) { this.colorMap = colorMap == null ? @@ -1361,22 +1361,22 @@ } /** - * Sets the value of the stream field. + * Sets the value of the {@code stream} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param stream the ImageInputStream to be read. + * @param stream the {@code ImageInputStream} to be read. */ public void setStream(ImageInputStream stream) { this.stream = stream; } /** - * Sets the value of the offset field. + * Sets the value of the {@code offset} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1388,9 +1388,9 @@ } /** - * Sets the value of the byteCount field. + * Sets the value of the {@code byteCount} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1403,9 +1403,9 @@ // Region of the file image represented in the stream /** - * Sets the value of the srcMinX field. + * Sets the value of the {@code srcMinX} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1418,9 +1418,9 @@ } /** - * Sets the value of the srcMinY field. + * Sets the value of the {@code srcMinY} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1433,9 +1433,9 @@ } /** - * Sets the value of the srcWidth field. + * Sets the value of the {@code srcWidth} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1447,9 +1447,9 @@ } /** - * Sets the value of the srcHeight field. + * Sets the value of the {@code srcHeight} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1463,9 +1463,9 @@ // First source pixel to be read /** - * Sets the value of the sourceXOffset field. + * Sets the value of the {@code sourceXOffset} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1477,9 +1477,9 @@ } /** - * Sets the value of the dstXOffset field. + * Sets the value of the {@code dstXOffset} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1491,9 +1491,9 @@ } /** - * Sets the value of the sourceYOffset. + * Sets the value of the {@code sourceYOffset}. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1505,9 +1505,9 @@ } /** - * Sets the value of the dstYOffset field. + * Sets the value of the {@code dstYOffset} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1521,15 +1521,15 @@ // Subsampling to be performed /** - * Sets the value of the subsampleX field. + * Sets the value of the {@code subsampleX} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param subsampleX the horizontal subsampling factor. * - * @throws IllegalArgumentException if subsampleX is + * @throws IllegalArgumentException if {@code subsampleX} is * less than or equal to 0. */ public void setSubsampleX(int subsampleX) { @@ -1540,15 +1540,15 @@ } /** - * Sets the value of the subsampleY field. + * Sets the value of the {@code subsampleY} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param subsampleY the vertical subsampling factor. * - * @throws IllegalArgumentException if subsampleY is + * @throws IllegalArgumentException if {@code subsampleY} is * less than or equal to 0. */ public void setSubsampleY(int subsampleY) { @@ -1561,13 +1561,13 @@ // Band subsetting/rearrangement /** - * Sets the value of the sourceBands field. + * Sets the value of the {@code sourceBands} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param sourceBands an array of ints + * @param sourceBands an array of {@code int}s * specifying the source bands to be read. */ public void setSourceBands(int[] sourceBands) { @@ -1576,13 +1576,13 @@ } /** - * Sets the value of the destinationBands field. + * Sets the value of the {@code destinationBands} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param destinationBands an array of ints + * @param destinationBands an array of {@code int}s * specifying the destination bands to be written. */ public void setDestinationBands(int[] destinationBands) { @@ -1593,22 +1593,22 @@ // Destination image and region /** - * Sets the value of the image field. + * Sets the value of the {@code image} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param image the destination BufferedImage. + * @param image the destination {@code BufferedImage}. */ public void setImage(BufferedImage image) { this.image = image; } /** - * Sets the value of the dstMinX field. + * Sets the value of the {@code dstMinX} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1620,9 +1620,9 @@ } /** - * Sets the value of the dstMinY field. + * Sets the value of the {@code dstMinY} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1634,9 +1634,9 @@ } /** - * Sets the value of the dstWidth field. + * Sets the value of the {@code dstWidth} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1647,9 +1647,9 @@ } /** - * Sets the value of the dstHeight field. + * Sets the value of the {@code dstHeight} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1662,9 +1662,9 @@ // Active source region /** - * Sets the value of the activeSrcMinX field. + * Sets the value of the {@code activeSrcMinX} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1676,9 +1676,9 @@ } /** - * Sets the value of the activeSrcMinY field. + * Sets the value of the {@code activeSrcMinY} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1690,9 +1690,9 @@ } /** - * Sets the value of the activeSrcWidth field. + * Sets the value of the {@code activeSrcWidth} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1703,9 +1703,9 @@ } /** - * Sets the value of the activeSrcHeight field. + * Sets the value of the {@code activeSrcHeight} field. * - *

    If this method is called, the beginDecoding + *

    If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1716,23 +1716,23 @@ } /** - * Sets the TIFFColorConverter object describing the color + * Sets the {@code TIFFColorConverter} object describing the color * space of the encoded data in the input stream. If no - * TIFFColorConverter is set, no conversion will be performed. + * {@code TIFFColorConverter} is set, no conversion will be performed. * - * @param colorConverter a TIFFColorConverter object, or - * null. + * @param colorConverter a {@code TIFFColorConverter} object, or + * {@code null}. */ public void setColorConverter(TIFFColorConverter colorConverter) { this.colorConverter = colorConverter; } /** - * Returns an ImageTypeSpecifier describing an image + * Returns an {@code ImageTypeSpecifier} describing an image * whose underlying data array has the same format as the raw * source pixel data. * - * @return an ImageTypeSpecifier. + * @return an {@code ImageTypeSpecifier}. */ public ImageTypeSpecifier getRawImageType() { ImageTypeSpecifier its = @@ -1747,18 +1747,18 @@ } /** - * Creates a BufferedImage whose underlying data + * Creates a {@code BufferedImage} whose underlying data * array will be suitable for holding the raw decoded output of - * the decodeRaw method. + * the {@code decodeRaw} method. * *

    The default implementation calls - * getRawImageType, and calls the resulting - * ImageTypeSpecifier's - * createBufferedImage method. + * {@code getRawImageType}, and calls the resulting + * {@code ImageTypeSpecifier}'s + * {@code createBufferedImage} method. * - * @return a BufferedImage whose underlying data + * @return a {@code BufferedImage} whose underlying data * array has the same format as the raw source pixel data, or - * null if it is not possible to create such an + * {@code null} if it is not possible to create such an * image. */ public BufferedImage createRawImage() { @@ -1811,22 +1811,22 @@ } /** - * Decodes the source data into the provided byte - * array b, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * bytes. + * Decodes the source data into the provided {@code byte} + * array {@code b}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code byte}s. * - * @param b a byte array to be written. - * @param dstOffset the starting offset in b to be + * @param b a {@code byte} array to be written. + * @param dstOffset the starting offset in {@code b} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of bytes to + * @param scanlineStride the number of {@code byte}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public abstract void decodeRaw(byte[] b, int dstOffset, @@ -1834,25 +1834,25 @@ int scanlineStride) throws IOException; /** - * Decodes the source data into the provided short - * array s, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * shorts + * Decodes the source data into the provided {@code short} + * array {@code s}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code short}s * - *

    The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into s. + *

    The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code s}. * - * @param s a short array to be written. - * @param dstOffset the starting offset in s to be + * @param s a {@code short} array to be written. + * @param dstOffset the starting offset in {@code s} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of shorts to + * @param scanlineStride the number of {@code short}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(short[] s, int dstOffset, @@ -1891,25 +1891,25 @@ } /** - * Decodes the source data into the provided int - * array i, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * ints. + * Decodes the source data into the provided {@code int} + * array {@code i}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code int}s. * - *

    The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into i. + *

    The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code i}. * - * @param i an int array to be written. - * @param dstOffset the starting offset in i to be + * @param i an {@code int} array to be written. + * @param dstOffset the starting offset in {@code i} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of ints to + * @param scanlineStride the number of {@code int}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(int[] i, int dstOffset, @@ -1953,25 +1953,25 @@ } /** - * Decodes the source data into the provided float - * array f, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * floats. + * Decodes the source data into the provided {@code float} + * array {@code f}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code float}s. * - *

    The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into f. + *

    The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code f}. * - * @param f a float array to be written. - * @param dstOffset the starting offset in f to be + * @param f a {@code float} array to be written. + * @param dstOffset the starting offset in {@code f} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of floats to + * @param scanlineStride the number of {@code float}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(float[] f, int dstOffset, @@ -2017,25 +2017,25 @@ } /** - * Decodes the source data into the provided double - * array f, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * doubles. + * Decodes the source data into the provided {@code double} + * array {@code f}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code double}s. * - *

    The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into f. + *

    The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code f}. * - * @param f a double array to be written. - * @param dstOffset the starting offset in f to be + * @param f a {@code double} array to be written. + * @param dstOffset the starting offset in {@code f} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of doubles to + * @param scanlineStride the number of {@code double}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(double[] d, int dstOffset, @@ -2104,16 +2104,16 @@ /** * This routine is called prior to a sequence of calls to the - * decode method, in order to allow any necessary + * {@code decode} method, in order to allow any necessary * tables or other structures to be initialized based on metadata * values. This routine is guaranteed to be called any time the * metadata values have changed. * *

    The default implementation computes tables used by the - * decode method to rescale components to different + * {@code decode} method to rescale components to different * bit depths. Thus, if this method is overridden, it is - * important for the subclass method to call super(), - * unless it overrides decode as well. + * important for the subclass method to call {@code super()}, + * unless it overrides {@code decode} as well. */ public void beginDecoding() { // Note: This method assumes that sourceBands, destinationBands, @@ -2242,35 +2242,35 @@ /** * Decodes the input bit stream (located in the - * ImageInputStream stream, at offset - * offset, and continuing for byteCount - * bytes) into the output BufferedImage - * image. + * {@code ImageInputStream} {@code stream}, at offset + * {@code offset}, and continuing for {@code byteCount} + * bytes) into the output {@code BufferedImage} + * {@code image}. * *

    The default implementation analyzes the destination image * to determine if it is suitable as the destination for the - * decodeRaw method. If not, a suitable image is - * created. Next, decodeRaw is called to perform the + * {@code decodeRaw} method. If not, a suitable image is + * created. Next, {@code decodeRaw} is called to perform the * actual decoding, and the results are copied into the * destination image if necessary. Subsampling and offsetting are * performed automatically. * *

    The precise responsibilities of this routine are as * follows. The input bit stream is defined by the instance - * variables stream, offset, and - * byteCount. These bits contain the data for the - * region of the source image defined by srcMinX, - * srcMinY, srcWidth, and - * srcHeight. + * variables {@code stream}, {@code offset}, and + * {@code byteCount}. These bits contain the data for the + * region of the source image defined by {@code srcMinX}, + * {@code srcMinY}, {@code srcWidth}, and + * {@code srcHeight}. * *

    The source data is required to be subsampling, starting at - * the sourceXOffsetth column and including - * every subsampleXth pixel thereafter (and similarly - * for sourceYOffset and - * subsampleY). + * the {@code sourceXOffset}th column and including + * every {@code subsampleX}th pixel thereafter (and similarly + * for {@code sourceYOffset} and + * {@code subsampleY}). * *

    Pixels are copied into the destination with an addition shift of - * (dstXOffset, dstYOffset). The complete + * ({@code dstXOffset}, {@code dstYOffset}). The complete * set of formulas relating the source and destination coordinate spaces * are: * @@ -2279,9 +2279,9 @@ * dy = (sy - sourceYOffset)/subsampleY + dstYOffset; * * - * Only source pixels such that (sx - sourceXOffset) % - * subsampleX == 0 and (sy - sourceYOffset) % - * subsampleY == 0 are copied. + * Only source pixels such that {@code (sx - sourceXOffset) % + * subsampleX == 0} and {@code (sy - sourceYOffset) % + * subsampleY == 0} are copied. * *

    The inverse mapping, from destination to source coordinates, * is one-to-one: @@ -2292,9 +2292,9 @@ * * *

    The region of the destination image to be updated is given - * by the instance variables dstMinX, - * dstMinY, dstWidth, and - * dstHeight. + * by the instance variables {@code dstMinX}, + * {@code dstMinY}, {@code dstWidth}, and + * {@code dstHeight}. * *

    It is possible that not all of the source data being read * will contribute to the destination image. For example, the @@ -2303,32 +2303,32 @@ * convenience, the bounds of the active source region (that is, * the region of the strip or tile being read that actually * contributes to the destination image, taking clipping into - * account) are available as activeSrcMinX, - * activeSrcMinY, activeSrcWidth and - * activeSrcHeight. Thus, the source pixel at - * (activeSrcMinX, activeSrcMinY) will - * map to the destination pixel (dstMinX, - * dstMinY). + * account) are available as {@code activeSrcMinX}, + * {@code activeSrcMinY}, {@code activeSrcWidth} and + * {@code activeSrcHeight}. Thus, the source pixel at + * ({@code activeSrcMinX}, {@code activeSrcMinY}) will + * map to the destination pixel ({@code dstMinX}, + * {@code dstMinY}). * *

    The sequence of source bands given by - * sourceBands are to be copied into the sequence of + * {@code sourceBands} are to be copied into the sequence of * bands in the destination given by - * destinationBands. + * {@code destinationBands}. * *

    Some standard tag information is provided the instance - * variables photometricInterpretation, - * compression, samplesPerPixel, - * bitsPerSample, sampleFormat, - * extraSamples, and colorMap. + * variables {@code photometricInterpretation}, + * {@code compression}, {@code samplesPerPixel}, + * {@code bitsPerSample}, {@code sampleFormat}, + * {@code extraSamples}, and {@code colorMap}. * *

    In practice, unless there is a significant performance * advantage to be gained by overriding this routine, most users * will prefer to use the default implementation of this routine, - * and instead override the decodeRaw and/or - * getRawImageType methods. + * and instead override the {@code decodeRaw} and/or + * {@code getRawImageType} methods. * * @exception IOException if an error occurs in - * decodeRaw. + * {@code decodeRaw}. */ public void decode() throws IOException { byte[] byteData = null; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ import javax.imageio.plugins.tiff.BaselineTIFFTagSet; /** - * A TIFFCompressor for the JPEG variant of Exif. + * A {@code TIFFCompressor} for the JPEG variant of Exif. */ public class TIFFExifJPEGCompressor extends TIFFBaseJPEGCompressor { public TIFFExifJPEGCompressor(ImageWriteParam param) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -232,12 +232,12 @@ } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

    The implementation in this class also sets local options * from the FILL_ORDER field if it exists.

    * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -253,8 +253,8 @@ } /** - * Return min of maxOffset or offset of first pixel - * different from pixel at bitOffset. + * Return min of {@code maxOffset} or offset of first pixel + * different from pixel at {@code bitOffset}. */ public int nextState(byte[] data, int base, diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,12 +34,12 @@ import javax.imageio.plugins.tiff.TIFFTagSet; /** - * The Node representation of a TIFFField + * The {@code Node} representation of a {@code TIFFField} * wherein the child node is procedural rather than buffered. */ public class TIFFFieldNode extends IIOMetadataNode { private static String getNodeName(TIFFField f) { - return f.getData() instanceof TIFFDirectory ? + return (f.hasDirectory() || f.getData() instanceof TIFFDirectory) ? "TIFFIFD" : "TIFFField"; } @@ -52,7 +52,8 @@ public TIFFFieldNode(TIFFField field) { super(getNodeName(field)); - isIFD = field.getData() instanceof TIFFDirectory; + isIFD = field.hasDirectory() || + field.getData() instanceof TIFFDirectory; this.field = field; @@ -68,7 +69,8 @@ setAttribute("parentTagName", tagName); } - TIFFDirectory dir = (TIFFDirectory)field.getData(); + TIFFDirectory dir = field.hasDirectory() ? + field.getDirectory() : (TIFFDirectory)field.getData(); TIFFTagSet[] tagSets = dir.getTagSets(); if(tagSets != null) { StringBuilder tagSetNames = new StringBuilder(); @@ -90,7 +92,8 @@ if(isInitialized) return; if(isIFD) { - TIFFDirectory dir = (TIFFDirectory)field.getData(); + TIFFDirectory dir = field.hasDirectory() ? + field.getDirectory() : (TIFFDirectory)field.getData(); TIFFField[] fields = dir.getTIFFFields(); if(fields != null) { TIFFTagSet[] tagSets = dir.getTagSets(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,7 +153,7 @@ } /** - * Returns an Iterator over the TIFF fields. The + * Returns an {@code Iterator} over the TIFF fields. The * traversal is in the order of increasing tag number. */ // Note: the sort is guaranteed for low fields by the use of an @@ -164,7 +164,7 @@ } /** - * Read the value of a field. The data parameter should be + * Read the value of a field. The {@code data} parameter should be * an array of length 1 of Object. * * @param stream the input stream @@ -762,8 +762,8 @@ } /** - * Returns a TIFFIFD wherein all fields from the - * BaselineTIFFTagSet are copied by value and all other + * Returns a {@code TIFFIFD} wherein all fields from the + * {@code BaselineTIFFTagSet} are copied by value and all other * fields copied by reference. */ public TIFFIFD getShallowClone() { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1620,8 +1620,8 @@ } /** - * Returns a TIFFImageMetadata wherein all fields in the - * root IFD from the BaselineTIFFTagSet are copied by value + * Returns a {@code TIFFImageMetadata} wherein all fields in the + * root IFD from the {@code BaselineTIFFTagSet} are copied by value * and all other fields copied by reference. */ public TIFFImageMetadata getShallowClone() { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ // Metadata for image at 'currIndex', or null. private TIFFImageMetadata imageMetadata = null; - // A List of Longs indicating the stream + // A {@code List} of {@code Long}s indicating the stream // positions of the start of the IFD for each image. Entries // are added as needed. private List imageStartPosition = new ArrayList(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,11 +122,11 @@ * quality value is passed directly to the JPEG writer plug-in which * interprets it in the usual way.

    * - *

    The canWriteTiles and - * canWriteCompressed methods will return - * true; the canOffsetTiles and - * canWriteProgressive methods will return - * false.

    + *

    The {@code canWriteTiles} and + * {@code canWriteCompressed} methods will return + * {@code true}; the {@code canOffsetTiles} and + * {@code canWriteProgressive} methods will return + * {@code false}.

    * *

    If tiles are being written, then each of their dimensions will be * rounded to the nearest multiple of 16 per the TIFF specification. If @@ -140,10 +140,10 @@ public class TIFFImageWriteParam extends ImageWriteParam { /** - * Constructs a TIFFImageWriteParam instance - * for a given Locale. + * Constructs a {@code TIFFImageWriteParam} instance + * for a given {@code Locale}. * - * @param locale the Locale for which messages + * @param locale the {@code Locale} for which messages * should be localized. */ public TIFFImageWriteParam(Locale locale) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,11 +221,11 @@ * relative to a given tile grid layout specified by its X offset * and tile width. * - *

    If tileWidth < 0, the results of this method - * are undefined. If tileWidth == 0, an - * ArithmeticException will be thrown. + *

    If {@code tileWidth < 0}, the results of this method + * are undefined. If {@code tileWidth == 0}, an + * {@code ArithmeticException} will be thrown. * - * @throws ArithmeticException If tileWidth == 0. + * @throws ArithmeticException If {@code tileWidth == 0}. */ public static int XToTileX(int x, int tileGridXOffset, int tileWidth) { x -= tileGridXOffset; @@ -240,11 +240,11 @@ * relative to a given tile grid layout specified by its Y offset * and tile height. * - *

    If tileHeight < 0, the results of this method - * are undefined. If tileHeight == 0, an - * ArithmeticException will be thrown. + *

    If {@code tileHeight < 0}, the results of this method + * are undefined. If {@code tileHeight == 0}, an + * {@code ArithmeticException} will be thrown. * - * @throws ArithmeticException If tileHeight == 0. + * @throws ArithmeticException If {@code tileHeight == 0}. */ public static int YToTileY(int y, int tileGridYOffset, int tileHeight) { y -= tileGridYOffset; @@ -424,17 +424,17 @@ } /** - * Converts a standard javax_imageio_1.0 tree to a - * TIFFImageMetadata object. + * Converts a standard {@code javax_imageio_1.0} tree to a + * {@code TIFFImageMetadata} object. * * @param inData The metadata object. - * @return a TIFFImageMetadata or null if - * the standard tree derived from the input object is null. - * @throws IllegalArgumentException if inData is - * null. - * @throws IllegalArgumentException if inData does not support + * @return a {@code TIFFImageMetadata} or {@code null} if + * the standard tree derived from the input object is {@code null}. + * @throws IllegalArgumentException if {@code inData} is + * {@code null}. + * @throws IllegalArgumentException if {@code inData} does not support * the standard metadata format. - * @throws IIOInvalidTreeException if inData generates an + * @throws IIOInvalidTreeException if {@code inData} generates an * invalid standard metadata tree. */ private TIFFImageMetadata convertStandardImageMetadata(IIOMetadata inData) @@ -463,15 +463,15 @@ /** * Converts a native - * javax_imageio_tiff_image_1.0 tree to a - * TIFFImageMetadata object. + * {@code javax_imageio_tiff_image_1.0} tree to a + * {@code TIFFImageMetadata} object. * * @param inData The metadata object. - * @return a TIFFImageMetadata or null if - * the native tree derived from the input object is null. - * @throws IllegalArgumentException if inData is - * null or does not support the native metadata format. - * @throws IIOInvalidTreeException if inData generates an + * @return a {@code TIFFImageMetadata} or {@code null} if + * the native tree derived from the input object is {@code null}. + * @throws IllegalArgumentException if {@code inData} is + * {@code null} or does not support the native metadata format. + * @throws IIOInvalidTreeException if {@code inData} generates an * invalid native metadata tree. */ private TIFFImageMetadata convertNativeImageMetadata(IIOMetadata inData) @@ -504,8 +504,8 @@ * as needed. The destination image dimensions are provided as parameters * because these might differ from those of the source due to subsampling. * - * @param cm The ColorModel of the image being written. - * @param sm The SampleModel of the image being written. + * @param cm The {@code ColorModel} of the image being written. + * @param sm The {@code SampleModel} of the image being written. * @param destWidth The width of the written image after subsampling. * @param destHeight The height of the written image after subsampling. */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,14 +102,14 @@ } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

    The implementation in this class also adds the TIFF fields * JPEGTables, YCbCrSubSampling, YCbCrPositioning, and * ReferenceBlackWhite superseding any prior settings of those * fields.

    * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,7 +245,7 @@ } /** - * Append newString to the end of oldString. + * Append {@code newString} to the end of {@code oldString}. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,7 +188,7 @@ } /** - * Append newString to the end of oldString. + * Append {@code newString} to the end of {@code oldString}. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,16 +34,16 @@ */ private boolean isReadActiveOnly = false; - /** The original value of srcMinX. */ + /** The original value of {@code srcMinX}. */ private int originalSrcMinX; - /** The original value of srcMinY. */ + /** The original value of {@code srcMinY}. */ private int originalSrcMinY; - /** The original value of srcWidth. */ + /** The original value of {@code srcWidth}. */ private int originalSrcWidth; - /** The original value of srcHeight. */ + /** The original value of {@code srcHeight}. */ private int originalSrcHeight; public TIFFNullDecompressor() {} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ import javax.imageio.plugins.tiff.TIFFField; /** - * TIFFDecompressor for "Old JPEG" compression. + * {@code TIFFDecompressor} for "Old JPEG" compression. */ public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,8 +42,8 @@ * CCITT RLE (Run Lenth Encoding). * * @param data The row of data to compress. - * @param rowOffset Starting index in data. - * @param colOffset Bit offset within first data[rowOffset]. + * @param rowOffset Starting index in {@code data}. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param rowLength Number of bits in the row. * @param compData The compressed data. * diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,15 +85,15 @@ } /** - * Creates a copy of param. The source subsampling and + * Creates a copy of {@code param}. The source subsampling and * and bands settings and the destination bands and offset settings - * are copied. If param is a TIFFImageReadParam - * then the TIFFDecompressor and - * TIFFColorConverter settings are also copied; otherwise - * they are explicitly set to null. + * are copied. If {@code param} is a {@code TIFFImageReadParam} + * then the {@code TIFFDecompressor} and + * {@code TIFFColorConverter} settings are also copied; otherwise + * they are explicitly set to {@code null}. * * @param param the parameters to be copied. - * @param copyTagSets whether the TIFFTagSet settings + * @param copyTagSets whether the {@code TIFFTagSet} settings * should be copied if set. * @return copied parameters. */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,13 +41,13 @@ } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

    The implementation in this class also sets local options * from the T4_OPTIONS field if it exists, and if it doesn't, adds * it with default values.

    * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -86,7 +86,7 @@ * @param isEOLAligned Whether EOL bit sequences should be padded. * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. - * @param colOffset Bit offset within first data[rowOffset]. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ * * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. - * @param colOffset Bit offset within first data[rowOffset]. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,11 @@ package com.sun.media.sound; import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; @@ -49,11 +49,6 @@ throws UnsupportedAudioFileException, IOException { DataInputStream dis = new DataInputStream(stream); - // assumes a stream at the beginning of the file which has already - // passed the magic number test... - // leaves the input stream at the beginning of the audio data - int fileRead = 0; - int dataLength = 0; AudioFormat format = null; // Read the magic number @@ -65,9 +60,9 @@ throw new UnsupportedAudioFileException("not an AIFF file"); } + int frameLength = 0; int length = dis.readInt(); int iffType = dis.readInt(); - fileRead += 12; int totallength; if(length <= 0 ) { @@ -91,7 +86,6 @@ // Read the chunk name int chunkName = dis.readInt(); int chunkLen = dis.readInt(); - fileRead += 8; int chunkRead = 0; @@ -112,7 +106,13 @@ if (channels <= 0) { throw new UnsupportedAudioFileException("Invalid number of channels"); } - dis.readInt(); // numSampleFrames + frameLength = dis.readInt(); // numSampleFrames + if (frameLength < 0) { + // AiffFileFormat uses int, unlike AIS which uses long + //TODO this (negative) value should be passed as long to AIS + frameLength = AudioSystem.NOT_SPECIFIED; + } + int sampleSizeInBits = dis.readUnsignedShort(); if (sampleSizeInBits < 1 || sampleSizeInBits > 32) { throw new UnsupportedAudioFileException("Invalid AIFF/COMM sampleSize"); @@ -149,38 +149,17 @@ break; case AiffFileFormat.SSND_MAGIC: // Data chunk. - // we are getting *weird* numbers for chunkLen sometimes; - // this really should be the size of the data chunk.... - int dataOffset = dis.readInt(); - int blocksize = dis.readInt(); + int dataOffset = dis.readInt(); // for now unused in javasound + int blocksize = dis.readInt(); // for now unused in javasound chunkRead += 8; - - // okay, now we are done reading the header. we need to set the size - // of the data segment. we know that sometimes the value we get for - // the chunksize is absurd. this is the best i can think of:if the - // value seems okay, use it. otherwise, we get our value of - // length by assuming that everything left is the data segment; - // its length should be our original length (for all AIFF data chunks) - // minus what we've read so far. - // $$kk: we should be able to get length for the data chunk right after - // we find "SSND." however, some aiff files give *weird* numbers. what - // is going on?? - - if (chunkLen < length) { - dataLength = chunkLen - chunkRead; - } else { - // $$kk: 11.03.98: this seems dangerous! - dataLength = length - (fileRead + chunkRead); - } ssndFound = true; break; } // switch - fileRead += chunkRead; // skip the remainder of this chunk if (!ssndFound) { int toSkip = chunkLen - chunkRead; if (toSkip > 0) { - fileRead += dis.skipBytes(toSkip); + dis.skipBytes(toSkip); } } } // while @@ -188,36 +167,12 @@ if (format == null) { throw new UnsupportedAudioFileException("missing COMM chunk"); } - AudioFileFormat.Type type = aifc?AudioFileFormat.Type.AIFC:AudioFileFormat.Type.AIFF; + Type type = aifc ? Type.AIFC : Type.AIFF; - return new AiffFileFormat(type, totallength, format, dataLength / format.getFrameSize()); + return new AiffFileFormat(type, totallength, format, frameLength); } // HELPER METHODS - /** write_ieee_extended(DataOutputStream dos, double f) throws IOException { - * Extended precision IEEE floating-point conversion routine. - * @argument DataOutputStream - * @argument double - * @return void - * @exception IOException - */ - private void write_ieee_extended(DataOutputStream dos, double f) throws IOException { - - int exponent = 16398; - double highMantissa = f; - - // For now write the integer portion of f - // $$jb: 03.30.99: stay in synch with JMF on this!!!! - while (highMantissa < 44000) { - highMantissa *= 2; - exponent--; - } - dos.writeShort(exponent); - dos.writeInt( ((int) highMantissa) << 16); - dos.writeInt(0); // low Mantissa - } - - /** * read_ieee_extended * Extended precision IEEE floating-point conversion routine. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -59,7 +59,6 @@ super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AIFF}); } - // METHODS TO IMPLEMENT AudioFileWriter @Override @@ -83,7 +82,6 @@ return new AudioFileFormat.Type[0]; } - @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException { Objects.requireNonNull(stream); @@ -102,11 +100,9 @@ throw new IOException("stream length not specified"); } - int bytesWritten = writeAiffFile(stream, aiffFileFormat, out); - return bytesWritten; + return writeAiffFile(stream, aiffFileFormat, out); } - @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException { Objects.requireNonNull(stream); @@ -129,12 +125,15 @@ // $$kk: 10.22.99: jan: please either implement this or throw an exception! // $$fb: 2001-07-13: done. Fixes Bug 4479981 - int ssndBlockSize = (aiffFileFormat.getFormat().getChannels() * aiffFileFormat.getFormat().getSampleSizeInBits()); + int channels = aiffFileFormat.getFormat().getChannels(); + int sampleSize = aiffFileFormat.getFormat().getSampleSizeInBits(); + int ssndBlockSize = channels * ((sampleSize + 7) / 8); int aiffLength=bytesWritten; int ssndChunkSize=aiffLength-aiffFileFormat.getHeaderSize()+16; long dataSize=ssndChunkSize-16; - int numFrames=(int) (dataSize*8/ssndBlockSize); + //TODO possibly incorrect round + int numFrames = (int) (dataSize / ssndBlockSize); RandomAccessFile raf=new RandomAccessFile(out, "rw"); // skip FORM magic @@ -173,12 +172,7 @@ AudioFormat streamFormat = stream.getFormat(); AudioFormat.Encoding streamEncoding = streamFormat.getEncoding(); - - float sampleRate; int sampleSizeInBits; - int channels; - int frameSize; - float frameRate; int fileSize; boolean convert8to16 = false; @@ -235,7 +229,6 @@ return fileFormat; } - private int writeAiffFile(InputStream in, AiffFileFormat aiffFileFormat, OutputStream out) throws IOException { int bytesRead = 0; @@ -275,25 +268,20 @@ AudioFormat.Encoding encoding = null; //$$fb a little bit nicer handling of constants - - //int headerSize = 54; int headerSize = aiffFileFormat.getHeaderSize(); - //int fverChunkSize = 0; int fverChunkSize = aiffFileFormat.getFverChunkSize(); - //int commChunkSize = 26; int commChunkSize = aiffFileFormat.getCommChunkSize(); int aiffLength = -1; int ssndChunkSize = -1; - //int ssndOffset = headerSize - 16; int ssndOffset = aiffFileFormat.getSsndChunkOffset(); short channels = (short) format.getChannels(); short sampleSize = (short) format.getSampleSizeInBits(); - int ssndBlockSize = (channels * sampleSize); - int numFrames = aiffFileFormat.getFrameLength(); - long dataSize = -1; + int ssndBlockSize = channels * ((sampleSize + 7) / 8); + int numFrames = aiffFileFormat.getFrameLength(); + long dataSize = -1; if( numFrames != AudioSystem.NOT_SPECIFIED) { - dataSize = (long) numFrames * ssndBlockSize / 8; + dataSize = (long) numFrames * ssndBlockSize; ssndChunkSize = (int)dataSize + 16; aiffLength = (int)dataSize+headerSize; } @@ -403,9 +391,6 @@ } - - - // HELPER METHODS private static final int DOUBLE_MANTISSA_LENGTH = 52; @@ -452,6 +437,4 @@ dos.writeShort(extendedBits79To64); dos.writeLong(extendedBits63To0); } - - } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java Mon Mar 21 11:21:08 2016 +0100 @@ -255,16 +255,17 @@ public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { - AudioFileFormat format = getAudioFileFormat(stream); + final AudioFileFormat format = getAudioFileFormat(stream); // we've got everything, the stream is supported and it is at the // beginning of the header, so find the data chunk again and return an // AudioInputStream - RIFFReader riffiterator = new RIFFReader(stream); + final RIFFReader riffiterator = new RIFFReader(stream); while (riffiterator.hasNextChunk()) { RIFFReader chunk = riffiterator.nextChunk(); if (chunk.getFormat().equals("data")) { - return new AudioInputStream(chunk, format.getFormat(), chunk - .getSize()); + final AudioFormat af = format.getFormat(); + final long length = chunk.getSize() / af.getFrameSize(); + return new AudioInputStream(chunk, af, length); } } throw new UnsupportedAudioFileException(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java Mon Mar 21 11:21:08 2016 +0100 @@ -95,16 +95,17 @@ public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { - AudioFileFormat format = getAudioFileFormat(stream); + final AudioFileFormat format = getAudioFileFormat(stream); // we've got everything, the stream is supported and it is at the // beginning of the header, so find the data chunk again and return an // AudioInputStream - RIFFReader riffiterator = new RIFFReader(stream); + final RIFFReader riffiterator = new RIFFReader(stream); while (riffiterator.hasNextChunk()) { RIFFReader chunk = riffiterator.nextChunk(); if (chunk.getFormat().equals("data")) { - return new AudioInputStream(chunk, format.getFormat(), - chunk.getSize()); + final AudioFormat af = format.getFormat(); + final long length = chunk.getSize() / af.getFrameSize(); + return new AudioInputStream(chunk, af, length); } } throw new UnsupportedAudioFileException(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java --- a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java Mon Mar 21 11:21:08 2016 +0100 @@ -231,7 +231,9 @@ // Before all the checks below we first see if it's an FTP provider or a focus cycle root. // If it's the case just go down cycle (if it's set to "implicit"). Component comp = getComponentDownCycle(aComponent, FORWARD_TRAVERSAL); - if (comp != null) { + // Check if aComponent is focus-cycle-root's default Component, i.e. + // focus cycle root & focus-cycle-root's default Component is same. + if (comp != null && comp != aComponent) { return comp; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/java/beans/EventHandler.java --- a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -526,8 +526,11 @@ * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see #create(Class, Object, String, String) + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action) @@ -584,8 +587,11 @@ * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see #create(Class, Object, String, String, String) + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action, @@ -675,8 +681,11 @@ * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see EventHandler + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action, diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java --- a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,8 @@ import java.awt.Image; import java.awt.Toolkit; -import java.io.InputStream; +import java.awt.image.ImageProducer; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; @@ -171,19 +172,24 @@ } /** - * This is a utility method to help in loading icon images. - * It takes the name of a resource file associated with the - * current object's class file and loads an image object - * from that file. Typically images will be GIFs. + * This is a utility method to help in loading icon images. It takes the + * name of a resource file associated with the current object's class file + * and loads an image object from that file. Typically images will be GIFs. * - * @param resourceName A pathname relative to the directory - * holding the class file of the current class. For example, - * "wombat.gif". - * @return an image object. May be null if the load failed. + * @param resourceName A pathname relative to the directory holding the + * class file of the current class. For example, "wombat.gif". + * @return an image object or null if the resource is not found or the + * resource could not be loaded as an Image */ public Image loadImage(final String resourceName) { - try (InputStream in = getClass().getResourceAsStream(resourceName)) { - return Toolkit.getDefaultToolkit().createImage(in.readAllBytes()); + try { + final URL url = getClass().getResource(resourceName); + if (url != null) { + final ImageProducer ip = (ImageProducer) url.getContent(); + if (ip != null) { + return Toolkit.getDefaultToolkit().createImage(ip); + } + } } catch (final Exception ignored) { } return null; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2175,9 +2175,9 @@ } /** - * Returns a shared instance of a BaselineTIFFTagSet. + * Returns a shared instance of a {@code BaselineTIFFTagSet}. * - * @return a BaselineTIFFTagSet instance. + * @return a {@code BaselineTIFFTagSet} instance. */ public synchronized static BaselineTIFFTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ /** * A value to be used with the "GPSVersionID" tag to indicate GPS version * 2.2. The value equals the US-ASCII encoding of the byte array - * {'2', '2', '0', '0'}. + * {@code {'2', '2', '0', '0'}}. * * @see #TAG_GPS_VERSION_ID */ @@ -711,9 +711,9 @@ } /** - * Returns a shared instance of an ExifGPSTagSet. + * Returns a shared instance of an {@code ExifGPSTagSet}. * - * @return an ExifGPSTagSet instance. + * @return an {@code ExifGPSTagSet} instance. */ public synchronized static ExifGPSTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,9 +88,9 @@ /** * Returns the shared instance of - * ExifInteroperabilityTagSet. + * {@code ExifInteroperabilityTagSet}. * - * @return the ExifInteroperabilityTagSet instance. + * @return the {@code ExifInteroperabilityTagSet} instance. */ public synchronized static ExifInteroperabilityTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,9 +80,9 @@ } /** - * Returns a shared instance of an ExifParentTIFFTagSet. + * Returns a shared instance of an {@code ExifParentTIFFTagSet}. * - * @return an ExifParentTIFFTagSet instance. + * @return an {@code ExifParentTIFFTagSet} instance. */ public synchronized static ExifParentTIFFTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ * standard for annotating images used by most digital camera * manufacturers. The Exif specification may be found at * - * http://www.exif.org/Exif2-2.PDF + * {@code http://www.exif.org/Exif2-2.PDF} * . * *

    The definitions of the data types referenced by the field @@ -67,7 +67,7 @@ /** * A value to be used with the "ExifVersion" tag to indicate Exif version * 2.1. The value equals the US-ASCII encoding of the byte array - * {'0', '2', '1', '0'}. + * {@code {'0', '2', '1', '0'}}. * * @see #TAG_EXIF_VERSION */ @@ -78,7 +78,7 @@ /** * A value to be used with the "ExifVersion" tag to indicate Exif version * 2.2. The value equals the US-ASCII encoding of the byte array - * {'0', '2', '2', '0'}. + * {@code {'0', '2', '2', '0'}}. * * @see #TAG_EXIF_VERSION */ @@ -94,7 +94,7 @@ /** * A tag indicating the color space information (type SHORT). The - * legal values are given by the COLOR_SPACE_* + * legal values are given by the {@code COLOR_SPACE_*} * constants. * * @see #COLOR_SPACE_SRGB @@ -1256,7 +1256,7 @@ static class ExifVersion extends TIFFTag { public ExifVersion() { - super("Exifversion", + super("ExifVersion", TAG_EXIF_VERSION, 1 << TIFFTag.TIFF_UNDEFINED, 4); @@ -1992,9 +1992,9 @@ } /** - * Returns a shared instance of an ExifTIFFTagSet. + * Returns a shared instance of an {@code ExifTIFFTagSet}. * - * @return an ExifTIFFTagSet instance. + * @return an {@code ExifTIFFTagSet} instance. */ public synchronized static ExifTIFFTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,9 +131,9 @@ } /** - * Returns a shared instance of a FaxTIFFTagSet. + * Returns a shared instance of a {@code FaxTIFFTagSet}. * - * @return a FaxTIFFTagSet instance. + * @return a {@code FaxTIFFTagSet} instance. */ public synchronized static FaxTIFFTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * standard for annotating georeferenced or geocoded raster imagery. * The GeoTIFF specification may be found at - * http://www.remotesensing.org/geotiff/spec/geotiffhome.html + * {@code http://www.remotesensing.org/geotiff/spec/geotiffhome.html} * . This class does not handle the GeoKeys referenced * from a GeoKeyDirectoryTag as those are not TIFF tags per se. * @@ -63,7 +63,7 @@ /** A tag used to store the GeoKey directory. */ public static final int TAG_GEO_KEY_DIRECTORY = 34735; - /** A tag used to store all double-values GeoKeys. */ + /** A tag used to store all {@code double}-values GeoKeys. */ public static final int TAG_GEO_DOUBLE_PARAMS = 34736; /** A tag used to store all ASCII-values GeoKeys. */ @@ -97,7 +97,7 @@ static class GeoKeyDirectory extends TIFFTag { public GeoKeyDirectory() { - super("GeoKeyDirectory", + super("GeoKeyDirectoryTag", TAG_GEO_KEY_DIRECTORY, 1 << TIFFTag.TIFF_SHORT); } @@ -105,7 +105,7 @@ static class GeoDoubleParams extends TIFFTag { public GeoDoubleParams() { - super("GeoDoubleParams", + super("GeoDoubleParamsTag", TAG_GEO_DOUBLE_PARAMS, 1 << TIFFTag.TIFF_DOUBLE); } @@ -113,7 +113,7 @@ static class GeoAsciiParams extends TIFFTag { public GeoAsciiParams() { - super("GeoAsciiParams", + super("GeoAsciiParamsTag", TAG_GEO_ASCII_PARAMS, 1 << TIFFTag.TIFF_ASCII); } @@ -137,9 +137,9 @@ } /** - * Returns a shared instance of a GeoTIFFTagSet. + * Returns a shared instance of a {@code GeoTIFFTagSet}. * - * @return a GeoTIFFTagSet instance. + * @return a {@code GeoTIFFTagSet} instance. */ public synchronized static GeoTIFFTagSet getInstance() { if (theInstance == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,58 +41,58 @@ * image metadata. A TIFF image metadata tree represents an Image File * Directory (IFD) from a TIFF 6.0 stream. An IFD consists of a number of * IFD Entries each of which associates an identifying tag number with - * a compatible value. A TIFFDirectory instance corresponds + * a compatible value. A {@code TIFFDirectory} instance corresponds * to an IFD and contains a set of {@link TIFFField}s each of which * corresponds to an IFD Entry in the IFD. * - *

    When reading, a TIFFDirectory may be created by passing + *

    When reading, a {@code TIFFDirectory} may be created by passing * the value returned by {@link javax.imageio.ImageReader#getImageMetadata * ImageReader.getImageMetadata()} to {@link #createFromMetadata * createFromMetadata()}. The {@link TIFFField}s in the directory may then * be obtained using the accessor methods provided in this class.

    * *

    When writing, an {@link IIOMetadata} object for use by one of the - * write() methods of {@link javax.imageio.ImageWriter} may be - * created from a TIFFDirectory by {@link #getAsMetadata()}. - * The TIFFDirectory itself may be created by construction or - * from the IIOMetadata object returned by + * {@code write()} methods of {@link javax.imageio.ImageWriter} may be + * created from a {@code TIFFDirectory} by {@link #getAsMetadata()}. + * The {@code TIFFDirectory} itself may be created by construction or + * from the {@code IIOMetadata} object returned by * {@link javax.imageio.ImageWriter#getDefaultImageMetadata - * ImageWriter.getDefaultImageMetadata()}. The TIFFFields in the + * ImageWriter.getDefaultImageMetadata()}. The {@code TIFFField}s in the * directory may be set using the mutator methods provided in this class.

    * - *

    A TIFFDirectory is aware of the tag numbers in the + *

    A {@code TIFFDirectory} is aware of the tag numbers in the * group of {@link TIFFTagSet}s associated with it. When - * a TIFFDirectory is created from a native image metadata + * a {@code TIFFDirectory} is created from a native image metadata * object, these tag sets are derived from the tagSets attribute * of the TIFFIFD node.

    * - *

    A TIFFDirectory might also have a parent {@link TIFFTag}. + *

    A {@code TIFFDirectory} might also have a parent {@link TIFFTag}. * This will occur if the directory represents an IFD other than the root * IFD of the image. The parent tag is the tag of the IFD Entry which is a - * pointer to the IFD represented by this TIFFDirectory. The - * {@link TIFFTag#isIFDPointer} method of this parent TIFFTag - * must return true. When a TIFFDirectory is + * pointer to the IFD represented by this {@code TIFFDirectory}. The + * {@link TIFFTag#isIFDPointer} method of this parent {@code TIFFTag} + * must return {@code true}. When a {@code TIFFDirectory} is * created from a native image metadata object, the parent tag set is set * from the parentTagName attribute of the corresponding - * TIFFIFD node. Note that a TIFFDirectory instance - * which has a non-null parent tag will be contained in the - * data field of a TIFFField instance which has a tag field + * TIFFIFD node. Note that a {@code TIFFDirectory} instance + * which has a non-{@code null} parent tag will be contained in the + * data field of a {@code TIFFField} instance which has a tag field * equal to the contained directory's parent tag.

    * - *

    As an example consider an Exif image. The TIFFDirectory + *

    As an example consider an Exif image. The {@code TIFFDirectory} * instance corresponding to the Exif IFD in the Exif stream would have parent * tag {@link ExifParentTIFFTagSet#TAG_EXIF_IFD_POINTER TAG_EXIF_IFD_POINTER} * and would include {@link ExifTIFFTagSet} in its group of known tag sets. - * The TIFFDirectory corresponding to this Exif IFD will be - * contained in the data field of a TIFFField which will in turn - * be contained in the TIFFDirectory corresponding to the primary - * IFD of the Exif image which will itself have a null-valued + * The {@code TIFFDirectory} corresponding to this Exif IFD will be + * contained in the data field of a {@code TIFFField} which will in turn + * be contained in the {@code TIFFDirectory} corresponding to the primary + * IFD of the Exif image which will itself have a {@code null}-valued * parent tag.

    * *

    Note that this implementation is not synchronized. If multiple - * threads use a TIFFDirectory instance concurrently, and at + * threads use a {@code TIFFDirectory} instance concurrently, and at * least one of the threads modifies the directory, for example, by adding - * or removing TIFFFields or TIFFTagSets, it + * or removing {@code TIFFField}s or {@code TIFFTagSet}s, it * must be synchronized externally.

    * * @since 9 @@ -107,10 +107,10 @@ private static final int MAX_LOW_FIELD_TAG_NUM = BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE; - /** The TIFFTagSets associated with this directory. */ + /** The {@code TIFFTagSets} associated with this directory. */ private List tagSets; - /** The parent TIFFTag of this directory. */ + /** The parent {@code TIFFTag} of this directory. */ private TIFFTag parentTag; /** @@ -123,13 +123,13 @@ private int numLowFields = 0; /** - * A mapping of Integer tag numbers to TIFFFields + * A mapping of {@code Integer} tag numbers to {@code TIFFField}s * for fields which are not low tag numbered. */ private Map highFields = new TreeMap(); /** - * Creates a TIFFDirectory instance from the contents of + * Creates a {@code TIFFDirectory} instance from the contents of * an image metadata object. The supplied object must support an image * metadata format supported by the TIFF {@link javax.imageio.ImageWriter} * plug-in. This will usually be either the TIFF native image metadata @@ -139,12 +139,12 @@ * @param tiffImageMetadata A metadata object which supports a compatible * image metadata format. * - * @return A TIFFDirectory populated from the contents of + * @return A {@code TIFFDirectory} populated from the contents of * the supplied metadata object. * - * @throws NullPointerException if tiffImageMetadata - * is null. - * @throws IllegalArgumentException if tiffImageMetadata + * @throws NullPointerException if {@code tiffImageMetadata} + * is {@code null}. + * @throws IllegalArgumentException if {@code tiffImageMetadata} * does not support a compatible image metadata format. * @throws IIOInvalidTreeException if the supplied metadata object * cannot be parsed. @@ -204,7 +204,7 @@ } /** - * Converts a TIFFDirectory to a TIFFIFD. + * Converts a {@code TIFFDirectory} to a {@code TIFFIFD}. */ private static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) { if(dir instanceof TIFFIFD) { @@ -219,27 +219,39 @@ TIFFField f = fields[i]; TIFFTag tag = f.getTag(); if(tag.isIFDPointer()) { - TIFFDirectory subIFD = - getDirectoryAsIFD((TIFFDirectory)f.getData()); - f = new TIFFField(tag, f.getType(), (long)f.getCount(), subIFD); + TIFFDirectory subDir = null; + if (f.hasDirectory()) { + subDir = f.getDirectory(); + } else if (f.getData() instanceof TIFFDirectory) { + subDir = (TIFFDirectory)f.getData(); + } + if (subDir != null) { + TIFFDirectory subIFD = getDirectoryAsIFD(subDir); + f = new TIFFField(tag, f.getType(), (long)f.getCount(), + subIFD); + } else { + f = null; + } } - ifd.addTIFFField(f); + if (f != null) { + ifd.addTIFFField(f); + } } return ifd; } /** - * Constructs a TIFFDirectory which is aware of a given + * Constructs a {@code TIFFDirectory} which is aware of a given * group of {@link TIFFTagSet}s. An optional parent {@link TIFFTag} * may also be specified. * - * @param tagSets The TIFFTagSets associated with this + * @param tagSets The {@code TIFFTagSets} associated with this * directory. - * @param parentTag The parent TIFFTag of this directory; - * may be null. - * @throws NullPointerException if tagSets is - * null. + * @param parentTag The parent {@code TIFFTag} of this directory; + * may be {@code null}. + * @throws NullPointerException if {@code tagSets} is + * {@code null}. */ public TIFFDirectory(TIFFTagSet[] tagSets, TIFFTag parentTag) { if(tagSets == null) { @@ -256,8 +268,8 @@ /** * Returns the {@link TIFFTagSet}s of which this directory is aware. * - * @return The TIFFTagSets associated with this - * TIFFDirectory. + * @return The {@code TIFFTagSet}s associated with this + * {@code TIFFDirectory}. */ public TIFFTagSet[] getTagSets() { return tagSets.toArray(new TIFFTagSet[tagSets.size()]); @@ -267,9 +279,9 @@ * Adds an element to the group of {@link TIFFTagSet}s of which this * directory is aware. * - * @param tagSet The TIFFTagSet to add. - * @throws NullPointerException if tagSet is - * null. + * @param tagSet The {@code TIFFTagSet} to add. + * @throws NullPointerException if {@code tagSet} is + * {@code null}. */ public void addTagSet(TIFFTagSet tagSet) { if(tagSet == null) { @@ -285,9 +297,9 @@ * Removes an element from the group of {@link TIFFTagSet}s of which this * directory is aware. * - * @param tagSet The TIFFTagSet to remove. - * @throws NullPointerException if tagSet is - * null. + * @param tagSet The {@code TIFFTagSet} to remove. + * @throws NullPointerException if {@code tagSet} is + * {@code null}. */ public void removeTagSet(TIFFTagSet tagSet) { if(tagSet == null) { @@ -301,10 +313,10 @@ /** * Returns the parent {@link TIFFTag} of this directory if one - * has been defined or null otherwise. + * has been defined or {@code null} otherwise. * - * @return The parent TIFFTag of this - * TIFFDiectory or null. + * @return The parent {@code TIFFTag} of this + * {@code TIFFDiectory} or {@code null}. */ public TIFFTag getParentTag() { return parentTag; @@ -312,12 +324,12 @@ /** * Returns the {@link TIFFTag} which has tag number equal to - * tagNumber or null if no such tag + * {@code tagNumber} or {@code null} if no such tag * exists in the {@link TIFFTagSet}s associated with this * directory. * * @param tagNumber The tag number of interest. - * @return The corresponding TIFFTag or null. + * @return The corresponding {@code TIFFTag} or {@code null}. */ public TIFFTag getTag(int tagNumber) { return TIFFIFD.getTag(tagNumber, tagSets); @@ -326,8 +338,8 @@ /** * Returns the number of {@link TIFFField}s in this directory. * - * @return The number of TIFFFields in this - * TIFFDirectory. + * @return The number of {@code TIFFField}s in this + * {@code TIFFDirectory}. */ public int getNumTIFFFields() { return numLowFields + highFields.size(); @@ -339,7 +351,7 @@ * * @param tagNumber The tag number. * @return Whether a {@link TIFFTag} with tag number equal to - * tagNumber is present in this TIFFDirectory. + * {@code tagNumber} is present in this {@code TIFFDirectory}. */ public boolean containsTIFFField(int tagNumber) { return (tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM && @@ -351,7 +363,7 @@ * Adds a TIFF field to the directory. * * @param f The field to add. - * @throws NullPointerException if f is null. + * @throws NullPointerException if {@code f} is {@code null}. */ public void addTIFFField(TIFFField f) { if(f == null) { @@ -372,8 +384,8 @@ * Retrieves a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. - * @return A TIFFField with the requested tag number of - * null if no such field is present. + * @return A {@code TIFFField} with the requested tag number of + * {@code null} if no such field is present. */ public TIFFField getTIFFField(int tagNumber) { TIFFField f; @@ -444,7 +456,7 @@ * Converts the directory to a metadata object. * * @return A metadata instance initialized from the contents of this - * TIFFDirectory. + * {@code TIFFDirectory}. */ public IIOMetadata getAsMetadata() { return new TIFFImageMetadata(getDirectoryAsIFD(this)); @@ -453,7 +465,7 @@ /** * Clones the directory and all the fields contained therein. * - * @return A clone of this TIFFDirectory. + * @return A clone of this {@code TIFFDirectory}. * @throws CloneNotSupportedException if the instance cannot be cloned. */ @Override diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ * *

    A field in a TIFF Image File Directory (IFD) is defined as a * tag number accompanied by a sequence of values of identical data type. - * TIFF 6.0 defines 12 data types; a 13th type IFD is + * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These * TIFF data types are referred to by Java constants and mapped internally * onto Java language data types and type names as follows: @@ -68,10 +68,10 @@ * {@link TIFFTag#TIFF_BYTE} * * - * byte + * {@code byte} * * - * "Byte" + * {@code "Byte"} * * * @@ -83,10 +83,10 @@ * {@link TIFFTag#TIFF_ASCII} * * - * String + * {@code String} * * - * "Ascii" + * {@code "Ascii"} * * * @@ -98,10 +98,10 @@ * {@link TIFFTag#TIFF_SHORT} * * - * char + * {@code char} * * - * "Short" + * {@code "Short"} * * * @@ -113,10 +113,10 @@ * {@link TIFFTag#TIFF_LONG} * * - * long + * {@code long} * * - * "Long" + * {@code "Long"} * * * @@ -128,10 +128,10 @@ * {@link TIFFTag#TIFF_RATIONAL} * * - * long[2] {numerator, denominator} + * {@code long[2]} {numerator, denominator} * * - * "Rational" + * {@code "Rational"} * * * @@ -143,10 +143,10 @@ * {@link TIFFTag#TIFF_SBYTE} * * - * byte + * {@code byte} * * - * "SByte" + * {@code "SByte"} * * * @@ -158,10 +158,10 @@ * {@link TIFFTag#TIFF_UNDEFINED} * * - * byte + * {@code byte} * * - * "Undefined" + * {@code "Undefined"} * * * @@ -173,10 +173,10 @@ * {@link TIFFTag#TIFF_SSHORT} * * - * short + * {@code short} * * - * "SShort" + * {@code "SShort"} * * * @@ -188,10 +188,10 @@ * {@link TIFFTag#TIFF_SLONG} * * - * int + * {@code int} * * - * "SLong" + * {@code "SLong"} * * * @@ -203,10 +203,10 @@ * {@link TIFFTag#TIFF_SRATIONAL} * * - * int[2] {numerator, denominator} + * {@code int[2]} {numerator, denominator} * * - * "SRational" + * {@code "SRational"} * * * @@ -218,10 +218,10 @@ * {@link TIFFTag#TIFF_FLOAT} * * - * float + * {@code float} * * - * "Float" + * {@code "Float"} * * * @@ -233,10 +233,10 @@ * {@link TIFFTag#TIFF_DOUBLE} * * - * double + * {@code double} * * - * "Double" + * {@code "Double"} * * * @@ -248,10 +248,10 @@ * {@link TIFFTag#TIFF_IFD_POINTER} * * - * long + * {@code long} * * - * "IFDPointer" + * {@code "IFDPointer"} * * * @@ -411,19 +411,19 @@ } /** - * Creates a TIFFField from a TIFF native image + * Creates a {@code TIFFField} from a TIFF native image * metadata node. If the value of the "tagNumber" attribute - * of the node is not found in tagSet then a new - * TIFFTag with name TIFFTag.UNKNOWN_TAG_NAME + * of the node is not found in {@code tagSet} then a new + * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME} * will be created and assigned to the field. * - * @param tagSet The TIFFTagSet to which the - * TIFFTag of the field belongs. - * @param node A native TIFF image metadata TIFFField node. - * @throws NullPointerException if node is - * null. + * @param tagSet The {@code TIFFTagSet} to which the + * {@code TIFFTag} of the field belongs. + * @param node A native TIFF image metadata {@code TIFFField} node. + * @throws NullPointerException if {@code node} is + * {@code null}. * @throws IllegalArgumentException if the name of the node is not - * "TIFFField". + * {@code "TIFFField"}. * @return A new {@code TIFFField}. */ public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, @@ -487,14 +487,14 @@ } /** - * Constructs a TIFFField with arbitrary data. The - * type parameter must be a value for which + * Constructs a {@code TIFFField} with arbitrary data. The + * {@code type} parameter must be a value for which * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()} - * returns true. The data parameter must + * returns {@code true}. The {@code data} parameter must * be an array of a Java type appropriate for the type of the TIFF * field. * - *

    Note that the value (data) of the TIFFField + *

    Note that the value (data) of the {@code TIFFField} * will always be the actual field value regardless of the number of * bytes required for that value. This is the case despite the fact * that the TIFF IFD Entry corresponding to the field may @@ -503,24 +503,29 @@ * value fits into 4 bytes). In other words, the value of the * field will already have been read from the TIFF stream. (An exception * to this case may occur when the field represents the contents of a - * non-baseline IFD. In that case the data will be a long[] - * containing the offset to the IFD and the TIFFDirectory + * non-baseline IFD. In that case the data will be a {@code long[]} + * containing the offset to the IFD and the {@code TIFFDirectory} * returned by {@link #getDirectory()} will be its contents.) * * @param tag The tag to associated with this field. - * @param type One of the TIFFTag.TIFF_* constants + * @param type One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. * @param data The actual data content of the field. * - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if count < 0. - * @throws NullPointerException if data == null. - * @throws IllegalArgumentException if data is an instance of + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code count < 0}. + * @throws IllegalArgumentException if {@code count < 1} + * and {@code type} is {@code TIFF_RATIONAL} or + * {@code TIFF_SRATIONAL}. + * @throws IllegalArgumentException if {@code count ≠ 1} + * and {@code type} is {@code TIFF_IFD_POINTER}. + * @throws NullPointerException if {@code data == null}. + * @throws IllegalArgumentException if {@code data} is an instance of * a class incompatible with the specified type. * @throws IllegalArgumentException if the size of the data array is wrong. */ @@ -534,6 +539,14 @@ + " for " + tag.getName() + " tag"); } else if(count < 0) { throw new IllegalArgumentException("count < 0!"); + } else if((type == TIFFTag.TIFF_RATIONAL + || type == TIFFTag.TIFF_SRATIONAL) + && count < 1) { + throw new IllegalArgumentException + ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); + } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) { + throw new IllegalArgumentException + ("Type is TIFF_IFD_POINTER count != 1"); } else if(data == null) { throw new NullPointerException("data == null!"); } @@ -612,15 +625,15 @@ * parameters and the created array. * * @param tag The tag to associated with this field. - * @param type One of the TIFFTag.TIFF_* constants + * @param type One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if count < 0. + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code count < 0}. * @see #TIFFField(TIFFTag,int,int,Object) */ public TIFFField(TIFFTag tag, int type, int count) { @@ -628,20 +641,20 @@ } /** - * Constructs a TIFFField with a single non-negative integral + * Constructs a {@code TIFFField} with a single non-negative integral * value. * The field will have type * {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if - * val < 65536 and type + * {@code val < 65536} and type * {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. The count * of the field will be unity. * * @param tag The tag to associate with this field. * @param value The value to associate with this field. - * @throws NullPointerException if tag == null. + * @throws NullPointerException if {@code tag == null}. * @throws IllegalArgumentException if the derived type is unacceptable - * for the supplied TIFFTag. - * @throws IllegalArgumentException if value < 0. + * for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code value < 0}. */ public TIFFField(TIFFTag tag, int value) { if(tag == null) { @@ -677,24 +690,24 @@ } /** - * Constructs a TIFFField with an IFD offset and contents. + * Constructs a {@code TIFFField} with an IFD offset and contents. * The offset will be stored as the data of this field as - * long[] {offset}. The directory will not be cloned. The count + * {@code long[] {offset}}. The directory will not be cloned. The count * of the field will be unity. * * @param tag The tag to associated with this field. - * @param type One of the constants TIFFTag.TIFF_LONG or - * TIFFTag.TIFF_IFD_POINTER. + * @param type One of the constants {@code TIFFTag.TIFF_LONG} or + * {@code TIFFTag.TIFF_IFD_POINTER}. * @param offset The IFD offset. * @param dir The directory. * - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is neither - * TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if offset is non-positive. - * @throws NullPointerException if dir == null. + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is neither + * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code offset} is non-positive. + * @throws NullPointerException if {@code dir == null}. * * @see #TIFFField(TIFFTag,int,int,Object) */ @@ -715,14 +728,14 @@ /** * Retrieves the tag associated with this field. * - * @return The associated TIFFTag. + * @return The associated {@code TIFFTag}. */ public TIFFTag getTag() { return tag; } /** - * Retrieves the tag number in the range [0, 65535]. + * Retrieves the tag number in the range {@code [0, 65535]}. * * @return The tag number. */ @@ -732,7 +745,7 @@ /** * Returns the type of the data stored in the field. For a TIFF 6.0 - * stream, the value will equal one of the TIFFTag.TIFF_* + * stream, the value will equal one of the {@code TIFFTag.TIFF_*} * constants. For future revisions of TIFF, higher values are possible. * * @return The data type of the field value. @@ -744,11 +757,11 @@ /** * Returns the name of the supplied data type constant. * - * @param dataType One of the TIFFTag.TIFF_* constants + * @param dataType One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @return The type name corresponding to the supplied type constant. - * @throws IllegalArgumentException if dataType is not - * one of the TIFFTag.TIFF_* data type constants. + * @throws IllegalArgumentException if {@code dataType} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. */ public static String getTypeName(int dataType) { if (dataType < TIFFTag.MIN_DATATYPE || @@ -761,11 +774,11 @@ /** * Returns the data type constant corresponding to the supplied data - * type name. If the name is unknown -1 will be returned. + * type name. If the name is unknown {@code -1} will be returned. * * @param typeName The type name. - * @return One of the TIFFTag.TIFF_* constants or - * -1 if the name is not recognized. + * @return One of the {@code TIFFTag.TIFF_*} constants or + * {@code -1} if the name is not recognized. */ public static int getTypeByName(String typeName) { for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { @@ -780,14 +793,14 @@ /** * Creates an array appropriate for the indicated data type. * - * @param dataType One of the TIFFTag.TIFF_* data type + * @param dataType One of the {@code TIFFTag.TIFF_*} data type * constants. * @param count The number of values in the array. * @return An array appropriate for the specified data type. * - * @throws IllegalArgumentException if dataType is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if count < 0. + * @throws IllegalArgumentException if {@code dataType} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code count < 0}. */ public static Object createArrayForType(int dataType, int count) { if(count < 0) { @@ -823,15 +836,15 @@ } /** - * Returns the TIFFField as a node named either + * Returns the {@code TIFFField} as a node named either * "TIFFField" or "TIFFIFD" as described in the * TIFF native image metadata specification. The node will be named * "TIFFIFD" if and only if the field's data object is an * instance of {@link TIFFDirectory} or equivalently * {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns - * true. + * {@code true}. * - * @return a Node named "TIFFField" or + * @return a {@code Node} named "TIFFField" or * "TIFFIFD". */ public Node getAsNativeNode() { @@ -850,8 +863,8 @@ /** * Returns the number of data items present in the field. For - * TIFFTag.TIFF_ASCII fields, the value returned is the - * number of Strings, not the total length of the + * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the + * number of {@code String}s, not the total length of the * data as in the file representation. * * @return The number of data items present in the field. @@ -871,17 +884,17 @@ /** * Returns the data as an uninterpreted array of - * bytes. The type of the field must be one of - * TIFFTag.TIFF_BYTE, TIFF_SBYTE, or - * TIFF_UNDEFINED. + * {@code byte}s. The type of the field must be one of + * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or + * {@code TIFF_UNDEFINED}. * - *

    For data in TIFFTag.TIFF_BYTE format, the application + *

    For data in {@code TIFFTag.TIFF_BYTE} format, the application * must take care when promoting the data to longer integral types * to avoid sign extension. * * @throws ClassCastException if the field is not of type - * TIFF_BYTE, TIFF_SBYTE, or - * TIFF_UNDEFINED. + * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or + * {@code TIFF_UNDEFINED}. * @return The data as an uninterpreted array of bytes. */ public byte[] getAsBytes() { @@ -889,11 +902,11 @@ } /** - * Returns TIFFTag.TIFF_SHORT data as an array of - * chars (unsigned 16-bit integers). + * Returns {@code TIFFTag.TIFF_SHORT} data as an array of + * {@code char}s (unsigned 16-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SHORT. + * {@code TIFF_SHORT}. * @return The data as an array of {@code char}s. */ public char[] getAsChars() { @@ -901,11 +914,11 @@ } /** - * Returns TIFFTag.TIFF_SSHORT data as an array of - * shorts (signed 16-bit integers). + * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of + * {@code short}s (signed 16-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SSHORT. + * {@code TIFF_SSHORT}. * @return The data as an array of {@code short}s. */ public short[] getAsShorts() { @@ -913,12 +926,12 @@ } /** - * Returns TIFFTag.TIFF_SLONG data as an array of - * ints (signed 32-bit integers). + * Returns {@code TIFFTag.TIFF_SLONG} data as an array of + * {@code int}s (signed 32-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SHORT, TIFF_SSHORT, or - * TIFF_SLONG. + * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or + * {@code TIFF_SLONG}. * @return The data as an array of {@code int}s. */ public int[] getAsInts() { @@ -944,12 +957,12 @@ } /** - * Returns TIFFTag.TIFF_LONG or - * TIFF_IFD_POINTER data as an array of - * longs (signed 64-bit integers). + * Returns {@code TIFFTag.TIFF_LONG} or + * {@code TIFF_IFD_POINTER} data as an array of + * {@code long}s (signed 64-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_LONG or TIFF_IFD_POINTER. + * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}. * @return The data as an array of {@code long}s. */ public long[] getAsLongs() { @@ -957,11 +970,11 @@ } /** - * Returns TIFFTag.TIFF_FLOAT data as an array of - * floats (32-bit floating-point values). + * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of + * {@code float}s (32-bit floating-point values). * * @throws ClassCastException if the field is not of type - * TIFF_FLOAT. + * {@code TIFF_FLOAT}. * @return The data as an array of {@code float}s. */ public float[] getAsFloats() { @@ -969,11 +982,11 @@ } /** - * Returns TIFFTag.TIFF_DOUBLE data as an array of - * doubles (64-bit floating-point values). + * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of + * {@code double}s (64-bit floating-point values). * * @throws ClassCastException if the field is not of type - * TIFF_DOUBLE. + * {@code TIFF_DOUBLE}. * @return The data as an array of {@code double}s. */ public double[] getAsDoubles() { @@ -981,11 +994,11 @@ } /** - * Returns TIFFTag.TIFF_SRATIONAL data as an array of - * 2-element arrays of ints. + * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of + * 2-element arrays of {@code int}s. * * @throws ClassCastException if the field is not of type - * TIFF_SRATIONAL. + * {@code TIFF_SRATIONAL}. * @return The data as an array of signed rationals. */ public int[][] getAsSRationals() { @@ -993,11 +1006,11 @@ } /** - * Returns TIFFTag.TIFF_RATIONAL data as an array of - * 2-element arrays of longs. + * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of + * 2-element arrays of {@code long}s. * * @throws ClassCastException if the field is not of type - * TIFF_RATIONAL. + * {@code TIFF_RATIONAL}. * @return The data as an array of unsigned rationals. */ public long[][] getAsRationals() { @@ -1005,30 +1018,30 @@ } /** - * Returns data in any format as an int. + * Returns data in any format as an {@code int}. * - *

    TIFFTag.TIFF_BYTE values are treated as unsigned; that + *

    {@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that * is, no sign extension will take place and the returned value - * will be in the range [0, 255]. TIFF_SBYTE data + * will be in the range [0, 255]. {@code TIFF_SBYTE} data * will be returned in the range [-128, 127]. * - *

    A TIFF_UNDEFINED value is treated as though - * it were a TIFF_BYTE. + *

    A {@code TIFF_UNDEFINED} value is treated as though + * it were a {@code TIFF_BYTE}. * - *

    Data in TIFF_SLONG, TIFF_LONG, - * TIFF_FLOAT, TIFF_DOUBLE or - * TIFF_IFD_POINTER format are simply cast to - * int and may suffer from truncation. + *

    Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, + * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or + * {@code TIFF_IFD_POINTER} format are simply cast to + * {@code int} and may suffer from truncation. * - *

    Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

    Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision - * arithmetic and then casting to int. Loss of + * arithmetic and then casting to {@code int}. Loss of * precision and truncation may occur. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * case to int. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * case to {@code int}. * * @param index The index of the data. * @return The data at the given index as an {@code int}. @@ -1068,17 +1081,17 @@ } /** - * Returns data in any format as a long. + * Returns data in any format as a {@code long}. * - *

    TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

    {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * cast to long. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * cast to {@code long}. * * @param index The index of the data. * @return The data at the given index as a {@code long}. @@ -1114,27 +1127,27 @@ } /** - * Returns data in any format as a float. + * Returns data in any format as a {@code float}. * - *

    TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

    {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

    Data in TIFF_SLONG, TIFF_LONG, - * TIFF_DOUBLE, or TIFF_IFD_POINTER format are - * simply cast to float and may suffer from + *

    Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, + * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are + * simply cast to {@code float} and may suffer from * truncation. * - *

    Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

    Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision - * arithmetic and then casting to float. + * arithmetic and then casting to {@code float}. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * cast to float. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * cast to {@code float}. * * @param index The index of the data. * @return The data at the given index as a {@code float}. @@ -1174,21 +1187,21 @@ } /** - * Returns data in any format as a double. + * Returns data in any format as a {@code double}. * - *

    TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

    {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

    Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

    Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision * arithmetic. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method. * * @param index The index of the data. * @return The data at the given index as a {@code double}. @@ -1228,11 +1241,11 @@ } /** - * Returns a TIFFTag.TIFF_ASCII value as a - * String. + * Returns a {@code TIFFTag.TIFF_ASCII} value as a + * {@code String}. * * @throws ClassCastException if the field is not of type - * TIFF_ASCII. + * {@code TIFF_ASCII}. * * @param index The index of the data. * @return The data at the given index as a {@code String}. @@ -1242,13 +1255,13 @@ } /** - * Returns a TIFFTag.TIFF_SRATIONAL data item as a - * two-element array of ints. + * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a + * two-element array of {@code int}s. * * @param index The index of the data. * @return The data at the given index as a signed rational. * @throws ClassCastException if the field is not of type - * TIFF_SRATIONAL. + * {@code TIFF_SRATIONAL}. */ public int[] getAsSRational(int index) { return ((int[][])data)[index]; @@ -1261,7 +1274,7 @@ * @param index The index of the data. * @return The data at the given index as an unsigned rational. * @throws ClassCastException if the field is not of type - * TIFF_RATIONAL. + * {@code TIFF_RATIONAL}. */ public long[] getAsRational(int index) { return ((long[][])data)[index]; @@ -1269,11 +1282,11 @@ /** - * Returns a String containing a human-readable + * Returns a {@code String} containing a human-readable * version of the data item. Data of type - * TIFFTag.TIFF_RATIONAL or TIFF_SRATIONAL are + * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are * represented as a pair of integers separated by a - * '/' character. + * {@code '/'} character. * * @param index The index of the data. * @return The data at the given index as a {@code String}. @@ -1342,7 +1355,7 @@ } /** - * Returns whether the field has a TIFFDirectory. + * Returns whether the field has a {@code TIFFDirectory}. * * @return true if and only if getDirectory() returns non-null. */ @@ -1351,8 +1364,8 @@ } /** - * Returns the associated TIFFDirectory, if available. If no - * directory is set, then null will be returned. + * Returns the associated {@code TIFFDirectory}, if available. If no + * directory is set, then {@code null} will be returned. * * @return the TIFFDirectory instance or null. */ @@ -1363,7 +1376,7 @@ /** * Clones the field and all the information contained therein. * - * @return A clone of this TIFFField. + * @return A clone of this {@code TIFFField}. * @throws CloneNotSupportedException if the instance cannot be cloned. */ @Override diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,11 +39,11 @@ * be provided by this interface. * *

    Additional TIFF tags must be organized into - * TIFFTagSets. A TIFFTagSet may be + * {@code TIFFTagSet}s. A {@code TIFFTagSet} may be * provided to the reader by means of the - * addAllowedTagSet method. By default, the tag sets - * BaselineTIFFTagSet, FaxTIFFTagSet, - * ExifParentTIFFTagSet, and GeoTIFFTagSet + * {@code addAllowedTagSet} method. By default, the tag sets + * {@code BaselineTIFFTagSet}, {@code FaxTIFFTagSet}, + * {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet} * are included. * * @since 9 @@ -53,10 +53,10 @@ private List allowedTagSets = new ArrayList(4); /** - * Constructs a TIFFImageReadParam. Tags defined by - * the TIFFTagSets BaselineTIFFTagSet, - * FaxTIFFTagSet, ExifParentTIFFTagSet, and - * GeoTIFFTagSet will be supported. + * Constructs a {@code TIFFImageReadParam}. Tags defined by + * the {@code TIFFTagSet}s {@code BaselineTIFFTagSet}, + * {@code FaxTIFFTagSet}, {@code ExifParentTIFFTagSet}, and + * {@code GeoTIFFTagSet} will be supported. * * @see BaselineTIFFTagSet * @see FaxTIFFTagSet @@ -71,13 +71,13 @@ } /** - * Adds a TIFFTagSet object to the list of allowed + * Adds a {@code TIFFTagSet} object to the list of allowed * tag sets. * - * @param tagSet a TIFFTagSet. + * @param tagSet a {@code TIFFTagSet}. * - * @throws IllegalArgumentException if tagSet is - * null. + * @throws IllegalArgumentException if {@code tagSet} is + * {@code null}. */ public void addAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { @@ -87,15 +87,15 @@ } /** - * Removes a TIFFTagSet object from the list of - * allowed tag sets. Removal is based on the equals - * method of the TIFFTagSet, which is normally + * Removes a {@code TIFFTagSet} object from the list of + * allowed tag sets. Removal is based on the {@code equals} + * method of the {@code TIFFTagSet}, which is normally * defined as reference equality. * - * @param tagSet a TIFFTagSet. + * @param tagSet a {@code TIFFTagSet}. * - * @throws IllegalArgumentException if tagSet is - * null. + * @throws IllegalArgumentException if {@code tagSet} is + * {@code null}. */ public void removeAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { @@ -105,10 +105,10 @@ } /** - * Returns a List containing the allowed - * TIFFTagSet objects. + * Returns a {@code List} containing the allowed + * {@code TIFFTagSet} objects. * - * @return a List of TIFFTagSets. + * @return a {@code List} of {@code TIFFTagSet}s. */ public List getAllowedTagSets() { return allowedTagSets; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ * The name assigned to a tag with an unknown tag number. Such * a tag may be created for example when reading an IFD and a * tag number is encountered which is not in any of the - * TIFFTagSets known to the reader. + * {@code TIFFTagSet}s known to the reader. */ public static final String UNKNOWN_TAG_NAME = "UnknownTag"; @@ -141,12 +141,12 @@ private SortedMap valueNames = null; /** - * Constructs a TIFFTag with a given name, tag number, set + * Constructs a {@code TIFFTag} with a given name, tag number, set * of legal data types, and value count. A negative value count signifies * that either an arbitrary number of values is legal or the required count * is determined by the values of other fields in the IFD. A non-negative * count specifies the number of values which an associated field must - * contain. The tag will have no associated TIFFTagSet. + * contain. The tag will have no associated {@code TIFFTagSet}. * *

    If there are mnemonic names to be associated with the legal * data values for the tag, {@link #addValueName(int, String) @@ -183,18 +183,18 @@ } /** - * Constructs a TIFFTag with a given name, tag number and - * TIFFTagSet to which it refers. The legal data types are + * Constructs a {@code TIFFTag} with a given name, tag number and + * {@code TIFFTagSet} to which it refers. The legal data types are * set to include {@link #TIFF_LONG} and {@link #TIFF_IFD_POINTER} and the - * value count is unity. The TIFFTagSet will - * represent the set of TIFFTags which appear in the IFD - * pointed to. A TIFFTag represents an IFD pointer if and - * only if tagSet is non-null or the data - * type TIFF_IFD_POINTER is legal. + * value count is unity. The {@code TIFFTagSet} will + * represent the set of {@code TIFFTag}s which appear in the IFD + * pointed to. A {@code TIFFTag} represents an IFD pointer if and + * only if {@code tagSet} is non-{@code null} or the data + * type {@code TIFF_IFD_POINTER} is legal. * * @param name the name of the tag. * @param number the number used to represent the tag. - * @param tagSet the TIFFTagSet to which this tag belongs. + * @param tagSet the {@code TIFFTagSet} to which this tag belongs. * @throws NullPointerException if name or tagSet is null. * @throws IllegalArgumentException if number is negative. * @@ -210,9 +210,9 @@ } /** - * Constructs a TIFFTag with a given name, tag number, + * Constructs a {@code TIFFTag} with a given name, tag number, * and set of legal data types. The value count of the tag will be - * undefined and it will have no associated TIFFTagSet. + * undefined and it will have no associated {@code TIFFTagSet}. * * @param name the name of the tag. * @param number the number used to represent the tag. @@ -236,9 +236,9 @@ * * @return the number of bytes used to store the given data type. * - * @throws IllegalArgumentException if datatype is - * less than MIN_DATATYPE or greater than - * MAX_DATATYPE. + * @throws IllegalArgumentException if {@code datatype} is + * less than {@code MIN_DATATYPE} or greater than + * {@code MAX_DATATYPE}. */ public static int getSizeOfType(int dataType) { if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) { @@ -251,7 +251,7 @@ /** * Returns the name of the tag, as it will appear in image metadata. * - * @return the tag name, as a String. + * @return the tag name, as a {@code String}. */ public String getName() { return name; @@ -260,7 +260,7 @@ /** * Returns the integer used to represent the tag. * - * @return the tag number, as an int. + * @return the tag number, as an {@code int}. */ public int getNumber() { return number; @@ -276,7 +276,7 @@ * (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG) * * - * @return an int containing a bitmask encoding the + * @return an {@code int} containing a bitmask encoding the * set of valid data types. */ public int getDataTypes() { @@ -285,11 +285,11 @@ /** * Returns the value count of this tag. If this value is positive, it - * represents the required number of values for a TIFFField + * represents the required number of values for a {@code TIFFField} * which has this tag. If the value is negative, the count is undefined. * In the latter case the count may be derived, e.g., the number of values - * of the BitsPerSample field is SamplesPerPixel, - * or it may be variable as in the case of most US-ASCII + * of the {@code BitsPerSample} field is {@code SamplesPerPixel}, + * or it may be variable as in the case of most {@code US-ASCII} * fields. * * @return the value count of this tag. @@ -299,18 +299,18 @@ } /** - * Returns true if the given data type + * Returns {@code true} if the given data type * may be used for the data associated with this tag. * * @param dataType the data type to be queried, one of - * TIFF_BYTE, TIFF_SHORT, etc. + * {@code TIFF_BYTE}, {@code TIFF_SHORT}, etc. * - * @return a boolean indicating whether the given + * @return a {@code boolean} indicating whether the given * data type may be used with this tag. * - * @throws IllegalArgumentException if datatype is - * less than MIN_DATATYPE or greater than - * MAX_DATATYPE. + * @throws IllegalArgumentException if {@code datatype} is + * less than {@code MIN_DATATYPE} or greater than + * {@code MAX_DATATYPE}. */ public boolean isDataTypeOK(int dataType) { if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) { @@ -320,38 +320,38 @@ } /** - * Returns the TIFFTagSet of which this tag is a part. + * Returns the {@code TIFFTagSet} of which this tag is a part. * - * @return the containing TIFFTagSet. + * @return the containing {@code TIFFTagSet}. */ public TIFFTagSet getTagSet() { return tagSet; } /** - * Returns true if this tag is used to point to an IFD - * structure containing additional tags. A TIFFTag represents - * an IFD pointer if and only if its TIFFTagSet is - * non-null or the data type TIFF_IFD_POINTER is + * Returns {@code true} if this tag is used to point to an IFD + * structure containing additional tags. A {@code TIFFTag} represents + * an IFD pointer if and only if its {@code TIFFTagSet} is + * non-{@code null} or the data type {@code TIFF_IFD_POINTER} is * legal. This condition will be satisfied if and only if either - * getTagSet() != null or - * isDataTypeOK(TIFF_IFD_POINTER) == true. + * {@code getTagSet() != null} or + * {@code isDataTypeOK(TIFF_IFD_POINTER) == true}. * *

    Many TIFF extensions use the IFD mechanism in order to limit the * number of new tags that may appear in the root IFD.

    * - * @return true if this tag points to an IFD. + * @return {@code true} if this tag points to an IFD. */ public boolean isIFDPointer() { return tagSet != null || isDataTypeOK(TIFF_IFD_POINTER); } /** - * Returns true if there are mnemonic names associated with + * Returns {@code true} if there are mnemonic names associated with * the set of legal values for the data associated with this tag. Mnemonic * names apply only to tags which have integral data type. * - * @return true if mnemonic value names are available. + * @return {@code true} if mnemonic value names are available. */ public boolean hasValueNames() { return valueNames != null; @@ -373,14 +373,14 @@ /** * Returns the mnemonic name associated with a particular value - * that this tag's data may take on, or null if + * that this tag's data may take on, or {@code null} if * no name is present. Mnemonic names apply only to tags which have * integral data type. * * @param value the data value. * * @return the mnemonic name associated with the value, as a - * String. + * {@code String}. */ public String getValueName(int value) { if (valueNames == null) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ * specification itself). * *

    This class and its subclasses are responsible for mapping - * between raw tag numbers and TIFFTag objects, which + * between raw tag numbers and {@code TIFFTag} objects, which * contain additional information about each tag, such as the tag's * name, legal data types, and mnemonic names for some or all of ts * data values. @@ -59,15 +59,15 @@ private TIFFTagSet() {} /** - * Constructs a TIFFTagSet, given a List - * of TIFFTag objects. + * Constructs a {@code TIFFTagSet}, given a {@code List} + * of {@code TIFFTag} objects. * - * @param tags a List object containing - * TIFFTag objects to be added to this tag set. + * @param tags a {@code List} object containing + * {@code TIFFTag} objects to be added to this tag set. * - * @throws IllegalArgumentException if tags is - * null, or contains objects that are not instances - * of the TIFFTag class. + * @throws IllegalArgumentException if {@code tags} is + * {@code null}, or contains objects that are not instances + * of the {@code TIFFTag} class. */ public TIFFTagSet(List tags) { if (tags == null) { @@ -88,29 +88,29 @@ } /** - * Returns the TIFFTag from this set that is - * associated with the given tag number, or null if + * Returns the {@code TIFFTag} from this set that is + * associated with the given tag number, or {@code null} if * no tag exists for that number. * * @param tagNumber the number of the tag to be retrieved. * - * @return the numbered TIFFTag, or null. + * @return the numbered {@code TIFFTag}, or {@code null}. */ public TIFFTag getTag(int tagNumber) { return allowedTagsByNumber.get(Integer.valueOf(tagNumber)); } /** - * Returns the TIFFTag having the given tag name, or - * null if the named tag does not belong to this tag set. + * Returns the {@code TIFFTag} having the given tag name, or + * {@code null} if the named tag does not belong to this tag set. * * @param tagName the name of the tag to be retrieved, as a - * String. + * {@code String}. * - * @return the named TIFFTag, or null. + * @return the named {@code TIFFTag}, or {@code null}. * - * @throws IllegalArgumentException if tagName is - * null. + * @throws IllegalArgumentException if {@code tagName} is + * {@code null}. */ public TIFFTag getTag(String tagName) { if (tagName == null) { @@ -123,7 +123,7 @@ * Retrieves an unmodifiable numerically increasing set of tag numbers. * *

    The returned object is unmodifiable and contains the tag - * numbers of all TIFFTags in this TIFFTagSet + * numbers of all {@code TIFFTag}s in this {@code TIFFTagSet} * sorted into ascending order according to * {@link Integer#compareTo(Object)}.

    * @@ -145,7 +145,7 @@ * Retrieves an unmodifiable lexicographically increasing set of tag names. * *

    The returned object is unmodifiable and contains the tag - * names of all TIFFTags in this TIFFTagSet + * names of all {@code TIFFTag}s in this {@code TIFFTagSet} * sorted into ascending order according to * {@link String#compareTo(Object)}.

    * diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java --- a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java Mon Mar 21 11:21:08 2016 +0100 @@ -193,36 +193,48 @@ getLocalGraphicsEnvironment().getDefaultScreenDevice(). getDefaultConfiguration().getBounds() : gc.getBounds(); + x += gcBounds.x; + y += gcBounds.y; ServiceDialog dialog; if (owner instanceof Frame) { dialog = new ServiceDialog(gc, - x + gcBounds.x, - y + gcBounds.y, + x, + y, services, defaultIndex, flavor, attributes, (Frame)owner); } else { dialog = new ServiceDialog(gc, - x + gcBounds.x, - y + gcBounds.y, + x, + y, services, defaultIndex, flavor, attributes, (Dialog)owner); } Rectangle dlgBounds = dialog.getBounds(); - // get union of all GC bounds - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] gs = ge.getScreenDevices(); - for (int j=0; j gcBounds.x + gcBounds.width) { + if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) { + x = (gcBounds.x + gcBounds.width) - dlgBounds.width; + } else { + x = gcBounds.x; + } + } + if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) { + if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) { + y = (gcBounds.y + gcBounds.height) - dlgBounds.height; + } else { + y = gcBounds.y; + } + } + dialog.setBounds(x, y, dlgBounds.width, dlgBounds.height); } dialog.show(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java --- a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java Mon Mar 21 11:21:08 2016 +0100 @@ -191,12 +191,6 @@ JLayeredPane.putLayer(desktopIcon, layer); } - // If we are maximized we already have the normal bounds recorded - // don't try to re-record them, otherwise we incorrectly set the - // normal bounds to maximized state. - if (!f.isMaximum()) { - f.setNormalBounds(f.getBounds()); - } if (findNext) { if (d.selectFrame(true) == null) { // The icon is the last frame. diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java --- a/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -584,6 +584,69 @@ } /** + * Returns an array of files representing the values to show by default in + * the file chooser selector. + * + * @return an array of {@code File} objects. + * @throws SecurityException if the caller does not have necessary + * permissions + * @since 9 + */ + public File[] getChooserComboBoxFiles() { + return (File[]) ShellFolder.get("fileChooserComboBoxFolders"); + } + + /** + * Returns whether the specified file denotes a shell interpreted link which + * can be obtained by the {@link #getLinkLocation(File)}. + * + * @param file a file + * @return whether this is a link + * @throws NullPointerException if {@code file} equals {@code null} + * @throws SecurityException if the caller does not have necessary + * permissions + * @see #getLinkLocation(File) + * @since 9 + */ + public boolean isLink(File file) { + if (file == null) { + throw new NullPointerException("file is null"); + } + try { + return ShellFolder.getShellFolder(file).isLink(); + } catch (FileNotFoundException e) { + return false; + } + } + + /** + * Returns the regular file referenced by the specified link file if + * the specified file is a shell interpreted link. + * Returns {@code null} if the specified file is not + * a shell interpreted link. + * + * @param file a file + * @return the linked file or {@code null}. + * @throws FileNotFoundException if the linked file does not exist + * @throws NullPointerException if {@code file} equals {@code null} + * @throws SecurityException if the caller does not have necessary + * permissions + * @since 9 + */ + public File getLinkLocation(File file) throws FileNotFoundException { + if (file == null) { + throw new NullPointerException("file is null"); + } + ShellFolder shellFolder; + try { + shellFolder = ShellFolder.getShellFolder(file); + } catch (FileNotFoundException e) { + return null; + } + return shellFolder.isLink() ? shellFolder.getLinkLocation() : null; + } + + /** * Throws {@code FileNotFoundException} if file not found or current thread was interrupted */ ShellFolder getShellFolder(File f) throws FileNotFoundException { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -962,18 +962,13 @@ int orientation = SwingConstants.VERTICAL; // find which scrollbar to scroll, or return if none - if (toScroll == null || !toScroll.isVisible()) { + if (toScroll == null || !toScroll.isVisible() + || e.isShiftDown()) { toScroll = scrollpane.getHorizontalScrollBar(); if (toScroll == null || !toScroll.isVisible()) { return; } orientation = SwingConstants.HORIZONTAL; - } else if(e.isShiftDown()){ - JScrollBar hScroll = scrollpane.getHorizontalScrollBar(); - if (hScroll != null && hScroll.isVisible()) { - toScroll = hScroll; - orientation = SwingConstants.HORIZONTAL; - } } e.consume(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java Mon Mar 21 11:21:08 2016 +0100 @@ -362,9 +362,6 @@ setWasIcon(f, Boolean.TRUE); } - if (!f.isMaximum()) { - f.setNormalBounds(f.getBounds()); - } c.remove(f); c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); try { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java Mon Mar 21 11:21:08 2016 +0100 @@ -230,9 +230,10 @@ boolean hasRollover = (column == getRolloverColumn()); if (isSelected || hasRollover || hasFocus) { + boolean enabled = (table == null)? true : table.isEnabled(); SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. getUIOfType(getUI(), SynthLabelUI.class), - isSelected, hasFocus, table.isEnabled(), + isSelected, hasFocus, enabled, hasRollover); } else { SynthLookAndFeel.resetSelectedUI(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/applet/Main.java --- a/jdk/src/java.desktop/share/classes/sun/applet/Main.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/applet/Main.java Mon Mar 21 11:21:08 2016 +0100 @@ -30,8 +30,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.MalformedURLException; import java.util.Enumeration; @@ -75,7 +73,6 @@ /** * Member variables set according to options passed in to AppletViewer. */ - private boolean debugFlag = false; private boolean helpFlag = false; private String encoding = null; private boolean noSecurityFlag = false; @@ -136,14 +133,6 @@ return 1; } - if (debugFlag) { - // START A DEBUG SESSION - // Given the current architecture, we will end up decoding the - // arguments again, but at least we are guaranteed to have - // arguments which are valid. - return invokeDebugger(args); - } - // INSTALL THE SECURITY MANAGER (if necessary) if (!noSecurityFlag && (System.getSecurityManager() == null)) init(); @@ -191,9 +180,6 @@ throw new ParseException(lookup("main.err.dupoption", arg)); encoding = args[++i]; return 2; - } else if ("-debug".equals(arg)) { - debugFlag = true; - return 1; } else if ("-Xnosecurity".equals(arg)) { // This is an undocumented (and, in the future, unsupported) // flag which prevents AppletViewer from installing its own @@ -267,68 +253,6 @@ return u; } - /** - * Invoke the debugger with the arguments passed in to appletviewer. - * - * @param args The arguments passed into the debugger. - * @return {@code 0} if the debugger is invoked successfully, - * {@code 1} otherwise. - */ - private int invokeDebugger(String [] args) { - // CONSTRUCT THE COMMAND LINE - String [] newArgs = new String[args.length + 1]; - int current = 0; - - // Add a -classpath argument that prevents - // the debugger from launching appletviewer with the default of - // ".". appletviewer's classpath should never contain valid - // classes since they will result in security exceptions. - // Ideally, the classpath should be set to "", but the VM won't - // allow an empty classpath, so a phony directory name is used. - String phonyDir = System.getProperty("java.home") + - File.separator + "phony"; - newArgs[current++] = "-Djava.class.path=" + phonyDir; - - // Appletviewer's main class is the debuggee - newArgs[current++] = "sun.applet.Main"; - - // Append all the of the original appletviewer arguments, - // leaving out the "-debug" option. - for (int i = 0; i < args.length; i++) { - if (!("-debug".equals(args[i]))) { - newArgs[current++] = args[i]; - } - } - - // LAUNCH THE DEBUGGER - // Reflection is used for two reasons: - // 1) The debugger classes are on classpath and thus must be loaded - // by the application class loader. (Currently, appletviewer are - // loaded through the boot class path out of rt.jar.) - // 2) Reflection removes any build dependency between appletviewer - // and jdb. - try { - Class c = Class.forName("com.sun.tools.example.debug.tty.TTY", true, - ClassLoader.getSystemClassLoader()); - Method m = c.getDeclaredMethod("main", - new Class[] { String[].class }); - m.invoke(null, new Object[] { newArgs }); - } catch (ClassNotFoundException cnfe) { - System.err.println(lookup("main.debug.cantfinddebug")); - return 1; - } catch (NoSuchMethodException nsme) { - System.err.println(lookup("main.debug.cantfindmain")); - return 1; - } catch (InvocationTargetException ite) { - System.err.println(lookup("main.debug.exceptionindebug")); - return 1; - } catch (IllegalAccessException iae) { - System.err.println(lookup("main.debug.cantaccess")); - return 1; - } - return 0; - } - private void init() { // GET APPLETVIEWER USER-SPECIFIC PROPERTIES Properties avProps = getAVProps(); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java --- a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java Mon Mar 21 11:21:08 2016 +0100 @@ -74,7 +74,7 @@ {"appletviewer.parse.warning.embed.requireswidth", "Warning: tag requires width attribute."}, {"appletviewer.parse.warning.appnotLongersupported", "Warning: tag no longer supported, use instead:"}, {"appletviewer.deprecated", "AppletViewer is deprecated."}, - {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -debug Start the applet viewer in the Java debugger\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, + {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, {"appletviewer.main.err.unsupportedopt", "Unsupported option: {0}"}, {"appletviewer.main.err.unrecognizedarg", "Unrecognized argument: {0}"}, {"appletviewer.main.err.dupoption", "Duplicate use of option: {0}"}, diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java --- a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.awt; import java.util.Collections; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.java2d; + +import java.lang.ref.Reference; + +/** + * ReentrantContext is a base class to hold thread-local data supporting + * reentrancy in either a ThreadLocal or a ConcurrentLinkedQueue + * + * @see ReentrantContextProvider + */ +public class ReentrantContext { + // usage stored as a byte + byte usage = ReentrantContextProvider.USAGE_TL_INACTIVE; + /* + * Reference to this instance (hard, soft or weak). + * @see ReentrantContextProvider#refType + */ + Reference reference = null; +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.java2d; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; + +/** + * This abstract ReentrantContextProvider helper class manages the creation, + * storage, and retrieval of concrete ReentrantContext instances which can be + * subclassed to hold cached contextual data. + * + * It supports reentrancy as every call to acquire() provides a new unique context + * instance that must later be returned for reuse by a call to release(ctx) + * (typically in a try/finally block). + * + * It has a couple of abstract implementations which store references in a queue + * and/or thread-local storage. + * The Providers can be configured to hold ReentrantContext instances in memory + * using hard, soft or weak references. + * + * The acquire() and release() methods are used to retrieve and return the contexts. + * + * The {@code newContext()} method remains abstract in all implementations and + * must be provided by the module to create a new subclass of ReentrantContext + * with the appropriate contextual data in it. + * + * Sample Usage: + * - create a subclass ReentrantContextImpl to hold the thread state: + * + * static final class ReentrantContextImpl extends ReentrantContext { + * // specific cached data + * } + * + * - create the appropriate ReentrantContextProvider: + * + * private static final ReentrantContextProvider contextProvider = + * new ReentrantContextProviderTL(ReentrantContextProvider.REF_WEAK) + * { + * @Override + * protected ReentrantContextImpl newContext() { + * return new ReentrantContextImpl(); + * } + * }; + * ... + * void someMethod() { + * ReentrantContextImpl ctx = contextProvider.acquire(); + * try { + * // use the context + * } finally { + * contextProvider.release(ctx); + * } + * } + * + * @param ReentrantContext subclass + * + * @see ReentrantContext + */ +public abstract class ReentrantContextProvider +{ + // thread-local storage: inactive + static final byte USAGE_TL_INACTIVE = 0; + // thread-local storage: in use + static final byte USAGE_TL_IN_USE = 1; + // CLQ storage + static final byte USAGE_CLQ = 2; + + // hard reference + public static final int REF_HARD = 0; + // soft reference + public static final int REF_SOFT = 1; + // weak reference + public static final int REF_WEAK = 2; + + /* members */ + // internal reference type + private final int refType; + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak + * + * @param refType reference type + */ + protected ReentrantContextProvider(final int refType) { + this.refType = refType; + } + + /** + * Create a new ReentrantContext instance + * + * @return new ReentrantContext instance + */ + protected abstract K newContext(); + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + public abstract K acquire(); + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + public abstract void release(K ctx); + + @SuppressWarnings("unchecked") + protected final Reference getOrCreateReference(final K ctx) { + if (ctx.reference == null) { + // Create the reference: + switch (refType) { + case REF_HARD: + ctx.reference = new HardReference(ctx); + break; + case REF_SOFT: + ctx.reference = new SoftReference(ctx); + break; + default: + case REF_WEAK: + ctx.reference = new WeakReference(ctx); + break; + } + } + return (Reference) ctx.reference; + } + + /* Missing HardReference implementation */ + static final class HardReference extends WeakReference { + // kept strong reference: + private final V strongRef; + + HardReference(final V referent) { + // no referent needed for the parent WeakReference: + super(null); + this.strongRef = referent; + } + + @Override + public V get() { + return strongRef; + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.java2d; + +import java.lang.ref.Reference; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * This ReentrantContextProvider implementation uses one ConcurrentLinkedQueue + * to store all ReentrantContext instances (thread and its child contexts) + * + * Note: this implementation keeps less contexts in memory depending on the + * concurrent active threads in contrary to a ThreadLocal provider. However, + * it is slower in highly concurrent workloads. + * + * @param ReentrantContext subclass + */ +public abstract class ReentrantContextProviderCLQ + extends ReentrantContextProvider +{ + // ReentrantContext queue to store all contexts + private final ConcurrentLinkedQueue> ctxQueue + = new ConcurrentLinkedQueue>(); + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak based using a ConcurrentLinkedQueue storage + * + * @param refType reference type + */ + public ReentrantContextProviderCLQ(final int refType) { + super(refType); + } + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + @Override + public final K acquire() { + K ctx = null; + // Drain queue if all referent are null: + Reference ref = null; + while ((ctx == null) && ((ref = ctxQueue.poll()) != null)) { + ctx = ref.get(); + } + if (ctx == null) { + // create a new ReentrantContext if none is available + ctx = newContext(); + ctx.usage = USAGE_CLQ; + } + return ctx; + } + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + @Override + public final void release(final K ctx) { + if (ctx.usage == USAGE_CLQ) { + ctxQueue.offer(getOrCreateReference(ctx)); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.java2d; + +import java.lang.ref.Reference; + +/** +* This ReentrantContextProvider implementation uses a ThreadLocal to hold + * the first ReentrantContext per thread and a ReentrantContextProviderCLQ to + * store child ReentrantContext instances needed during recursion. + * + * Note: this implementation may keep up to one context in memory per thread. + * Child contexts for recursive uses are stored in the queue using a WEAK + * reference by default unless specified in the 2 argument constructor. + * + * @param ReentrantContext subclass + */ +public abstract class ReentrantContextProviderTL + extends ReentrantContextProvider +{ + // Thread-local storage: + private final ThreadLocal> ctxTL + = new ThreadLocal>(); + + // ReentrantContext CLQ provider for child contexts: + private final ReentrantContextProviderCLQ ctxProviderCLQ; + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak. + * It uses weak reference for the child contexts. + * + * @param refType reference type + */ + public ReentrantContextProviderTL(final int refType) { + this(refType, REF_WEAK); + } + + /** + * Create a new ReentrantContext provider using the given reference types + * among hard, soft or weak + * + * @param refTypeTL reference type used by ThreadLocal + * @param refTypeCLQ reference type used by ReentrantContextProviderCLQ + */ + public ReentrantContextProviderTL(final int refTypeTL, final int refTypeCLQ) + { + super(refTypeTL); + + final ReentrantContextProviderTL parent = this; + + this.ctxProviderCLQ = new ReentrantContextProviderCLQ(refTypeCLQ) { + @Override + protected K newContext() { + return parent.newContext(); + } + }; + } + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + @Override + public final K acquire() { + K ctx = null; + final Reference ref = ctxTL.get(); + if (ref != null) { + ctx = ref.get(); + } + if (ctx == null) { + // create a new ReentrantContext if none is available + ctx = newContext(); + // update thread local reference: + ctxTL.set(getOrCreateReference(ctx)); + } + // Check reentrance: + if (ctx.usage == USAGE_TL_INACTIVE) { + ctx.usage = USAGE_TL_IN_USE; + } else { + // get or create another ReentrantContext from CLQ provider: + ctx = ctxProviderCLQ.acquire(); + } + return ctx; + } + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + @Override + public final void release(final K ctx) { + if (ctx.usage == USAGE_TL_IN_USE) { + ctx.usage = USAGE_TL_INACTIVE; + } else { + ctxProviderCLQ.release(ctx); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,7 @@ } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -135,9 +135,10 @@ { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -136,9 +136,10 @@ { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,7 @@ } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -135,9 +135,10 @@ { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -590,8 +590,8 @@ alphaRow[to + 1] = 0; } if (doChecks) { - IntArrayCache.check(blkFlags, 0, blkFlags.length, 0); - IntArrayCache.check(alphaRow, 0, alphaRow.length, 0); + IntArrayCache.check(blkFlags, blkW, blkE, 0); + IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0); } if (doMonitors) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,11 +30,12 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; -import java.lang.ref.Reference; import java.security.AccessController; -import java.util.concurrent.ConcurrentLinkedQueue; import static sun.java2d.marlin.MarlinUtils.logInfo; import sun.awt.geom.PathConsumer2D; +import sun.java2d.ReentrantContextProvider; +import sun.java2d.ReentrantContextProviderCLQ; +import sun.java2d.ReentrantContextProviderTL; import sun.java2d.pipe.AATileGenerator; import sun.java2d.pipe.Region; import sun.java2d.pipe.RenderingEngine; @@ -882,46 +883,50 @@ // use ThreadLocal or ConcurrentLinkedQueue to get one RendererContext private static final boolean useThreadLocal; - // hard reference - static final int REF_HARD = 0; - // soft reference - static final int REF_SOFT = 1; - // weak reference - static final int REF_WEAK = 2; - // reference type stored in either TL or CLQ static final int REF_TYPE; // Per-thread RendererContext - private static final ThreadLocal rdrCtxThreadLocal; - // RendererContext queue when ThreadLocal is disabled - private static final ConcurrentLinkedQueue rdrCtxQueue; + private static final ReentrantContextProvider rdrCtxProvider; // Static initializer to use TL or CLQ mode static { - // CLQ mode by default: useThreadLocal = MarlinProperties.isUseThreadLocal(); - rdrCtxThreadLocal = (useThreadLocal) ? new ThreadLocal() - : null; - rdrCtxQueue = (!useThreadLocal) ? new ConcurrentLinkedQueue() - : null; // Soft reference by default: - String refType = AccessController.doPrivileged( + final String refType = AccessController.doPrivileged( new GetPropertyAction("sun.java2d.renderer.useRef", "soft")); switch (refType) { default: case "soft": - REF_TYPE = REF_SOFT; + REF_TYPE = ReentrantContextProvider.REF_SOFT; break; case "weak": - REF_TYPE = REF_WEAK; + REF_TYPE = ReentrantContextProvider.REF_WEAK; break; case "hard": - REF_TYPE = REF_HARD; + REF_TYPE = ReentrantContextProvider.REF_HARD; break; } + + if (useThreadLocal) { + rdrCtxProvider = new ReentrantContextProviderTL(REF_TYPE) + { + @Override + protected RendererContext newContext() { + return RendererContext.createContext(); + } + }; + } else { + rdrCtxProvider = new ReentrantContextProviderCLQ(REF_TYPE) + { + @Override + protected RendererContext newContext() { + return RendererContext.createContext(); + } + }; + } } private static boolean settingsLogged = !enableLogs; @@ -936,13 +941,13 @@ String refType; switch (REF_TYPE) { default: - case REF_HARD: + case ReentrantContextProvider.REF_HARD: refType = "hard"; break; - case REF_SOFT: + case ReentrantContextProvider.REF_SOFT: refType = "soft"; break; - case REF_WEAK: + case ReentrantContextProvider.REF_WEAK: refType = "weak"; break; } @@ -1025,22 +1030,7 @@ */ @SuppressWarnings({"unchecked"}) static RendererContext getRendererContext() { - RendererContext rdrCtx = null; - final Object ref = (useThreadLocal) ? rdrCtxThreadLocal.get() - : rdrCtxQueue.poll(); - if (ref != null) { - // resolve reference: - rdrCtx = (REF_TYPE == REF_HARD) ? ((RendererContext) ref) - : ((Reference) ref).get(); - } - // create a new RendererContext if none is available - if (rdrCtx == null) { - rdrCtx = RendererContext.createContext(); - if (useThreadLocal) { - // update thread local reference: - rdrCtxThreadLocal.set(rdrCtx.reference); - } - } + final RendererContext rdrCtx = rdrCtxProvider.acquire(); if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.start(); } @@ -1057,8 +1047,6 @@ if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.stop(); } - if (!useThreadLocal) { - rdrCtxQueue.offer(rdrCtx.reference); - } + rdrCtxProvider.release(rdrCtx); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java Mon Mar 21 11:21:08 2016 +0100 @@ -148,8 +148,8 @@ ////////////////////////////////////////////////////////////////////////////// // EDGE LIST ////////////////////////////////////////////////////////////////////////////// - private float edgeMinY = Float.POSITIVE_INFINITY; - private float edgeMaxY = Float.NEGATIVE_INFINITY; + private int edgeMinY = Integer.MAX_VALUE; + private int edgeMaxY = Integer.MIN_VALUE; private float edgeMinX = Float.POSITIVE_INFINITY; private float edgeMaxX = Float.NEGATIVE_INFINITY; @@ -357,18 +357,21 @@ } return; } - // edge min/max X/Y are in subpixel space (inclusive) - if (y1 < edgeMinY) { - edgeMinY = y1; + + // edge min/max X/Y are in subpixel space (inclusive) within bounds: + // note: Use integer crossings to ensure consistent range within + // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0) + if (firstCrossing < edgeMinY) { + edgeMinY = firstCrossing; } - if (y2 > edgeMaxY) { - edgeMaxY = y2; + if (lastCrossing > edgeMaxY) { + edgeMaxY = lastCrossing; } // Use double-precision for improved accuracy: final double x1d = x1; final double y1d = y1; - final double slope = (x2 - x1d) / (y2 - y1d); + final double slope = (x1d - x2) / (y1d - y2); if (slope >= 0.0) { // <==> x1 < x2 if (x1 < edgeMinX) { @@ -504,7 +507,7 @@ private float x0, y0; // Position of most recent 'moveTo' command - private float pix_sx0, pix_sy0; + private float sx0, sy0; // per-thread renderer context final RendererContext rdrCtx; @@ -570,8 +573,8 @@ edgeBucketCounts = rdrCtx.getIntArray(edgeBucketsLength); } - edgeMinY = Float.POSITIVE_INFINITY; - edgeMaxY = Float.NEGATIVE_INFINITY; + edgeMinY = Integer.MAX_VALUE; + edgeMaxY = Integer.MIN_VALUE; edgeMinX = Float.POSITIVE_INFINITY; edgeMaxX = Float.NEGATIVE_INFINITY; @@ -628,7 +631,7 @@ blkFlags = blkFlags_initial; } - if (edgeMinY != Float.POSITIVE_INFINITY) { + if (edgeMinY != Integer.MAX_VALUE) { // if context is maked as DIRTY: if (rdrCtx.dirty) { // may happen if an exception if thrown in the pipeline processing: @@ -688,16 +691,18 @@ @Override public void moveTo(float pix_x0, float pix_y0) { closePath(); - this.pix_sx0 = pix_x0; - this.pix_sy0 = pix_y0; - this.y0 = tosubpixy(pix_y0); - this.x0 = tosubpixx(pix_x0); + final float sx = tosubpixx(pix_x0); + final float sy = tosubpixy(pix_y0); + this.sx0 = sx; + this.sy0 = sy; + this.x0 = sx; + this.y0 = sy; } @Override public void lineTo(float pix_x1, float pix_y1) { - float x1 = tosubpixx(pix_x1); - float y1 = tosubpixy(pix_y1); + final float x1 = tosubpixx(pix_x1); + final float y1 = tosubpixy(pix_y1); addLine(x0, y0, x1, y1); x0 = x1; y0 = y1; @@ -729,8 +734,9 @@ @Override public void closePath() { - // lineTo expects its input in pixel coordinates. - lineTo(pix_sx0, pix_sy0); + addLine(x0, y0, sx0, sy0); + x0 = sx0; + y0 = sy0; } @Override @@ -1396,7 +1402,7 @@ if (doMonitors) { RendererContext.stats.mon_rdr_endRendering.start(); } - if (edgeMinY == Float.POSITIVE_INFINITY) { + if (edgeMinY == Integer.MAX_VALUE) { return false; // undefined edges bounds } @@ -1407,11 +1413,10 @@ final int spminX = FloatMath.max(FloatMath.ceil_int(edgeMinX - 0.5f), boundsMinX); final int spmaxX = FloatMath.min(FloatMath.ceil_int(edgeMaxX - 0.5f), boundsMaxX - 1); - // y1 (and y2) are already biased by -0.5 in tosubpixy(): - final int spminY = FloatMath.max(FloatMath.ceil_int(edgeMinY), _boundsMinY); - int maxY = FloatMath.ceil_int(edgeMaxY); - + // edge Min/Max Y are already rounded to subpixels within bounds: + final int spminY = edgeMinY; final int spmaxY; + int maxY = edgeMaxY; if (maxY <= _boundsMaxY - 1) { spmaxY = maxY; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,10 @@ package sun.java2d.marlin; import java.awt.geom.Path2D; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; +import sun.java2d.ReentrantContext; +import sun.java2d.ReentrantContextProvider; import static sun.java2d.marlin.ArrayCache.*; import sun.java2d.marlin.MarlinRenderingEngine.NormalizingPathIterator; import static sun.java2d.marlin.MarlinUtils.logInfo; @@ -36,7 +37,7 @@ /** * This class is a renderer context dedicated to a single thread */ -final class RendererContext implements MarlinConst { +final class RendererContext extends ReentrantContext implements MarlinConst { // RendererContext creation counter private static final AtomicInteger contextCount = new AtomicInteger(1); @@ -45,7 +46,7 @@ ? RendererStats.getInstance(): null; private static final boolean USE_CACHE_HARD_REF = doStats - || (MarlinRenderingEngine.REF_TYPE == MarlinRenderingEngine.REF_WEAK); + || (MarlinRenderingEngine.REF_TYPE == ReentrantContextProvider.REF_WEAK); /** * Create a new renderer context @@ -55,6 +56,7 @@ static RendererContext createContext() { final RendererContext newCtx = new RendererContext("ctx" + Integer.toString(contextCount.getAndIncrement())); + if (RendererContext.stats != null) { RendererContext.stats.allContexts.add(newCtx); } @@ -63,11 +65,6 @@ // context name (debugging purposes) final String name; - /* - * Reference to this instance (hard, soft or weak). - * @see MarlinRenderingEngine#REF_TYPE - */ - final Object reference; // Smallest object used as Cleaner's parent reference final Object cleanerObj = new Object(); // dirty flag indicating an exception occured during pipeline in pathTo() @@ -101,7 +98,7 @@ /** * Constructor * - * @param name + * @param name context name (debugging) */ RendererContext(final String name) { if (logCreateContext) { @@ -124,20 +121,6 @@ stroker = new Stroker(this); dasher = new Dasher(this); - - // Create the reference to this instance (hard, soft or weak): - switch (MarlinRenderingEngine.REF_TYPE) { - default: - case MarlinRenderingEngine.REF_HARD: - reference = this; - break; - case MarlinRenderingEngine.REF_SOFT: - reference = new SoftReference(this); - break; - case MarlinRenderingEngine.REF_WEAK: - reference = new WeakReference(this); - break; - } } /** diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ public final class Version { - private static final String version = "marlin-0.7.3-Unsafe-OpenJDK"; + private static final String version = "marlin-0.7.3.2-Unsafe-OpenJDK"; public static String getVersion() { return version; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,11 @@ import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Rectangle2D; +import java.util.concurrent.ConcurrentLinkedQueue; import sun.awt.SunHints; +import sun.java2d.ReentrantContext; +import sun.java2d.ReentrantContextProvider; +import sun.java2d.ReentrantContextProviderTL; import sun.java2d.SunGraphics2D; /** @@ -38,28 +42,31 @@ * This class sets up the Generator and computes the alpha tiles * and then passes them on to a CompositePipe object for painting. */ -public class AAShapePipe +public final class AAShapePipe implements ShapeDrawPipe, ParallelogramPipe { - static RenderingEngine renderengine = RenderingEngine.getInstance(); + static final RenderingEngine renderengine = RenderingEngine.getInstance(); // Per-thread TileState (~1K very small so do not use any Weak Reference) - private static final ThreadLocal tileStateThreadLocal = - new ThreadLocal() { - @Override - protected TileState initialValue() { - return new TileState(); - } - }; + private static final ReentrantContextProvider tileStateProvider = + new ReentrantContextProviderTL( + ReentrantContextProvider.REF_HARD) + { + @Override + protected TileState newContext() { + return new TileState(); + } + }; - CompositePipe outpipe; + final CompositePipe outpipe; public AAShapePipe(CompositePipe pipe) { outpipe = pipe; } + @Override public void draw(SunGraphics2D sg, Shape s) { - BasicStroke bs; + final BasicStroke bs; if (sg.stroke instanceof BasicStroke) { bs = (BasicStroke) sg.stroke; @@ -71,10 +78,12 @@ renderPath(sg, s, bs); } + @Override public void fill(SunGraphics2D sg, Shape s) { renderPath(sg, s, null); } + @Override public void fillParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, @@ -82,21 +91,23 @@ double dx1, double dy1, double dx2, double dy2) { - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, - clip, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, + sg.getCompClip(), abox); + if (aatg != null) { + renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), + aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } + @Override public void drawParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, @@ -105,52 +116,61 @@ double dx2, double dy2, double lw1, double lw2) { - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, - clip, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, + lw2, sg.getCompClip(), abox); + if (aatg != null) { + // Note that bbox is of the original shape, not the wide path. + // This is appropriate for handing to Paint methods... + renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), + aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - // Note that bbox is of the original shape, not the wide path. - // This is appropriate for handing to Paint methods... - renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { - boolean adjust = (bs != null && + final boolean adjust = (bs != null && sg.strokeHint != SunHints.INTVAL_STROKE_PURE); - boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); + final boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(s, sg.transform, clip, - bs, thin, adjust, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(s, sg.transform, sg.getCompClip(), + bs, thin, adjust, abox); + if (aatg != null) { + renderTiles(sg, s, aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - renderTiles(sg, s, aatg, abox, ts); } public void renderTiles(SunGraphics2D sg, Shape s, - AATileGenerator aatg, int abox[], TileState ts) + final AATileGenerator aatg, + final int[] abox, final TileState ts) { Object context = null; try { + // reentrance: outpipe may also use AAShapePipe: context = outpipe.startSequence(sg, s, ts.computeDevBox(abox), abox); + // copy of int[] abox as local variables for performance: + final int x0 = abox[0]; + final int y0 = abox[1]; + final int x1 = abox[2]; + final int y1 = abox[3]; + final int tw = aatg.getTileWidth(); final int th = aatg.getTileHeight(); @@ -158,16 +178,15 @@ final byte[] alpha = ts.getAlphaTile(tw * th); byte[] atile; - for (int y = abox[1]; y < abox[3]; y += th) { - int h = Math.min(th, abox[3] - y); + for (int y = y0; y < y1; y += th) { + final int h = Math.min(th, y1 - y); - for (int x = abox[0]; x < abox[2]; x += tw) { - int w = Math.min(tw, abox[2] - x); + for (int x = x0; x < x1; x += tw) { + final int w = Math.min(tw, x1 - x); - int a = aatg.getTypicalAlpha(); - if (a == 0x00 || - outpipe.needTile(context, x, y, w, h) == false) - { + final int a = aatg.getTypicalAlpha(); + + if (a == 0x00 || !outpipe.needTile(context, x, y, w, h)) { aatg.nextTile(); outpipe.skipTile(context, x, y); continue; @@ -180,8 +199,7 @@ aatg.getAlpha(alpha, 0, tw); } - outpipe.renderPathTile(context, atile, 0, tw, - x, y, w, h); + outpipe.renderPathTile(context, atile, 0, tw, x, y, w, h); } } } finally { @@ -193,7 +211,7 @@ } // Tile state used by AAShapePipe - static final class TileState { + static final class TileState extends ReentrantContext { // cached tile (32 x 32 tile by default) private byte[] theTile = new byte[32 * 32]; // dirty aabox array @@ -240,5 +258,4 @@ return box; } } - } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java Mon Mar 21 11:21:08 2016 +0100 @@ -791,12 +791,15 @@ return page; } - final GraphicsConfiguration gc = - GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); - Rectangle bounds = gc.getBounds(); - int x = bounds.x+bounds.width/3; - int y = bounds.y+bounds.height/3; + GraphicsConfiguration grCfg = null; + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if (w != null) { + grCfg = w.getGraphicsConfiguration(); + } else { + grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + final GraphicsConfiguration gc = grCfg; PrintService service = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -814,9 +817,39 @@ return null; } + // we position the dialog a little beyond the upper-left corner of the window + // which is consistent with the NATIVE page dialog + Rectangle gcBounds = gc.getBounds(); + int x = gcBounds.x+50; + int y = gcBounds.y+50; ServiceDialog pageDialog = new ServiceDialog(gc, x, y, service, DocFlavor.SERVICE_FORMATTED.PAGEABLE, attributes, (Frame)null); + Rectangle dlgBounds = pageDialog.getBounds(); + + // if portion of dialog is not within the gc boundary + if (!gcBounds.contains(dlgBounds)) { + // check if dialog exceed window bounds at left or bottom + // Then position the dialog by moving it by the amount it exceeds + // the window bounds + // If it results in dialog moving beyond the window bounds at top/left + // then position it at window top/left + if (dlgBounds.x + dlgBounds.width > gcBounds.x + gcBounds.width) { + if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) { + x = (gcBounds.x + gcBounds.width) - dlgBounds.width; + } else { + x = gcBounds.x; + } + } + if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) { + if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) { + y = (gcBounds.y + gcBounds.height) - dlgBounds.height; + } else { + y = gcBounds.y; + } + } + pageDialog.setBounds(x, y, dlgBounds.width, dlgBounds.height); + } pageDialog.show(); if (pageDialog.getStatus() == ServiceDialog.APPROVE) { @@ -893,9 +926,15 @@ * We raise privilege when we put up the dialog, to avoid * the "warning applet window" banner. */ - final GraphicsConfiguration gc = - GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); + GraphicsConfiguration grCfg = null; + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if (w != null) { + grCfg = w.getGraphicsConfiguration(); + } else { + grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + final GraphicsConfiguration gc = grCfg; PrintService service = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -940,9 +979,10 @@ } } - Rectangle bounds = gc.getBounds(); - int x = bounds.x+bounds.width/3; - int y = bounds.y+bounds.height/3; + // we position the dialog a little beyond the upper-left corner of the window + // which is consistent with the NATIVE print dialog + int x = 50; + int y = 50; PrintService newService; // temporarily add an attribute pointing back to this job. PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java --- a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.java2d.x11; import java.awt.image.*; diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java --- a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java Mon Mar 21 11:21:08 2016 +0100 @@ -52,6 +52,7 @@ private boolean initialized; private static native String getCupsServer(); private static native int getCupsPort(); + private static native String getCupsDefaultPrinter(); private static native boolean canConnect(String server, int port); private static native boolean initIDs(); // These functions need to be synchronized as @@ -266,6 +267,15 @@ * Returns 2 values - index 0 is printer name, index 1 is the uri. */ static String[] getDefaultPrinter() { + // Try to get user/lpoptions-defined printer name from CUPS + // if not user-set, then go for server default destination + String printerInfo[] = new String[2]; + printerInfo[0] = getCupsDefaultPrinter(); + + if (printerInfo[0] != null) { + printerInfo[1] = null; + return printerInfo.clone(); + } try { URL url = new URL("http", getServer(), getPort(), ""); final HttpURLConnection urlConnection = @@ -301,7 +311,7 @@ attCl)) { HashMap defaultMap = null; - String[] printerInfo = new String[2]; + InputStream is = urlConnection.getInputStream(); HashMap[] responseMap = IPPPrintService.readIPPResponse( is); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c --- a/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c Mon Mar 21 11:21:08 2016 +0100 @@ -43,6 +43,10 @@ typedef http_t* (*fn_httpConnect)(const char *, int); typedef void (*fn_httpClose)(http_t *); typedef char* (*fn_cupsGetPPD)(const char *); +typedef cups_dest_t* (*fn_cupsGetDest)(const char *name, + const char *instance, int num_dests, cups_dest_t *dests); +typedef int (*fn_cupsGetDests)(cups_dest_t **dests); +typedef void (*fn_cupsFreeDests)(int num_dests, cups_dest_t *dests); typedef ppd_file_t* (*fn_ppdOpenFile)(const char *); typedef void (*fn_ppdClose)(ppd_file_t *); typedef ppd_option_t* (*fn_ppdFindOption)(ppd_file_t *, const char *); @@ -53,6 +57,9 @@ fn_httpConnect j2d_httpConnect; fn_httpClose j2d_httpClose; fn_cupsGetPPD j2d_cupsGetPPD; +fn_cupsGetDest j2d_cupsGetDest; +fn_cupsGetDests j2d_cupsGetDests; +fn_cupsFreeDests j2d_cupsFreeDests; fn_ppdOpenFile j2d_ppdOpenFile; fn_ppdClose j2d_ppdClose; fn_ppdFindOption j2d_ppdFindOption; @@ -106,6 +113,24 @@ return JNI_FALSE; } + j2d_cupsGetDest = (fn_cupsGetDest)dlsym(handle, "cupsGetDest"); + if (j2d_cupsGetDest == NULL) { + dlclose(handle); + return JNI_FALSE; + } + + j2d_cupsGetDests = (fn_cupsGetDests)dlsym(handle, "cupsGetDests"); + if (j2d_cupsGetDests == NULL) { + dlclose(handle); + return JNI_FALSE; + } + + j2d_cupsFreeDests = (fn_cupsFreeDests)dlsym(handle, "cupsFreeDests"); + if (j2d_cupsFreeDests == NULL) { + dlclose(handle); + return JNI_FALSE; + } + j2d_ppdOpenFile = (fn_ppdOpenFile)dlsym(handle, "ppdOpenFile"); if (j2d_ppdOpenFile == NULL) { dlclose(handle); @@ -170,6 +195,30 @@ /* + * Gets CUPS default printer name. + * + */ +JNIEXPORT jstring JNICALL +Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env, + jobject printObj) +{ + jstring cDefPrinter = NULL; + cups_dest_t *dests; + char *defaultPrinter = NULL; + int num_dests = j2d_cupsGetDests(&dests); + int i = 0; + cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests); + if (dest != NULL) { + defaultPrinter = dest->name; + if (defaultPrinter != NULL) { + cDefPrinter = JNU_NewStringPlatform(env, defaultPrinter); + } + } + j2d_cupsFreeDests(num_dests, dests); + return cDefPrinter; +} + +/* * Checks if connection can be made to the server. * */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java Mon Mar 21 11:21:08 2016 +0100 @@ -500,6 +500,7 @@ class D3DSurfaceToSwBlit extends Blit { private int typeval; + private WeakReference srcTmp; // REMIND: destination will actually be opaque/premultiplied... D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) { @@ -509,11 +510,97 @@ this.typeval = typeval; } + /* + * Clip value is ignored in D3D SurfaceToSw blit. + * Root Cause: The native interfaces to D3D use StretchRect API followed + * by custom copy of pixels from Surface to Sysmem. As a result, clipping + * in D3DSurfaceToSw works 'only' for Rect clips, provided, proper srcX, + * srcY, dstX, dstY, width and height are passed to native interfaces. + * Non rect clips (For example: Shape clips) are ignored completely. + * + * Solution: There are three solutions possible to fix this issue. + * 1. Convert the entire Surface to Sysmem and perform regular Blit. + * An optimized version of this is to take up the conversion only + * when Shape clips are needed. Existing native interface will suffice + * for supporting Rect clips. + * 2. With help of existing classes we could perform SwToSurface, + * SurfaceToSurface (implements clip) and SurfaceToSw (complete copy) + * in order. + * 3. Modify the native D3D interface to accept clip and perform same logic + * as the second approach but at native side. + * + * Upon multiple experiments, the first approach has been found to be + * faster than the others as it deploys 1-draw/copy operation for rect clip + * and 2-draw/copy operations for shape clip compared to 3-draws/copy + * operations deployed by the remaining approaches. + * + * complexClipBlit method helps to convert or copy the contents from + * D3DSurface onto Sysmem and perform a regular Blit with the clip + * information as required. This method is used when non-rectangular + * clip is needed. + */ + private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + int sx, int sy, int dx, int dy, + int w, int h) { + SurfaceData cachedSrc = null; + if (srcTmp != null) { + // use cached intermediate surface, if available + cachedSrc = srcTmp.get(); + } + + // Type- indicates the pixel format of Sysmem based BufferedImage. + // Native d3d interfaces support on the fly conversion of pixels from + // d3d surface to destination sysmem memory of type IntARGB only. + final int type = BufferedImage.TYPE_INT_ARGB; + src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); + + // copy intermediate SW to destination SW using complex clip + final Blit performop = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + dst.getSurfaceType()); + performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } + public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { + if (clip != null) { + clip = clip.getIntersectionXYWH(dx, dy, w, h); + // At the end this method will flush the RenderQueue, we should exit + // from it as soon as possible. + if (clip.isEmpty()) { + return; + } + + // Adjust final dst(x,y) and src(x,y) based on the clip. The + // logic is that, when clip limits drawing on the destination, + // corresponding pixels from the src should be skipped. + sx += clip.getLoX() - dx; + sy += clip.getLoY() - dy; + dx = clip.getLoX(); + dy = clip.getLoY(); + w = clip.getWidth(); + h = clip.getHeight(); + + // Check if the clip is Rectangular. For non-rectangular clips + // complexClipBlit will convert Surface To Sysmem and perform + // regular Blit. + if (!clip.isRectangular()) { + complexClipBlit(src, dst, comp, clip, + sx, sy, dx, dy, + w, h); + return; + } + } + D3DRenderQueue rq = D3DRenderQueue.getInstance(); rq.lock(); try { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/java.naming/share/classes/javax/naming/CompoundName.java --- a/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java Mon Mar 21 11:21:08 2016 +0100 @@ -82,7 +82,7 @@ * attribute-value-assertions when specifying multiple attribute/value * pairs. (e.g. "," in age=65,gender=male). *
    jndi.syntax.separator.typeval - *
    If present, specifies the string that separators attribute + *
    If present, specifies the string that separates attribute * from value (e.g. "=" in "age=65") * * These properties are interpreted according to the following rules: diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java --- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java Mon Mar 21 11:21:08 2016 +0100 @@ -32,6 +32,7 @@ import java.awt.*; import java.awt.event.*; import java.awt.image.*; +import java.security.AccessControlException; // Do not import Swing classes. This module is intended to work // with both Swing and AWT. // import javax.swing.*; @@ -77,7 +78,7 @@ return null; } try { - t = Class.forName("com.sun.java.accessibility.util.internal" + t = Class.forName("com.sun.java.accessibility.util.internal." + c.getSimpleName() + "Translator"); return t; @@ -105,6 +106,10 @@ if (o instanceof Accessible) { a = (Accessible)o; } else { + // About to "newInstance" an object of a class of a restricted package + // so ensure the caller is allowed access to that package. + String pkg = "com.sun.java.accessibility.util.internal"; + System.getSecurityManager().checkPackageAccess(pkg); Class translatorClass = getTranslatorClass(o.getClass()); if (translatorClass != null) { try { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java --- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/RuntimeConstants.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,7 @@ /* Class File Constants */ int JAVA_MAGIC = 0xcafebabe; int JAVA_MIN_SUPPORTED_VERSION = 45; - int JAVA_MAX_SUPPORTED_VERSION = 52; + int JAVA_MAX_SUPPORTED_VERSION = 53; int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0; /* Generate class file version for 1.1 by default */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/TEST.groups --- a/jdk/test/TEST.groups Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/TEST.groups Mon Mar 21 11:21:08 2016 +0100 @@ -32,6 +32,7 @@ -java/util/WeakHashMap/GCDuringIteration.java \ -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ + -java/util/TimeZone/Bug6772689.java \ sun/nio/cs/ISO8859x.java \ java/nio/Buffer \ com/sun/crypto/provider/Cipher \ @@ -42,6 +43,7 @@ java/util/WeakHashMap/GCDuringIteration.java \ java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ + java/util/TimeZone/Bug6772689.java \ :jdk_io \ :jdk_nio \ -sun/nio/cs/ISO8859x.java \ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/com/sun/jdi/BadAgentPath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/jdi/BadAgentPath.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; + +/* @test + * @bug 8147456 + * @summary Check that providing a non-existing -agentpath gives a proper error. + * @author Sharath Ballal + * + * @library /lib/testlibrary + * @modules java.management + * @build jdk.testlibrary.* + * @build BadAgentPath + * @run driver BadAgentPath + */ + +public class BadAgentPath { + + public static void main(String[] args) throws Throwable { + OutputAnalyzer output = ProcessTools.executeTestJvm("-agentpath:/badAgent/agent", "-version"); + output.shouldContain("Could not find agent library /badAgent/agent"); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 8025001 + @summary Tests java.awt.ContainerOrderFocusTraversalPolicy functionality. + @run main ContainerOrderFTPTest +*/ + +import java.awt.Frame; +import java.awt.Button; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.ContainerOrderFocusTraversalPolicy; + +public class ContainerOrderFTPTest { + + private final ContainerOrderFocusTraversalPolicy coftp; + private final Frame frame; + private final Button b1; + private final Button b2; + private final String expectedTraversal; + + public ContainerOrderFTPTest() { + expectedTraversal = "B1B2F1"; + b1 = new Button("B1"); + b2 = new Button("B2"); + frame = new Frame("F1"); + + frame.setLayout(new FlowLayout()); + frame.setSize(200, 200); + coftp = new ContainerOrderFocusTraversalPolicy(); + frame.setFocusTraversalPolicy(coftp); + frame.add(b1); + frame.add(b2); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + ContainerOrderFTPTest test = new ContainerOrderFTPTest(); + test.performTest(); + test.dispose(); + } + + public void performTest() { + int count = 0; + Component comp = coftp.getFirstComponent(frame); + String traversal = ""; + do { + comp = coftp.getComponentAfter(frame, comp); + if (comp instanceof Button) { + traversal += ((Button)comp).getLabel(); + } else if (comp instanceof Frame) { + traversal += ((Frame)comp).getTitle(); + } + count++; + } while(count < 3); + + if (!expectedTraversal.equals(traversal)) { + dispose(); + throw new RuntimeException("Incorrect Traversal. Expected : " + + expectedTraversal + "Actual : " + traversal); + } + } + + public void dispose() { + frame.dispose(); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java --- a/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java Mon Mar 21 11:21:08 2016 +0100 @@ -42,11 +42,11 @@ /** * @test - * @bug 8041644 + * @bug 8041644 8044788 * @summary Tests drawing volatile image to BI using different clip. * Results of the blit compatibleImage to BI used for comparison. * @author Sergey Bylokhov - * @run main/othervm -Dsun.java2d.d3d=false IncorrectClipSurface2SW + * @run main/othervm IncorrectClipSurface2SW */ public final class IncorrectClipSurface2SW { diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8150258 + * @author a.stepanov + * @summary Check that correct resolution variants are chosen for menu icons + * when multiresolution image is used for their construction. + * + * @library ../../../../lib/testlibrary/ + * @build ExtendedRobot + * @run main/othervm -Dsun.java2d.uiScale=1 MenuMultiresolutionIconTest + * @run main/othervm -Dsun.java2d.uiScale=2 MenuMultiresolutionIconTest + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import javax.swing.*; + +public class MenuMultiresolutionIconTest extends JPanel { + + private final static int DELAY = 1000; + private final static int SZ = 50; + private final static String SCALE = "sun.java2d.uiScale"; + private final static Color C1X = Color.RED, C2X = Color.BLUE; + private final ExtendedRobot r; + + private static BufferedImage generateImage(int scale, Color c) { + + int x = SZ * scale; + BufferedImage img = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, x, x); + return img; + } + + private static BaseMultiResolutionImage createIcon() { + + return new BaseMultiResolutionImage(new BufferedImage[] { + generateImage(1, C1X), generateImage(2, C2X)}); + } + + private JFrame frame; + private JPopupMenu popup; + private JMenuItem popupItem; + private JMenu menu; + + public MenuMultiresolutionIconTest() throws Exception { + + r = new ExtendedRobot(); + SwingUtilities.invokeAndWait(this::createUI); + } + + private void createUI() { + + ImageIcon ii = new ImageIcon(createIcon()); + + popup = new JPopupMenu(); + popupItem = new JMenuItem("test", ii); + popup.add(popupItem); + popupItem.setHorizontalTextPosition(JMenuItem.RIGHT); + addMouseListener(new MousePopupListener()); + + frame = new JFrame(); + JMenuBar menuBar = new JMenuBar(); + menu = new JMenu("test"); + menuBar.add(menu); + menu.add(new JMenuItem("test", ii)); + menu.add(new JRadioButtonMenuItem("test", ii, true)); + menu.add(new JCheckBoxMenuItem("test", ii, true)); + + frame.setJMenuBar(menuBar); + frame.setContentPane(this); + frame.setSize(300, 300); + frame.setVisible(true); + } + + private class MousePopupListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { showPopup(e); } + @Override + public void mouseClicked(MouseEvent e) { showPopup(e); } + @Override + public void mouseReleased(MouseEvent e) { showPopup(e); } + + private void showPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(MenuMultiresolutionIconTest.this, e.getX(), e.getY()); + } + } + } + + private static boolean is2x() { + + return GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(). + getDefaultTransform().getScaleX() > 1.001; + } + + private boolean eqColors(Color c1, Color c2) { + + int tol = 15; + return ( + Math.abs(c2.getRed() - c1.getRed() ) < tol && + Math.abs(c2.getGreen() - c1.getGreen()) < tol && + Math.abs(c2.getBlue() - c1.getBlue() ) < tol); + } + + private void checkIconColor(Point p, String what) { + + Color expected = is2x() ? C2X : C1X; + Color c = r.getPixelColor(p.x + SZ / 2, p.y + SZ / 2); + if (!eqColors(c, expected)) { + frame.dispose(); + throw new RuntimeException("invalid " + what + "menu item icon " + + "color, expected: " + expected + ", got: " + c); + } + System.out.println(what + "item icon check passed"); + } + + private void doTest() { + + r.waitForIdle(2 * DELAY); + + Point p = getLocationOnScreen(); + r.mouseMove(p.x + getWidth() / 4, p.y + getHeight() / 4); + r.waitForIdle(DELAY); + r.click(InputEvent.BUTTON3_DOWN_MASK); + r.waitForIdle(DELAY); + p = popupItem.getLocationOnScreen(); + checkIconColor(p, "popup "); + r.waitForIdle(DELAY); + + p = menu.getLocationOnScreen(); + r.mouseMove(p.x + menu.getWidth() / 2, p.y + menu.getHeight() / 2); + r.waitForIdle(DELAY); + r.click(); + p = menu.getItem(0).getLocationOnScreen(); + checkIconColor(p, ""); + r.waitForIdle(DELAY); + + p = menu.getItem(1).getLocationOnScreen(); + checkIconColor(p, "radiobutton "); + r.waitForIdle(DELAY); + + p = menu.getItem(2).getLocationOnScreen(); + checkIconColor(p, "checkbox "); + r.waitForIdle(DELAY); + + frame.dispose(); + } + + public static void main(String s[]) throws Exception { + + // TODO: remove is2x() after JDK-8150844 fix + if (is2x() == "2".equals(System.getProperty(SCALE))) { + (new MenuMultiresolutionIconTest()).doTest(); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,41 @@ + + + + + MultiResolutionTrayIconTest + + + + +To run test please push "Start" (if system tray is not supported, push "Pass"). + +Two tray icons will appear (note: sometimes they can go to the tray icons pool). + +Please check if both of them have correct size and +the same colouring (white rectagle in a blue mount). In this case please push "Pass". + +Otherwise (if the 2nd red-white small icon appears) please push "Fail". + + + diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 8150176 + @ignore 8150176 + @summary Check if correct resolution variant is used for tray icon. + @author a.stepanov + @run applet/manual=yesno MultiResolutionTrayIconTest.html +*/ + + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; + + +public class MultiResolutionTrayIconTest extends Applet { + + private SystemTray tray; + private TrayIcon icon, iconMRI; + + public void init() { this.setLayout(new BorderLayout()); } + + public void start() { + + boolean trayIsSupported = SystemTray.isSupported(); + Button b = new Button("Start"); + if (trayIsSupported) { + + prepareIcons(); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { doTest(); } + }); + } else { + b.setLabel("not supported"); + b.setEnabled(false); + System.out.println("system tray is not supported"); + } + add(b, BorderLayout.CENTER); + + validate(); + setVisible(true); + } + + private BufferedImage generateImage(int w, int h, Color c) { + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, w, h); + g.setColor(Color.WHITE); + int r = (Math.min(w, h) >= 8) ? 3 : 1; + g.fillRect(r, r, w - 2 * r, h - 2 * r); + return img; + } + + private void prepareIcons() { + + tray = SystemTray.getSystemTray(); + Dimension d = tray.getTrayIconSize(); + int w = d.width, h = d.height; + + BufferedImage img = generateImage(w, h, Color.BLUE); + // use wrong icon size for "nok" + BufferedImage nok = generateImage(w / 2 + 2, h / 2 + 2, Color.RED); + BaseMultiResolutionImage mri = + new BaseMultiResolutionImage(new BufferedImage[] {nok, img}); + icon = new TrayIcon(img); + iconMRI = new TrayIcon(mri); + } + + private void doTest() { + + if (tray.getTrayIcons().length > 0) { return; } // icons were added already + try { + tray.add(icon); + tray.add(iconMRI); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void stop() { + + // check for null, just in case + if (tray != null) { + tray.remove(icon); + tray.remove(iconMRI); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,125 @@ +/* + * 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.awt.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.KeyboardFocusManager; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 8138749 + * @summary PrinterJob.printDialog() does not support multi-mon, + * always displayed on primary + * @run main/manual MultiMonPrintDlgTest + */ +public class MultiMonPrintDlgTest implements ActionListener { + + Frame primaryFrame = null; + Frame secFrame = null; + GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getScreenDevices(); + + public MultiMonPrintDlgTest() throws Exception { + if (gd.length <= 1) { + System.out.println("This test should be run only on dual-monitor systems. Aborted!!"); + return; + } + + String[] instructions = + { + " This test should be running on a dual-monitor setup.", + "A frame will be created on each of the 2 monitor. ", + "Click the Print button on the frame displayed in the non-default monitor.", + "Please verify that page dialog followed by print dialog ", + " is displayed in the same screen", + "where the frame is located ie, in the non-default monitor.", + }; + + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog( + (Component) null, + instructions, + "information", JOptionPane.INFORMATION_MESSAGE); + }); + GraphicsDevice defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + int x = 0; + Frame f = null; + for (x = 0; x < gd.length; x ++) { + if (gd[x] != defDev) { + secFrame = new Frame("Screen " + x + " - secondary", gd[x].getDefaultConfiguration()); + f = secFrame; + } else { + primaryFrame = new Frame("Screen " + x + " - primary", gd[x].getDefaultConfiguration()); + f = primaryFrame; + } + Button b = new Button("Print"); + b.addActionListener(this); + f.add("South", b); + f.addWindowListener (new WindowAdapter() { + public void windowClosing(WindowEvent we) { + ((Window) we.getSource()).dispose(); + } + }); + f.setSize(200, 200); + f.setVisible(true); + } + } + + public void actionPerformed (ActionEvent ae) { + try { + javax.print.attribute.PrintRequestAttributeSet prSet = + new javax.print.attribute.HashPrintRequestAttributeSet(); + java.awt.print.PrinterJob.getPrinterJob().pageDialog(prSet); + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + int dialogButton = JOptionPane.showConfirmDialog (w, + "Did the pageDialog shown in non-default monitor?", + null, JOptionPane.YES_NO_OPTION); + if(dialogButton == JOptionPane.NO_OPTION) { + throw new RuntimeException("PageDialog is shown in wrong monitor"); + } + java.awt.print.PrinterJob.getPrinterJob().printDialog(prSet); + dialogButton = JOptionPane.showConfirmDialog (w, + "Did the printDialog shown in non-default monitor?", + null, JOptionPane.YES_NO_OPTION); + if(dialogButton == JOptionPane.NO_OPTION) { + throw new RuntimeException("PrintDialog is shown in wrong monitor"); + } + } finally { + primaryFrame.dispose(); + secFrame.dispose(); + } + } + + public static void main (String args[]) throws Exception { + MultiMonPrintDlgTest test = new MultiMonPrintDlgTest(); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/lang/invoke/t8150782/TestAccessClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/invoke/t8150782/TestAccessClass.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @compile TestAccessClass.java TestCls.java + * @run testng/othervm -ea -esa test.java.lang.invoke.t8150782.TestAccessClass + */ +package test.java.lang.invoke.t8150782; + +import java.lang.invoke.*; + +import static java.lang.invoke.MethodHandles.*; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +public class TestAccessClass { + + private static boolean initializedClass1; + + private static class Class1 { + static { + initializedClass1 = true; + } + } + + @Test + public void initializerNotRun() throws IllegalAccessException { + lookup().accessClass(Class1.class); + assertFalse(initializedClass1); + } + + @Test + public void returnsSameClass() throws IllegalAccessException, ClassNotFoundException { + Class aClass = lookup().accessClass(Class1.class); + assertEquals(Class1.class, aClass); + } + + @DataProvider + Object[][] illegalAccessAccess() { + return new Object[][] { + {publicLookup(), Class1.class}, + {publicLookup(), TestCls.getPrivateSIC()} + }; + } + + @Test(dataProvider = "illegalAccessAccess", expectedExceptions = {IllegalAccessException.class}) + public void illegalAccessExceptionTest(Lookup lookup, Class klass) throws IllegalAccessException, ClassNotFoundException { + lookup.accessClass(klass); + } + + @Test + public void okAccess() throws IllegalAccessException { + lookup().accessClass(TestCls.getPrivateSIC()); + } + +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/lang/invoke/t8150782/TestCls.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/invoke/t8150782/TestCls.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 test.java.lang.invoke.t8150782; + +import static java.lang.invoke.MethodHandles.*; + +public class TestCls { + + public static final Lookup LOOKUP = lookup(); + + private static class PrivateSIC {} + public static Class getPrivateSIC() { return PrivateSIC.class; } + public static Lookup getLookupForPrivateSIC() { return lookup(); } + +} + diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/lang/invoke/t8150782/TestFindClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/invoke/t8150782/TestFindClass.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @compile TestFindClass.java TestCls.java + * @run testng/othervm -ea -esa test.java.lang.invoke.t8150782.TestFindClass + */ +package test.java.lang.invoke.t8150782; + +import java.lang.invoke.*; + +import static java.lang.invoke.MethodHandles.*; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +public class TestFindClass { + + private static final String PACKAGE_PREFIX = "test.java.lang.invoke.t8150782."; + + private static boolean initializedClass1; + + private static class Class1 { + static { + initializedClass1 = true; + } + } + + @Test + public void initializerNotRun() throws IllegalAccessException, ClassNotFoundException { + lookup().findClass(PACKAGE_PREFIX + "TestFindClass$Class1"); + assertFalse(initializedClass1); + } + + @Test + public void returnsRequestedClass() throws IllegalAccessException, ClassNotFoundException { + Class aClass = lookup().findClass(PACKAGE_PREFIX + "TestFindClass$Class1"); + assertEquals(Class1.class, aClass); + } + + @Test(expectedExceptions = {ClassNotFoundException.class}) + public void classNotFoundExceptionTest() throws IllegalAccessException, ClassNotFoundException { + lookup().findClass(PACKAGE_PREFIX + "TestFindClass$NonExistent"); + } + + @DataProvider + Object[][] illegalAccessFind() { + return new Object[][] { + {publicLookup(), PACKAGE_PREFIX + "TestFindClass$Class1"}, + {publicLookup(), PACKAGE_PREFIX + "TestCls$PrivateSIC"} + }; + } + + /** + * Assertion: @throws IllegalAccessException if the class is not accessible, using the allowed access modes. + */ + @Test(dataProvider = "illegalAccessFind", expectedExceptions = {ClassNotFoundException.class}) + public void illegalAccessExceptionTest(Lookup lookup, String className) throws IllegalAccessException, ClassNotFoundException { + lookup.findClass(className); + } + + @Test + public void okAccess() throws IllegalAccessException, ClassNotFoundException { + lookup().findClass(PACKAGE_PREFIX + "TestCls$PrivateSIC"); + } + +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/lang/invoke/t8150782/TestLookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/invoke/t8150782/TestLookup.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @compile TestLookup.java TestCls.java + * @run testng/othervm -ea -esa test.java.lang.invoke.t8150782.TestLookup + */ +package test.java.lang.invoke.t8150782; + +import org.testng.annotations.Test; + +import static java.lang.invoke.MethodHandles.*; + +import static org.testng.AssertJUnit.*; + +public class TestLookup { + + @Test + public void testClassLoaderChange() { + Lookup lookup = lookup(); + assertNotNull(lookup.lookupClass().getClassLoader()); + Lookup lookup2 = lookup.in(Object.class); + assertNull(lookup2.lookupClass().getClassLoader()); + } + + @Test(expectedExceptions = {ClassNotFoundException.class}) + public void testPublicCannotLoadUserClass() throws IllegalAccessException, ClassNotFoundException { + Lookup lookup = publicLookup(); + lookup.findClass("test.java.lang.invoke.t8150782.TestCls"); + } + + @Test + public void testPublicCanLoadSystemClass() throws IllegalAccessException, ClassNotFoundException { + Lookup lookup = publicLookup(); + lookup.findClass("java.util.HashMap"); + } + + @Test + public void testPublicInChangesClassLoader() { + Lookup lookup = publicLookup(); + assertNull(lookup.lookupClass().getClassLoader()); + Lookup lookup2 = lookup.in(TestCls.class); + assertNotNull(lookup2.lookupClass().getClassLoader()); + } + +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/nio/channels/Selector/ChangingInterests.java --- a/jdk/test/java/nio/channels/Selector/ChangingInterests.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/java/nio/channels/Selector/ChangingInterests.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* @test * @bug 7200742 + * @key intermittent * @summary Test that Selector doesn't spin when changing interest ops */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java --- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatter.java Mon Mar 21 11:21:08 2016 +0100 @@ -79,19 +79,24 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.time.chrono.Chronology; import java.time.chrono.ThaiBuddhistChronology; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DecimalStyle; import java.time.format.SignStyle; +import java.time.format.TextStyle; +import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.util.Locale; import java.util.function.Function; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Test DateTimeFormatter. + * @bug 8085887 */ @Test public class TestDateTimeFormatter { @@ -196,4 +201,75 @@ assertTrue(msg.contains("11:30:56"), msg); } + @DataProvider(name="nozone_exception_cases") + Object[][] exceptionCases() { + return new Object[][] { + {LocalDateTime.of(2000, 1, 1, 1, 1), "z", "ZoneId"}, + {OffsetDateTime.of(2000, 1, 1, 3, 3, 3, 0, ZoneOffset.ofTotalSeconds(60)), "z", "ZoneId"}, + }; + } + + // Test cases that should throw an exception with a cogent message + // containing the Type being queried and the Temporal being queried. + @Test(dataProvider="nozone_exception_cases") + public void test_throws_message(Temporal temporal, String pattern, String queryName) { + DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern); + try { + fmt.format(temporal); + fail("Format using \"" + pattern + "\" with " + + temporal + " should have failed"); + } catch (DateTimeException dte) { + String msg = dte.getMessage(); + // Verify message contains the type that is missing and the temporal value + assertTrue(msg.contains(queryName), + String.format("\"%s\" missing from %s", queryName, msg)); + String s = temporal.toString(); + assertTrue(msg.contains(s), + String.format("\"%s\" missing from %s", s, msg)); + } + + } + + // Test cases that should throw an exception with a cogent message when missing the Chronology + @Test + public void test_throws_message_chrono() { + Chronology chrono = ThaiBuddhistChronology.INSTANCE; + DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneId().toFormatter() + .withChronology(chrono); + LocalTime now = LocalTime.now(); + try { + fmt.format(now); + fail("Format using appendZoneId() should have failed"); + } catch (DateTimeException dte) { + String msg = dte.getMessage(); + // Verify message contains the type that is missing and the temporal value + assertTrue(msg.contains("ZoneId"), + String.format("\"%s\" missing from %s", "ZoneId", msg)); + assertTrue(msg.contains(chrono.toString()), + String.format("\"%s\" missing from %s", chrono.toString(), msg)); + } + + } + + // Test cases that should throw an exception with a cogent message when missing the ZoneId + @Test + public void test_throws_message_zone() { + ZoneId zone = ZoneId.of("Pacific/Honolulu"); + DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendChronologyId().toFormatter() + .withZone(zone); + LocalTime now = LocalTime.now(); + try { + fmt.format(now); + fail("Format using appendChronologyId() should have failed"); + } catch (DateTimeException dte) { + String msg = dte.getMessage(); + // Verify message contains the type that is missing and the temporal value + assertTrue(msg.contains("Chronology"), + String.format("\"%s\" missing from %s", "Chronology", msg)); + assertTrue(msg.contains(zone.toString()), + String.format("\"%s\" missing from %s", zone.toString(), msg)); + } + + } + } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/java/util/TimeZone/Bug6772689.java --- a/jdk/test/java/util/TimeZone/Bug6772689.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/java/util/TimeZone/Bug6772689.java Mon Mar 21 11:21:08 2016 +0100 @@ -24,6 +24,7 @@ /* * @test * @bug 6772689 + * @key intermittent * @summary Test for standard-to-daylight transitions at midnight: * date stays on the given day. */ diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileWriter; +import javax.sound.sampled.spi.FormatConversionProvider; + +import static java.util.ServiceLoader.load; +import static javax.sound.sampled.AudioFileFormat.Type.AIFC; +import static javax.sound.sampled.AudioFileFormat.Type.AIFF; +import static javax.sound.sampled.AudioFileFormat.Type.AU; +import static javax.sound.sampled.AudioFileFormat.Type.SND; +import static javax.sound.sampled.AudioFileFormat.Type.WAVE; +import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED; + +/** + * @test + * @bug 8038139 + */ +public final class FrameLengthAfterConversion { + + /** + * We will try to use all formats, in this case all our providers will be + * covered by supported/unsupported formats. + */ + private static final List formats = new ArrayList<>(23000); + + private static final AudioFormat.Encoding[] encodings = { + AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW, + AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test") + }; + + private static final int[] sampleBits = { + 1, 4, 8, 11, 16, 20, 24, 32 + }; + + private static final int[] channels = { + 1, 2, 3, 4, 5 + }; + + private static final AudioFileFormat.Type[] types = { + WAVE, AU, AIFF, AIFC, SND, + new AudioFileFormat.Type("TestName", "TestExt") + }; + + private static final int FRAME_LENGTH = 10; + + static { + for (final int sampleSize : sampleBits) { + for (final int channel : channels) { + for (final AudioFormat.Encoding enc : encodings) { + final int frameSize = ((sampleSize + 7) / 8) * channel; + formats.add(new AudioFormat(enc, 44100, sampleSize, channel, + frameSize, 44100, true)); + formats.add(new AudioFormat(enc, 44100, sampleSize, channel, + frameSize, 44100, false)); + } + } + } + } + + public static void main(final String[] args) { + for (final FormatConversionProvider fcp : load( + FormatConversionProvider.class)) { + System.out.println("fcp = " + fcp); + for (final AudioFormat from : formats) { + for (final AudioFormat to : formats) { + testAfterConversion(fcp, to, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToStream(afw, type, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToFile(afw, type, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToFile(afw, type, getStream(from, false)); + } + } + } + } + + /** + * Verifies the frame length after the stream was saved/read to/from + * stream. + */ + private static void testAfterSaveToStream(final AudioFileWriter afw, + final AudioFileFormat.Type type, + final AudioInputStream ais) { + try { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + afw.write(ais, type, out); + final InputStream input = new ByteArrayInputStream( + out.toByteArray()); + validate(AudioSystem.getAudioInputStream(input).getFrameLength()); + } catch (IllegalArgumentException | UnsupportedAudioFileException + | IOException ignored) { + } + } + + /** + * Verifies the frame length after the stream was saved/read to/from file. + */ + private static void testAfterSaveToFile(final AudioFileWriter afw, + final AudioFileFormat.Type type, + AudioInputStream ais) { + try { + final File temp = File.createTempFile("sound", ".tmp"); + temp.deleteOnExit(); + afw.write(ais, type, temp); + ais = AudioSystem.getAudioInputStream(temp); + final long frameLength = ais.getFrameLength(); + ais.close(); + temp.delete(); + validate(frameLength); + } catch (IllegalArgumentException | UnsupportedAudioFileException + | IOException ignored) { + } + } + + /** + * Verifies the frame length after the stream was converted to other + * stream. + * + * @see FormatConversionProvider#getAudioInputStream(AudioFormat, + * AudioInputStream) + */ + private static void testAfterConversion(final FormatConversionProvider fcp, + final AudioFormat to, + final AudioInputStream ais) { + if (fcp.isConversionSupported(to, ais.getFormat())) { + validate(fcp.getAudioInputStream(to, ais).getFrameLength()); + } + } + + /** + * Throws an exception if the frameLength is specified and is not equal to + * the gold value. + */ + private static void validate(final long frameLength) { + if (frameLength != FRAME_LENGTH) { + System.err.println("Expected: " + FRAME_LENGTH); + System.err.println("Actual: " + frameLength); + throw new RuntimeException(); + } + } + + private static AudioInputStream getStream(final AudioFormat format, + final boolean frameLength) { + final int dataSize = FRAME_LENGTH * format.getFrameSize(); + final InputStream in = new ByteArrayInputStream(new byte[dataSize]); + if (frameLength) { + return new AudioInputStream(in, format, FRAME_LENGTH); + } else { + return new AudioInputStream(in, format, NOT_SPECIFIED); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8081722 + * @summary Provide public API for file hierarchy provided by + * sun.awt.shell.ShellFolder + * @author Semyon Sadetsky + * @run main ShellFolderQueriesTest + */ + +import sun.awt.OSInfo; + +import javax.swing.filechooser.FileSystemView; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +public class ShellFolderQueriesTest { + static final String HOME = System.getProperty("user.home"); + static final FileSystemView fsv = FileSystemView.getFileSystemView(); + + + static String scriptBeg = + "set WshShell = WScript.CreateObject(\"WScript.Shell\")\n" + + "set oShellLink = WshShell.CreateShortcut(\"shortcut.lnk\")\n" + + "oShellLink.TargetPath = \""; + static String scriptEnd = "\"\noShellLink.WindowStyle = 1\noShellLink.Save"; + + public static void main(String[] args) throws Exception { + if(OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { + testGet(); + testLink(); + } else { + testGet(); + } + System.out.println("ok"); + } + + private static void testLink() throws IOException, InterruptedException { + // Create and execute VBS script to create a link + File file = createVbsScript(scriptBeg + HOME + scriptEnd); + Runtime.getRuntime().exec("cscript " + file.getName(), null, + file.getParentFile()).waitFor(); + file.delete(); + + File link = new File(file.getParentFile(), "shortcut.lnk"); + if (!fsv.isLink(link)) { + link.delete(); + throw new RuntimeException("Link is not detected"); + } + + File location = fsv.getLinkLocation(link); + if (!location.getAbsolutePath().equals(HOME)) { + link.delete(); + throw new RuntimeException("Link location " + location + + " is wrong"); + } + link.delete(); + + + link = File.createTempFile("test", ".tst"); + + if (fsv.isLink(link)) { + link.delete(); + throw new RuntimeException("File is not a link"); + } + + try { + location = fsv.getLinkLocation(link); + if (location != null) { + link.delete(); + throw new RuntimeException("Not a link, should return null"); + } + } + catch (FileNotFoundException e) { + } + link.delete(); + } + + private static File createVbsScript(String script) throws IOException { + File file = File.createTempFile("test", ".vbs"); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(script.getBytes()); + fos.close(); + return file; + } + + private static void testGet() { + File[] files = fsv.getChooserComboBoxFiles(); + for (File file : files) { + if (fsv.isLink(file)) { + throw new RuntimeException( + "Link shouldn't be in FileChooser combobox, " + + file.getPath()); + } + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,275 @@ +/* + * 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 8146321 + * @summary verifies JInternalFrame Icon and ImageIcon + * @library ../../regtesthelpers + * @build Util + * @run main JInternalFrameIconTest + */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class JInternalFrameIconTest { + + private static JFrame frame; + private static JDesktopPane desktopPane; + private static JInternalFrame internalFrame; + private static ImageIcon titleImageIcon; + private static Icon titleIcon; + private static BufferedImage imageIconImage; + private static BufferedImage iconImage; + + private static Robot robot; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.delay(2000); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName()); + } + + } + + private static void executeCase(String lookAndFeelString) throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createImageIconUI(lookAndFeelString); + robot.delay(1000); + getImageIconBufferedImage(); + robot.waitForIdle(); + cleanUp(); + robot.waitForIdle(); + + createIconUI(lookAndFeelString); + robot.delay(1000); + getIconBufferedImage(); + robot.waitForIdle(); + cleanUp(); + robot.waitForIdle(); + testIfSame(); + robot.waitForIdle(); + } + + } + + private static void createImageIconUI(final String lookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + desktopPane = new JDesktopPane(); + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setTitle(lookAndFeelString); + titleImageIcon = new ImageIcon() { + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + + @Override + public void paintIcon( + Component c, Graphics g, int x, int y) { + g.setColor(java.awt.Color.black); + g.fillRect(x, y, 16, 16); + } + }; + internalFrame.setFrameIcon(titleImageIcon); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void createIconUI(final String lookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + desktopPane = new JDesktopPane(); + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setTitle(lookAndFeelString); + titleIcon = new Icon() { + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + + @Override + public void paintIcon( + Component c, Graphics g, int x, int y) { + g.setColor(java.awt.Color.black); + g.fillRect(x, y, 16, 16); + } + }; + internalFrame.setFrameIcon(titleIcon); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void getImageIconBufferedImage() throws Exception { + Point point = internalFrame.getLocationOnScreen(); + Rectangle rect = internalFrame.getBounds(); + Rectangle captureRect = new Rectangle( + point.x + internalFrame.getInsets().left, + point.y, + rect.width, + internalFrame.getInsets().top); + imageIconImage + = robot.createScreenCapture(captureRect); + } + + private static void getIconBufferedImage() throws Exception { + Point point = internalFrame.getLocationOnScreen(); + Rectangle rect = internalFrame.getBounds(); + Rectangle captureRect = new Rectangle( + point.x + internalFrame.getInsets().left, + point.y, + rect.width, + internalFrame.getInsets().top); + iconImage + = robot.createScreenCapture(captureRect); + } + + private static void testIfSame() throws Exception { + if (!bufferedImagesEqual(imageIconImage, iconImage)) { + System.err.println("ERROR: icon and imageIcon not same."); + } else { + System.out.println("SUCCESS: icon and imageIcon same."); + } + } + + private static boolean bufferedImagesEqual( + BufferedImage bufferedImage1, BufferedImage bufferedImage2) { + boolean flag = true; + + if (bufferedImage1.getWidth() == bufferedImage2.getWidth() + && bufferedImage1.getHeight() == bufferedImage2.getHeight()) { + final int colorTolerance = 25; + final int mismatchTolerance = (int) (0.1 + * bufferedImage1.getWidth() * bufferedImage1.getHeight()); + int mismatchCounter = 0; + for (int x = 0; x < bufferedImage1.getWidth(); x++) { + for (int y = 0; y < bufferedImage1.getHeight(); y++) { + + int color1 = bufferedImage1.getRGB(x, y); + int red1 = (color1 >> 16) & 0x000000FF; + int green1 = (color1 >> 8) & 0x000000FF; + int blue1 = (color1) & 0x000000FF; + + int color2 = bufferedImage2.getRGB(x, y); + int red2 = (color2 >> 16) & 0x000000FF; + int green2 = (color2 >> 8) & 0x000000FF; + int blue2 = (color2) & 0x000000FF; + if (red1 != red2 || green1 != green2 || blue1 != blue2) { + ++mismatchCounter; + if ((Math.abs(red1 - red2) > colorTolerance) + || (Math.abs(green1 - green2) > colorTolerance) + || (Math.abs(blue1 - blue2) > colorTolerance)) { + + flag = false; + } + } + } + } + if (mismatchCounter > mismatchTolerance) { + flag = false; + } + } else { + System.err.println("ERROR: size is different"); + flag = false; + } + return flag; + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + @test + @bug 7126823 + @summary Verify NormalBounds upon iconify/deiconify sequence + @run main NormalBoundsTest + */ +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.beans.PropertyVetoException; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.WindowConstants; + +public class NormalBoundsTest { + + private static JFrame mainFrame; + private static JInternalFrame internalFrame; + private static Rectangle bounds; + + private static void createUI(String lookAndFeelString) { + internalFrame = new JInternalFrame("Internal", true, true, true, true); + internalFrame.setDefaultCloseOperation( + WindowConstants.DO_NOTHING_ON_CLOSE); + internalFrame.setSize(200, 200); + + JDesktopPane desktopPane = new JDesktopPane(); + desktopPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); + desktopPane.add(internalFrame); + + mainFrame = new JFrame(lookAndFeelString); + mainFrame.setSize(640, 480); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.setContentPane(desktopPane); + + mainFrame.setVisible(true); + internalFrame.setVisible(true); + + } + + private static int signWOZero(int i) { + return (i > 0) ? 1 : -1; + } + + private static void mouseMove(Robot robot, Point startPt, Point endPt) { + int dx = endPt.x - startPt.x; + int dy = endPt.y - startPt.y; + + int ax = Math.abs(dx) * 2; + int ay = Math.abs(dy) * 2; + + int sx = signWOZero(dx); + int sy = signWOZero(dy); + + int x = startPt.x; + int y = startPt.y; + + int d = 0; + + if (ax > ay) { + d = ay - ax / 2; + while (true) { + robot.mouseMove(x, y); + robot.delay(50); + + if (x == endPt.x) { + return; + } + if (d >= 0) { + y = y + sy; + d = d - ax; + } + x = x + sx; + d = d + ay; + } + } else { + d = ax - ay / 2; + while (true) { + robot.mouseMove(x, y); + robot.delay(50); + + if (y == endPt.y) { + return; + } + if (d >= 0) { + x = x + sx; + d = d - ay; + } + y = y + sy; + d = d + ax; + } + } + } + + private static void drag(Robot r, Point startPt, Point endPt, int button) { + if (!(button == InputEvent.BUTTON1_MASK + || button == InputEvent.BUTTON2_MASK + || button == InputEvent.BUTTON3_MASK)) { + throw new IllegalArgumentException("invalid mouse button"); + } + + r.mouseMove(startPt.x, startPt.y); + r.mousePress(button); + try { + mouseMove(r, startPt, endPt); + } finally { + r.mouseRelease(button); + } + } + + private static boolean tryLookAndFeel(String lookAndFeelString) { + try { + UIManager.setLookAndFeel(lookAndFeelString); + return true; + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | + InstantiationException | IllegalAccessException e) { + return false; + } + } + + public static void executeTest(Robot robot) throws Exception { + + // Iconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Iconize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // Deiconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Deiconize InternalFrame" + + " Failed"); + } + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Point loc = internalFrame.getLocationOnScreen(); + // Drag Frame + drag(robot, + new Point((int) loc.x + 80, (int) loc.y + 12), + new Point((int) loc.x + 100, (int) loc.y + 40), + InputEvent.BUTTON1_MASK); + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + bounds = internalFrame.getBounds(); + if (!internalFrame.getNormalBounds().equals(bounds)) { + mainFrame.dispose(); + throw new RuntimeException("Invalid NormalBounds"); + } + } + }); + robot.waitForIdle(); + + // Regression Test Bug ID: 4424247 + // Maximize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setMaximum(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Maximize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // Iconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Iconize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // DeIconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("DeIcoize InternalFrame " + + " Failed"); + } + } + }); + robot.waitForIdle(); + + // Restore/Undo Maximize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setMaximum(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Restore InternalFrame " + + " Failed"); + } + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if (!internalFrame.getBounds().equals(bounds)) { + mainFrame.dispose(); + throw new RuntimeException("Regression Test Failed"); + } + } + }); + robot.waitForIdle(); + + mainFrame.dispose(); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + if (tryLookAndFeel(lookAndFeelString)) { + // create UI + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createUI(lookAndFeelString); + } + }); + + robot.waitForIdle(); + executeTest(robot); + } else { + throw new RuntimeException("Setting Look and Feel Failed"); + } + } + + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java --- a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +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.awt.BorderLayout; -import java.awt.Point; -import java.awt.Robot; -import java.awt.event.KeyEvent; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import jdk.testlibrary.OSInfo; - -/** - * @test - * @bug 8033000 - * @author Alexander Scherbatiy - * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI - * @library ../../../../lib/testlibrary - * @build jdk.testlibrary.OSInfo - * @run main bug8033000 - */ -public class bug8033000 { - - private static JScrollPane scrollPane; - private static JTextArea textArea; - private static Point point; - private static final int delta; - - static { - delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30; - } - - public static void main(String[] args) throws Exception { - - Robot robot = new Robot(); - robot.setAutoDelay(50); - - SwingUtilities.invokeAndWait(bug8033000::createAndShowGUI); - robot.waitForIdle(); - - SwingUtilities.invokeAndWait(() -> { - Point locationOnScreen = scrollPane.getLocationOnScreen(); - point = new Point( - locationOnScreen.x + scrollPane.getWidth() / 2, - locationOnScreen.y + scrollPane.getHeight() / 2); - }); - - robot.mouseMove(point.x, point.y); - robot.waitForIdle(); - - // vertical scroll bar is enabled - initScrollPane(true, false); - robot.waitForIdle(); - robot.mouseWheel(delta); - robot.waitForIdle(); - checkScrollPane(true); - - // vertical scroll bar is enabled + shift - initScrollPane(true, false); - robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_SHIFT); - robot.mouseWheel(delta); - robot.keyRelease(KeyEvent.VK_SHIFT); - robot.waitForIdle(); - checkScrollPane(true); - - // horizontal scroll bar is enabled - initScrollPane(false, true); - robot.waitForIdle(); - robot.mouseWheel(delta); - robot.waitForIdle(); - checkScrollPane(false); - - // horizontal scroll bar is enabled + shift - initScrollPane(false, true); - robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_SHIFT); - robot.mouseWheel(delta); - robot.keyRelease(KeyEvent.VK_SHIFT); - robot.waitForIdle(); - checkScrollPane(false); - - // both scroll bars are enabled - initScrollPane(true, true); - robot.waitForIdle(); - robot.mouseWheel(delta); - robot.waitForIdle(); - checkScrollPane(true); - - // both scroll bars are enabled + shift - initScrollPane(true, true); - robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_SHIFT); - robot.mouseWheel(delta); - robot.keyRelease(KeyEvent.VK_SHIFT); - robot.waitForIdle(); - checkScrollPane(false); - } - - static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception { - SwingUtilities.invokeAndWait(() -> { - scrollPane.getVerticalScrollBar().setValue(0); - scrollPane.getHorizontalScrollBar().setValue(0); - - textArea.setRows(vVisible ? 100 : 1); - textArea.setColumns(hVisible ? 100 : 1); - scrollPane.getVerticalScrollBar().setVisible(vVisible); - scrollPane.getHorizontalScrollBar().setVisible(hVisible); - }); - } - - static void checkScrollPane(boolean verticalScrolled) throws Exception { - SwingUtilities.invokeAndWait(() -> { - - if (verticalScrolled) { - if (scrollPane.getVerticalScrollBar().getValue() == 0 - || scrollPane.getHorizontalScrollBar().getValue() != 0) { - throw new RuntimeException("Wrong vertical scrolling!"); - } - } else { - if (scrollPane.getVerticalScrollBar().getValue() != 0 - || scrollPane.getHorizontalScrollBar().getValue() == 0) { - throw new RuntimeException("Wrong horizontal scrolling!"); - } - } - }); - } - - static void createAndShowGUI() { - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setSize(300, 300); - textArea = new JTextArea("Hello World!"); - scrollPane = new JScrollPane(textArea); - JPanel panel = new JPanel(new BorderLayout()); - panel.add(scrollPane, BorderLayout.CENTER); - frame.getContentPane().add(panel); - frame.setVisible(true); - } -} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +import jdk.testlibrary.OSInfo; + +/** + * @test + * @bug 8033000 8147994 + * @author Alexander Scherbatiy + * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI + * @library ../../../../lib/testlibrary + * @build jdk.testlibrary.OSInfo + * @run main HorizontalMouseWheelOnShiftPressed + */ +public class HorizontalMouseWheelOnShiftPressed { + + private static JScrollPane scrollPane; + private static JTextArea textArea; + private static Point point; + private static final int delta; + private static JFrame frame; + + static { + delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30; + } + + public static void main(String[] args) throws Exception { + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait( + HorizontalMouseWheelOnShiftPressed::createAndShowGUI); + robot.waitForIdle(); + try { + test(robot); + } finally { + frame.dispose(); + } + } + + private static void test(Robot robot) throws Exception { + SwingUtilities.invokeAndWait(() -> { + Point locationOnScreen = scrollPane.getLocationOnScreen(); + point = new Point( + locationOnScreen.x + scrollPane.getWidth() / 2, + locationOnScreen.y + scrollPane.getHeight() / 2); + }); + + robot.mouseMove(point.x, point.y); + robot.waitForIdle(); + + // vertical scroll bar is enabled + initScrollPane(true, false); + robot.waitForIdle(); + robot.mouseWheel(delta); + robot.waitForIdle(); + checkScrollPane(true, false); + + // vertical scroll bar is enabled + shift + initScrollPane(true, false); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mouseWheel(delta); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + checkScrollPane(false, false); + + // horizontal scroll bar is enabled + initScrollPane(false, true); + robot.waitForIdle(); + robot.mouseWheel(delta); + robot.waitForIdle(); + checkScrollPane(false, true); + + // horizontal scroll bar is enabled + shift + initScrollPane(false, true); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mouseWheel(delta); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + checkScrollPane(false, true); + + // both scroll bars are enabled + initScrollPane(true, true); + robot.waitForIdle(); + robot.mouseWheel(delta); + robot.waitForIdle(); + checkScrollPane(true, false); + + // both scroll bars are enabled + shift + initScrollPane(true, true); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mouseWheel(delta); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + checkScrollPane(false, true); + } + + static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception { + SwingUtilities.invokeAndWait(() -> { + scrollPane.getVerticalScrollBar().setValue(0); + scrollPane.getHorizontalScrollBar().setValue(0); + + textArea.setRows(vVisible ? 100 : 1); + textArea.setColumns(hVisible ? 100 : 1); + scrollPane.getVerticalScrollBar().setVisible(vVisible); + scrollPane.getHorizontalScrollBar().setVisible(hVisible); + }); + } + + static void checkScrollPane(boolean verticalScrolled, + boolean horizontalScrolled) throws Exception { + SwingUtilities.invokeAndWait(() -> { + + if (verticalScrolled) { + if (scrollPane.getVerticalScrollBar().getValue() == 0) { + throw new RuntimeException("Wrong vertical scrolling!"); + } + } else{ + if (scrollPane.getVerticalScrollBar().getValue() != 0) { + throw new RuntimeException("Wrong vertical scrolling!"); + } + } + if (horizontalScrolled) { + if (scrollPane.getHorizontalScrollBar().getValue() == 0) { + throw new RuntimeException("Wrong horizontal scrolling!"); + } + } else { + if (scrollPane.getHorizontalScrollBar().getValue() != 0) { + throw new RuntimeException("Wrong horizontal scrolling!"); + } + } + }); + } + + static void createAndShowGUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + textArea = new JTextArea("Hello World!"); + scrollPane = new JScrollPane(textArea); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(scrollPane, BorderLayout.CENTER); + frame.getContentPane().add(panel); + frame.setVisible(true); + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.UIManager; +import javax.swing.table.JTableHeader; + +/** + * @test + * @summary Tests whether getTableCellRendererComponent() method handles + * null table parameter + * @bug 8020039 + * @run main TableHeaderRendererExceptionTest + */ +public class TableHeaderRendererExceptionTest { + + public static void main(String[] args) throws Throwable { + //Execute test for all supported look and feels + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + + UIManager.setLookAndFeel(lookAndFeelString); + + // Test getTableCellRendererComponent method by passing null table + JTableHeader header = new JTableHeader(); + + header.getDefaultRenderer().getTableCellRendererComponent(null, + " test ", true, true, -1, 0); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java --- a/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,16 +23,15 @@ /* @test - @bug 8056151 + @bug 8056151 8131751 @summary Switching to GTK L&F on-the-fly leads to X Window System error RenderBadPicture @run main/othervm -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel -Dsun.java2d.xrender=T RenderBadPictureCrash */ - import java.awt.Color; +import java.awt.GraphicsDevice; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.SwingUtilities; - import javax.swing.UIManager; public class RenderBadPictureCrash { @@ -41,7 +40,10 @@ SwingUtilities.invokeAndWait(() -> { JFrame f = new JFrame(); f.setUndecorated(true); - f.setBackground(new Color(0, 0, 0, 0)); + GraphicsDevice gd = f.getGraphicsConfiguration().getDevice(); + if (gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) { + f.setBackground(new Color(0, 0, 0, 0)); + } f.setSize(200, 300); f.setVisible(true); diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/jdk/internal/misc/Unsafe/CopyCommon.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/internal/misc/Unsafe/CopyCommon.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,607 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.internal.misc.Unsafe; +import java.lang.reflect.Field; + +/** + * Helper class to support testing of Unsafe.copyMemory and Unsafe.copySwapMemory + */ +public class CopyCommon { + private static final boolean DEBUG = Boolean.getBoolean("CopyCommon.DEBUG"); + + public static final long KB = 1024; + public static final long MB = KB * 1024; + public static final long GB = MB * 1024; + + static final int SMALL_COPY_SIZE = 32; + static final int BASE_ALIGNMENT = 16; + + protected static final Unsafe UNSAFE; + + static { + try { + Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + static long alignDown(long value, long alignment) { + return value & ~(alignment - 1); + } + + static long alignUp(long value, long alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + + static boolean isAligned(long value, long alignment) { + return value == alignDown(value, alignment); + } + + CopyCommon() { + } + + /** + * Generate verification data for a given offset + * + * The verification data is used to verify that the correct bytes + * have indeed been copied and byte swapped. + * + * The data is generated based on the offset (in bytes) into the + * source buffer. For a native buffer the offset is relative to + * the base pointer. For a heap array it is relative to the + * address of the first array element. + * + * This method will return the result of doing an elementSize byte + * read starting at offset (in bytes). + * + * @param offset offset into buffer + * @param elemSize size (in bytes) of the element + * + * @return the verification data, only the least significant + * elemSize*8 bits are set, zero extended + */ + private long getVerificationDataForOffset(long offset, long elemSize) { + byte[] bytes = new byte[(int)elemSize]; + + for (long i = 0; i < elemSize; i++) { + bytes[(int)i] = (byte)(offset + i); + } + + long o = UNSAFE.arrayBaseOffset(byte[].class); + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o)); + case 8: return UNSAFE.getLongUnaligned(bytes, o); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Verify byte swapped data + * + * @param ptr the data to verify + * @param srcOffset the srcOffset (in bytes) from which the copy started, + * used as key to regenerate the verification data + * @param dstOffset the offset (in bytes) in the array at which to start + * the verification, relative to the first element in the array + * @param size size (in bytes) of data to to verify + * @param elemSize size (in bytes) of the individual array elements + * + * @throws RuntimeException if an error is found + */ + private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) { + for (long offset = 0; offset < size; offset += elemSize) { + long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize); + long expected = byteSwap(expectedUnswapped, elemSize); + + long actual = getArrayElem(ptr, dstOffset + offset, elemSize); + + if (expected != actual) { + throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) + + " dstOffset: 0x" + Long.toHexString(dstOffset) + + " size: 0x" + Long.toHexString(size) + + " offset: 0x" + Long.toHexString(offset) + + " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + /** + * Initialize an array with verification friendly data + * + * @param ptr pointer to the data to initialize + * @param size size (in bytes) of the data + * @param elemSize size (in bytes) of the individual elements + */ + private void initVerificationData(GenericPointer ptr, long size, long elemSize) { + for (long offset = 0; offset < size; offset++) { + byte data = (byte)getVerificationDataForOffset(offset, 1); + + if (ptr.isOnHeap()) { + UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data); + } else { + UNSAFE.putByte(ptr.getOffset() + offset, data); + } + } + } + + /** + * Allocate a primitive array + * + * @param size size (in bytes) of all the array elements (elemSize * length) + * @param elemSize the size of the array elements + * + * @return a newly allocated primitive array + */ + Object allocArray(long size, long elemSize) { + int length = (int)(size / elemSize); + + switch ((int)elemSize) { + case 1: return new byte[length]; + case 2: return new short[length]; + case 4: return new int[length]; + case 8: return new long[length]; + default: + throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the value of a primitive array entry + * + * @param ptr pointer to the data + * @param offset offset (in bytes) of the array element, relative to the first element in the array + * + * @return the array element, as an unsigned long + */ + private long getArrayElem(GenericPointer ptr, long offset, long elemSize) { + if (ptr.isOnHeap()) { + Object o = ptr.getObject(); + int index = (int)(offset / elemSize); + + if (o instanceof short[]) { + short[] arr = (short[])o; + return Short.toUnsignedLong(arr[index]); + } else if (o instanceof int[]) { + int[] arr = (int[])o; + return Integer.toUnsignedLong(arr[index]); + } else if (o instanceof long[]) { + long[] arr = (long[])o; + return arr[index]; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } else { + long addr = ptr.getOffset() + offset; + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr)); + case 8: return UNSAFE.getLongUnaligned(null, addr); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + } + + private void putValue(long addr, long elemSize, long value) { + switch ((int)elemSize) { + case 1: UNSAFE.putByte(addr, (byte)value); break; + case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break; + case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break; + case 8: UNSAFE.putLongUnaligned(null, addr, value); break; + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the size of the elements for an array + * + * @param o a primitive heap array + * + * @return the size (in bytes) of the individual array elements + */ + private long getArrayElemSize(Object o) { + if (o instanceof short[]) { + return 2; + } else if (o instanceof int[]) { + return 4; + } else if (o instanceof long[]) { + return 8; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } + + /** + * Byte swap a value + * + * @param value the value to swap, only the bytes*8 least significant bits are used + * @param size size (in bytes) of the value + * + * @return the byte swapped value in the bytes*8 least significant bits + */ + private long byteSwap(long value, long size) { + switch ((int)size) { + case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value)); + case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value)); + case 8: return Long.reverseBytes(value); + default: throw new IllegalArgumentException("Invalid element size: " + size); + } + } + + /** + * Verify data which has *not* been byte swapped + * + * @param ptr the data to verify + * @param startOffset the offset (in bytes) at which to start the verification + * @param size size (in bytes) of the data to verify + * + * @throws RuntimeException if an error is found + */ + private void verifyUnswappedData(GenericPointer ptr, long startOffset, long srcOffset, long size) { + for (long i = 0; i < size; i++) { + byte expected = (byte)getVerificationDataForOffset(srcOffset + i, 1); + + byte actual; + if (ptr.isOnHeap()) { + actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + startOffset + i); + } else { + actual = UNSAFE.getByte(ptr.getOffset() + startOffset + i); + } + + if (expected != actual) { + throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) + + " srcOffset: 0x" + Long.toHexString(srcOffset) + + " size: 0x" + Long.toHexString(size) + + " i: 0x" + Long.toHexString(i) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + + /** + * Copy and byte swap data from the source to the destination + * + * This method will pre-populate the whole source and destination + * buffers with verification friendly data. It will then copy data + * to fill part of the destination buffer with data from the + * source, optionally byte swapping the copied elements on the + * fly. Some space (padding) will be left before and after the + * data in the destination buffer, which should not be + * touched/overwritten by the copy call. + * + * Note: Both source and destination buffers will be overwritten! + * + * @param src source buffer to copy from + * @param srcOffset the offset (in bytes) in the source buffer, relative to + * the first array element, at which to start reading data + * @param dst destination buffer to copy to + * @param dstOffset the offset (in bytes) in the destination + * buffer, relative to the first array element, at which to + * start writing data + * @param bufSize the size (in bytes) of the src and dst arrays + * @param copyBytes the size (in bytes) of the copy to perform, + * must be a multiple of elemSize + * @param elemSize the size (in bytes) of the elements + * @param swap true if elements should be byte swapped + * + * @throws RuntimeException if an error is found + */ + void testCopyGeneric(GenericPointer src, long srcOffset, + GenericPointer dst, long dstOffset, + long bufSize, long copyBytes, long elemSize, boolean swap) { + if (swap) { + if (!isAligned(copyBytes, elemSize)) { + throw new IllegalArgumentException( + "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + } + + if (srcOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + if (dstOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + + // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes) + initVerificationData(src, bufSize, elemSize); + if (!src.equals(dst)) { + initVerificationData(dst, bufSize, elemSize); + } + + if (DEBUG) { + System.out.println("===before==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + if (swap) { + // Copy & swap data into the middle of the destination buffer + UNSAFE.copySwapMemory(src.getObject(), + src.getOffset() + srcOffset, + dst.getObject(), + dst.getOffset() + dstOffset, + copyBytes, + elemSize); + } else { + // Copy & swap data into the middle of the destination buffer + UNSAFE.copyMemory(src.getObject(), + src.getOffset() + srcOffset, + dst.getObject(), + dst.getOffset() + dstOffset, + copyBytes); + } + + if (DEBUG) { + System.out.println("===after==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Verify the the front padding is unchanged + verifyUnswappedData(dst, 0, 0, dstOffset); + + if (swap) { + // Verify swapped data + verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize); + } else { + // Verify copied/unswapped data + verifyUnswappedData(dst, dstOffset, srcOffset, copyBytes); + } + + // Verify that the back padding is unchanged + long frontAndCopyBytes = dstOffset + copyBytes; + long trailingBytes = bufSize - frontAndCopyBytes; + verifyUnswappedData(dst, frontAndCopyBytes, frontAndCopyBytes, trailingBytes); + } + + /** + * Test various configurations of copying and optionally swapping data + * + * @param src the source buffer to copy from + * @param dst the destination buffer to copy to + * @param size size (in bytes) of the buffers + * @param elemSize size (in bytes) of the individual elements + * + * @throws RuntimeException if an error is found + */ + public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize, boolean swap) { + // offset in source from which to start reading data + for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) { + + // offset in destination at which to start writing data + for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) { + + // number of bytes to copy + long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset); + for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) { + try { + testCopyGeneric(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize, swap); + } catch (RuntimeException e) { + // Wrap the exception in another exception to catch the relevant configuration data + throw new RuntimeException("testBufferPair: " + + "src=" + src + + " dst=" + dst + + " elemSize=0x" + Long.toHexString(elemSize) + + " copyBytes=0x" + Long.toHexString(copyBytes) + + " srcOffset=0x" + Long.toHexString(srcOffset) + + " dstOffset=0x" + Long.toHexString(dstOffset) + + " swap=" + swap, + e); + } + } + } + } + } + + /** + * Test copying between various permutations of buffers + * + * @param buffers buffers to permute (src x dst) + * @param size size (in bytes) of buffers + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize, boolean swap) { + System.out.println("testPermuteBuffers(buffers, " + size + ", " + elemSize + ", " + swap + ")"); + for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) { + for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) { + testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize, swap); + } + } + } + + /** + * Test copying of a specific element size + * + * @param size size (in bytes) of buffers to allocate + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + private void testElemSize(long size, long elemSize, boolean swap) { + long buf1Raw = 0; + long buf2Raw = 0; + + try { + buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT); + + buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT); + + GenericPointer[] buffers = { + new GenericPointer(buf1), + new GenericPointer(buf2), + new GenericPointer(allocArray(size, elemSize)), + new GenericPointer(allocArray(size, elemSize)) + }; + + testPermuteBuffers(buffers, size, elemSize, swap); + } finally { + if (buf1Raw != 0) { + UNSAFE.freeMemory(buf1Raw); + } + if (buf2Raw != 0) { + UNSAFE.freeMemory(buf2Raw); + } + } + } + + /** + * Verify that small copies work + */ + void testSmallCopy(boolean swap) { + int smallBufSize = SMALL_COPY_SIZE; + int minElemSize = swap ? 2 : 1; + int maxElemSize = swap ? 8 : 1; + + // Test various element types and heap/native combinations + for (long elemSize = minElemSize; elemSize <= maxElemSize; elemSize <<= 1) { + testElemSize(smallBufSize, elemSize, swap); + } + } + + + /** + * Verify that large copies work + */ + void testLargeCopy(boolean swap) { + long size = 2 * GB + 8; + long bufRaw = 0; + + // Check that a large native copy succeeds + try { + try { + bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + } catch (OutOfMemoryError e) { + // Accept failure, skip test + return; + } + + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + + if (swap) { + UNSAFE.copySwapMemory(null, buf, null, buf, size, 8); + } else { + UNSAFE.copyMemory(null, buf, null, buf, size); + } + } catch (Exception e) { + throw new RuntimeException("copy of large buffer failed (swap=" + swap + ")"); + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Helper class to represent a "pointer" - either a heap array or + * a pointer to a native buffer. + * + * In the case of a native pointer, the Object is null and the offset is + * the absolute address of the native buffer. + * + * In the case of a heap object, the Object is a primitive array, and + * the offset will be set to the base offset to the first element, meaning + * the object and the offset together form a double-register pointer. + */ + static class GenericPointer { + private final Object o; + private final long offset; + + private GenericPointer(Object o, long offset) { + this.o = o; + this.offset = offset; + } + + public String toString() { + return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")"; + } + + public boolean equals(Object other) { + if (!(other instanceof GenericPointer)) { + return false; + } + + GenericPointer otherp = (GenericPointer)other; + + return o == otherp.o && offset == otherp.offset; + } + + GenericPointer(Object o) { + this(o, UNSAFE.arrayBaseOffset(o.getClass())); + } + + GenericPointer(long offset) { + this(null, offset); + } + + public boolean isOnHeap() { + return o != null; + } + + public Object getObject() { + return o; + } + + public long getOffset() { + return offset; + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/jdk/internal/misc/Unsafe/CopyMemory.java --- a/jdk/test/jdk/internal/misc/Unsafe/CopyMemory.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/jdk/internal/misc/Unsafe/CopyMemory.java Mon Mar 21 11:21:08 2016 +0100 @@ -29,492 +29,18 @@ * @summary Test Unsafe.copyMemory * @modules java.base/jdk.internal.misc */ -public class CopyMemory { - private static final boolean DEBUG = Boolean.getBoolean("CopyMemory.DEBUG"); - - public static final long KB = 1024; - public static final long MB = KB * 1024; - public static final long GB = MB * 1024; - - private static final Unsafe UNSAFE; - private static final int SMALL_COPY_SIZE = 32; - private static final int BASE_ALIGNMENT = 16; - - static { - try { - Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); - } catch (Exception e) { - throw new RuntimeException("Unable to get Unsafe instance.", e); - } - } - - private static long alignDown(long value, long alignment) { - return value & ~(alignment - 1); - } - - private static long alignUp(long value, long alignment) { - return (value + alignment - 1) & ~(alignment - 1); - } - - private static boolean isAligned(long value, long alignment) { - return value == alignDown(value, alignment); - } - +public class CopyMemory extends CopyCommon { private CopyMemory() { } /** - * Generate verification data for a given offset - * - * The verification data is used to verify that the correct bytes - * have indeed been copied and byte swapped. - * - * The data is generated based on the offset (in bytes) into the - * source buffer. For a native buffer the offset is relative to - * the base pointer. For a heap array it is relative to the - * address of the first array element. - * - * This method will return the result of doing an elementSize byte - * read starting at offset (in bytes). - * - * @param offset offset into buffer - * @param elemSize size (in bytes) of the element - * - * @return the verification data, only the least significant - * elemSize*8 bits are set, zero extended - */ - private long getVerificationDataForOffset(long offset, long elemSize) { - byte[] bytes = new byte[(int)elemSize]; - - for (long i = 0; i < elemSize; i++) { - bytes[(int)i] = (byte)(offset + i); - } - - long o = UNSAFE.arrayBaseOffset(byte[].class); - - switch ((int)elemSize) { - case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o)); - case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o)); - case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o)); - case 8: return UNSAFE.getLongUnaligned(bytes, o); - default: throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - - /** - * Verify byte swapped data - * - * @param ptr the data to verify - * @param srcOffset the srcOffset (in bytes) from which the copy started, - * used as key to regenerate the verification data - * @param dstOffset the offset (in bytes) in the array at which to start - * the verification, relative to the first element in the array - * @param size size (in bytes) of data to to verify - * @param elemSize size (in bytes) of the individual array elements - * - * @throws RuntimeException if an error is found - */ - private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) { - for (long offset = 0; offset < size; offset += elemSize) { - long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize); - long expected = byteSwap(expectedUnswapped, elemSize); - - long actual = getArrayElem(ptr, dstOffset + offset, elemSize); - - if (expected != actual) { - throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) + - " dstOffset: 0x" + Long.toHexString(dstOffset) + - " size: 0x" + Long.toHexString(size) + - " offset: 0x" + Long.toHexString(offset) + - " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) + - " expected: 0x" + Long.toHexString(expected) + - " != actual: 0x" + Long.toHexString(actual)); - } - } - } - - /** - * Initialize an array with verification friendly data - * - * @param ptr pointer to the data to initialize - * @param size size (in bytes) of the data - * @param elemSize size (in bytes) of the individual elements - */ - private void initVerificationData(GenericPointer ptr, long size, long elemSize) { - for (long offset = 0; offset < size; offset++) { - byte data = (byte)getVerificationDataForOffset(offset, 1); - - if (ptr.isOnHeap()) { - UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data); - } else { - UNSAFE.putByte(ptr.getOffset() + offset, data); - } - } - } - - /** - * Allocate a primitive array - * - * @param size size (in bytes) of all the array elements (elemSize * length) - * @param elemSize the size of the array elements - * - * @return a newly allocated primitive array - */ - Object allocArray(long size, long elemSize) { - int length = (int)(size / elemSize); - - switch ((int)elemSize) { - case 1: return new byte[length]; - case 2: return new short[length]; - case 4: return new int[length]; - case 8: return new long[length]; - default: - throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - - /** - * Get the value of a primitive array entry - * - * @param ptr pointer to the data - * @param offset offset (in bytes) of the array element, relative to the first element in the array - * - * @return the array element, as an unsigned long - */ - private long getArrayElem(GenericPointer ptr, long offset, long elemSize) { - if (ptr.isOnHeap()) { - Object o = ptr.getObject(); - int index = (int)(offset / elemSize); - - if (o instanceof short[]) { - short[] arr = (short[])o; - return Short.toUnsignedLong(arr[index]); - } else if (o instanceof int[]) { - int[] arr = (int[])o; - return Integer.toUnsignedLong(arr[index]); - } else if (o instanceof long[]) { - long[] arr = (long[])o; - return arr[index]; - } else { - throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); - } - } else { - long addr = ptr.getOffset() + offset; - - switch ((int)elemSize) { - case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr)); - case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr)); - case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr)); - case 8: return UNSAFE.getLongUnaligned(null, addr); - default: throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - } - - private void putValue(long addr, long elemSize, long value) { - switch ((int)elemSize) { - case 1: UNSAFE.putByte(addr, (byte)value); break; - case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break; - case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break; - case 8: UNSAFE.putLongUnaligned(null, addr, value); break; - default: throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - - /** - * Get the size of the elements for an array - * - * @param o a primitive heap array - * - * @return the size (in bytes) of the individual array elements - */ - private long getArrayElemSize(Object o) { - if (o instanceof short[]) { - return 2; - } else if (o instanceof int[]) { - return 4; - } else if (o instanceof long[]) { - return 8; - } else { - throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); - } - } - - /** - * Byte swap a value - * - * @param value the value to swap, only the bytes*8 least significant bits are used - * @param size size (in bytes) of the value - * - * @return the byte swapped value in the bytes*8 least significant bits - */ - private long byteSwap(long value, long size) { - switch ((int)size) { - case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value)); - case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value)); - case 8: return Long.reverseBytes(value); - default: throw new IllegalArgumentException("Invalid element size: " + size); - } - } - - /** - * Verify data which has *not* been byte swapped - * - * @param ptr the data to verify - * @param startOffset the offset (in bytes) at which to start the verification - * @param size size (in bytes) of the data to verify - * - * @throws RuntimeException if an error is found - */ - private void verifyUnswappedData(GenericPointer ptr, long startOffset, long srcOffset, long size) { - for (long i = 0; i < size; i++) { - byte expected = (byte)getVerificationDataForOffset(srcOffset + i, 1); - - byte actual; - if (ptr.isOnHeap()) { - actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + startOffset + i); - } else { - actual = UNSAFE.getByte(ptr.getOffset() + startOffset + i); - } - - if (expected != actual) { - throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) + - " srcOffset: 0x" + Long.toHexString(srcOffset) + - " size: 0x" + Long.toHexString(size) + - " i: 0x" + Long.toHexString(i) + - " expected: 0x" + Long.toHexString(expected) + - " != actual: 0x" + Long.toHexString(actual)); - } - } - } - - - /** - * Copy and byte swap data from the source to the destination - * - * This method will pre-populate the whole source and destination - * buffers with verification friendly data. It will then use - * copypMemory to fill part of the destination buffer with - * data from the source. Some space (padding) will be - * left before and after the data in the destination buffer, which - * should not be touched/overwritten by the copy call. - * - * Note: Both source and destination buffers will be overwritten! - * - * @param src source buffer to copy from - * @param srcOffset the offset (in bytes) in the source buffer, relative to - * the first array element, at which to start reading data - * @param dst destination buffer to copy to - * @param dstOffset the offset (in bytes) in the destination - * buffer, relative to the first array element, at which to - * start writing data - * @param bufSize the size (in bytes) of the src and dst arrays - * @param copyBytes the size (in bytes) of the copy to perform, - * must be a multiple of elemSize - * - * @throws RuntimeException if an error is found - */ - private void testCopy(GenericPointer src, long srcOffset, - GenericPointer dst, long dstOffset, - long bufSize, long copyBytes) { - if (srcOffset + copyBytes > bufSize) { - throw new IllegalArgumentException( - "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); - } - if (dstOffset + copyBytes > bufSize) { - throw new IllegalArgumentException( - "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); - } - - // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes) - initVerificationData(src, bufSize, 1); - if (!src.equals(dst)) { - initVerificationData(dst, bufSize, 1); - } - - if (DEBUG) { - System.out.println("===before==="); - for (int offset = 0; offset < bufSize; offset++) { - long srcValue = getArrayElem(src, offset, 1); - long dstValue = getArrayElem(dst, offset, 1); - - System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + - " src=0x" + Long.toHexString(srcValue) + - " dst=0x" + Long.toHexString(dstValue)); - } - } - - // Copy & swap data into the middle of the destination buffer - UNSAFE.copyMemory(src.getObject(), - src.getOffset() + srcOffset, - dst.getObject(), - dst.getOffset() + dstOffset, - copyBytes); - - if (DEBUG) { - System.out.println("===after==="); - for (int offset = 0; offset < bufSize; offset++) { - long srcValue = getArrayElem(src, offset, 1); - long dstValue = getArrayElem(dst, offset, 1); - - System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + - " src=0x" + Long.toHexString(srcValue) + - " dst=0x" + Long.toHexString(dstValue)); - } - } - - // Verify the the front padding is unchanged - verifyUnswappedData(dst, 0, 0, dstOffset); - - // Verify copied data - verifyUnswappedData(dst, dstOffset, srcOffset, copyBytes); - - // Verify that the back back padding is unchanged - long frontAndDataBytes = dstOffset + copyBytes; - long trailingBytes = bufSize - frontAndDataBytes; - verifyUnswappedData(dst, frontAndDataBytes, frontAndDataBytes, trailingBytes); - } - - /** - * Test various configurations copying from one buffer to the other - * - * @param src the source buffer to copy from - * @param dst the destination buffer to copy to - * @param size size (in bytes) of the buffers - * @param elemSize size (in bytes) of the individual elements - * - * @throws RuntimeException if an error is found - */ - public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) { - // offset in source from which to start reading data - for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) { - - // offset in destination at which to start writing data - for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) { - - // number of bytes to copy - long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset); - for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) { - try { - testCopy(src, srcOffset, dst, dstOffset, size, copyBytes); - } catch (RuntimeException e) { - // Wrap the exception in another exception to catch the relevant configuration data - throw new RuntimeException("testBufferPair: " + - "src=" + src + - " dst=" + dst + - " elemSize=0x" + Long.toHexString(elemSize) + - " copyBytes=0x" + Long.toHexString(copyBytes) + - " srcOffset=0x" + Long.toHexString(srcOffset) + - " dstOffset=0x" + Long.toHexString(dstOffset), - e); - } - } - } - } - } - - /** - * Test copying between various permutations of buffers - * - * @param buffers buffers to permute (src x dst) - * @param size size (in bytes) of buffers - * @param elemSize size (in bytes) of individual elements - * - * @throws RuntimeException if an error is found - */ - public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) { - for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) { - for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) { - testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize); - } - } - } - - /** - * Test copying of a specific element size - * - * @param size size (in bytes) of buffers to allocate - * @param elemSize size (in bytes) of individual elements - * - * @throws RuntimeException if an error is found - */ - private void testElemSize(long size, long elemSize) { - long buf1Raw = 0; - long buf2Raw = 0; - - try { - buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); - long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT); - - buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); - long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT); - - GenericPointer[] buffers = { - new GenericPointer(buf1), - new GenericPointer(buf2), - new GenericPointer(allocArray(size, elemSize)), - new GenericPointer(allocArray(size, elemSize)) - }; - - testPermuteBuffers(buffers, size, elemSize); - } finally { - if (buf1Raw != 0) { - UNSAFE.freeMemory(buf1Raw); - } - if (buf2Raw != 0) { - UNSAFE.freeMemory(buf2Raw); - } - } - } - - /** - * Verify that small copies work - */ - private void testSmallCopy() { - int smallBufSize = SMALL_COPY_SIZE; - - testElemSize(smallBufSize, 1); - } - - - /** - * Verify that large copies work - */ - private void testLargeCopy() { - long size = 2 * GB + 8; - long bufRaw = 0; - - // Check that a large native copy succeeds - try { - try { - bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); - } catch (OutOfMemoryError e) { - // Accept failure, skip test - return; - } - - long buf = alignUp(bufRaw, BASE_ALIGNMENT); - - UNSAFE.copyMemory(null, buf, null, buf, size); - } catch (Exception e) { - throw new RuntimeException("copyMemory of large buffer failed"); - } finally { - if (bufRaw != 0) { - UNSAFE.freeMemory(bufRaw); - } - } - } - - /** * Run positive tests * * @throws RuntimeException if an error is found */ private void testPositive() { - testSmallCopy(); - testLargeCopy(); + testSmallCopy(false); + testLargeCopy(false); } /** @@ -527,7 +53,7 @@ try { bufRaw = UNSAFE.allocateMemory(1024); - long buf = alignUp(bufRaw, BASE_ALIGNMENT); + long buf = CopyCommon.alignUp(bufRaw, CopyCommon.BASE_ALIGNMENT); short[] arr = new short[16]; // Check illegal sizes @@ -609,59 +135,4 @@ CopyMemory cs = new CopyMemory(); cs.test(); } - - /** - * Helper class to represent a "pointer" - either a heap array or - * a pointer to a native buffer. - * - * In the case of a native pointer, the Object is null and the offset is - * the absolute address of the native buffer. - * - * In the case of a heap object, the Object is a primitive array, and - * the offset will be set to the base offset to the first element, meaning - * the object and the offset together form a double-register pointer. - */ - static class GenericPointer { - private final Object o; - private final long offset; - - private GenericPointer(Object o, long offset) { - this.o = o; - this.offset = offset; - } - - public String toString() { - return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")"; - } - - public boolean equals(Object other) { - if (!(other instanceof GenericPointer)) { - return false; - } - - GenericPointer otherp = (GenericPointer)other; - - return o == otherp.o && offset == otherp.offset; - } - - GenericPointer(Object o) { - this(o, UNSAFE.arrayBaseOffset(o.getClass())); - } - - GenericPointer(long offset) { - this(null, offset); - } - - public boolean isOnHeap() { - return o != null; - } - - public Object getObject() { - return o; - } - - public long getOffset() { - return offset; - } - } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/jdk/internal/misc/Unsafe/CopySwap.java --- a/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java Mon Mar 21 11:21:08 2016 +0100 @@ -29,507 +29,18 @@ * @summary Test Unsafe.copySwapMemory * @modules java.base/jdk.internal.misc */ -public class CopySwap { - private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG"); - - public static final long KB = 1024; - public static final long MB = KB * 1024; - public static final long GB = MB * 1024; - - private static final Unsafe UNSAFE; - private static final int SMALL_COPY_SIZE = 32; - private static final int BASE_ALIGNMENT = 16; - - static { - try { - Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); - } catch (Exception e) { - throw new RuntimeException("Unable to get Unsafe instance.", e); - } - } - - private static long alignDown(long value, long alignment) { - return value & ~(alignment - 1); - } - - private static long alignUp(long value, long alignment) { - return (value + alignment - 1) & ~(alignment - 1); - } - - private static boolean isAligned(long value, long alignment) { - return value == alignDown(value, alignment); - } - +public class CopySwap extends CopyCommon { private CopySwap() { } /** - * Generate verification data for a given offset - * - * The verification data is used to verify that the correct bytes - * have indeed been copied and byte swapped. - * - * The data is generated based on the offset (in bytes) into the - * source buffer. For a native buffer the offset is relative to - * the base pointer. For a heap array it is relative to the - * address of the first array element. - * - * This method will return the result of doing an elementSize byte - * read starting at offset (in bytes). - * - * @param offset offset into buffer - * @param elemSize size (in bytes) of the element - * - * @return the verification data, only the least significant - * elemSize*8 bits are set, zero extended - */ - private long getVerificationDataForOffset(long offset, long elemSize) { - byte[] bytes = new byte[(int)elemSize]; - - for (long i = 0; i < elemSize; i++) { - bytes[(int)i] = (byte)(offset + i); - } - - long o = UNSAFE.arrayBaseOffset(byte[].class); - - switch ((int)elemSize) { - case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o)); - case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o)); - case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o)); - case 8: return UNSAFE.getLongUnaligned(bytes, o); - default: throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - - /** - * Verify byte swapped data - * - * @param ptr the data to verify - * @param srcOffset the srcOffset (in bytes) from which the copy started, - * used as key to regenerate the verification data - * @param dstOffset the offset (in bytes) in the array at which to start - * the verification, relative to the first element in the array - * @param size size (in bytes) of data to to verify - * @param elemSize size (in bytes) of the individual array elements - * - * @throws RuntimeException if an error is found - */ - private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) { - for (long offset = 0; offset < size; offset += elemSize) { - long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize); - long expected = byteSwap(expectedUnswapped, elemSize); - - long actual = getArrayElem(ptr, dstOffset + offset, elemSize); - - if (expected != actual) { - throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) + - " dstOffset: 0x" + Long.toHexString(dstOffset) + - " size: 0x" + Long.toHexString(size) + - " offset: 0x" + Long.toHexString(offset) + - " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) + - " expected: 0x" + Long.toHexString(expected) + - " != actual: 0x" + Long.toHexString(actual)); - } - } - } - - /** - * Initialize an array with verification friendly data - * - * @param ptr pointer to the data to initialize - * @param size size (in bytes) of the data - * @param elemSize size (in bytes) of the individual elements - */ - private void initVerificationData(GenericPointer ptr, long size, long elemSize) { - for (long offset = 0; offset < size; offset++) { - byte data = (byte)getVerificationDataForOffset(offset, 1); - - if (ptr.isOnHeap()) { - UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data); - } else { - UNSAFE.putByte(ptr.getOffset() + offset, data); - } - } - } - - /** - * Allocate a primitive array - * - * @param size size (in bytes) of all the array elements (elemSize * length) - * @param elemSize the size of the array elements - * - * @return a newly allocated primitive array - */ - Object allocArray(long size, long elemSize) { - int length = (int)(size / elemSize); - - switch ((int)elemSize) { - case 2: return new short[length]; - case 4: return new int[length]; - case 8: return new long[length]; - default: - throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - - /** - * Get the value of a primitive array entry - * - * @param ptr pointer to the data - * @param offset offset (in bytes) of the array element, relative to the first element in the array - * - * @return the array element, as an unsigned long - */ - private long getArrayElem(GenericPointer ptr, long offset, long elemSize) { - if (ptr.isOnHeap()) { - Object o = ptr.getObject(); - int index = (int)(offset / elemSize); - - if (o instanceof short[]) { - short[] arr = (short[])o; - return Short.toUnsignedLong(arr[index]); - } else if (o instanceof int[]) { - int[] arr = (int[])o; - return Integer.toUnsignedLong(arr[index]); - } else if (o instanceof long[]) { - long[] arr = (long[])o; - return arr[index]; - } else { - throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); - } - } else { - long addr = ptr.getOffset() + offset; - - switch ((int)elemSize) { - case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr)); - case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr)); - case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr)); - case 8: return UNSAFE.getLongUnaligned(null, addr); - default: throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - } - - private void putValue(long addr, long elemSize, long value) { - switch ((int)elemSize) { - case 1: UNSAFE.putByte(addr, (byte)value); break; - case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break; - case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break; - case 8: UNSAFE.putLongUnaligned(null, addr, value); break; - default: throw new IllegalArgumentException("Invalid element size: " + elemSize); - } - } - - /** - * Get the size of the elements for an array - * - * @param o a primitive heap array - * - * @return the size (in bytes) of the individual array elements - */ - private long getArrayElemSize(Object o) { - if (o instanceof short[]) { - return 2; - } else if (o instanceof int[]) { - return 4; - } else if (o instanceof long[]) { - return 8; - } else { - throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); - } - } - - /** - * Byte swap a value - * - * @param value the value to swap, only the bytes*8 least significant bits are used - * @param size size (in bytes) of the value - * - * @return the byte swapped value in the bytes*8 least significant bits - */ - private long byteSwap(long value, long size) { - switch ((int)size) { - case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value)); - case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value)); - case 8: return Long.reverseBytes(value); - default: throw new IllegalArgumentException("Invalid element size: " + size); - } - } - - /** - * Verify data in a heap array which has *not* been byte swapped - * - * @param ptr the data to verify - * @param startOffset the offset (in bytes) at which to start the verification - * @param size size (in bytes) of the data to verify - * - * @throws RuntimeException if an error is found - */ - private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) { - for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) { - byte expected = (byte)getVerificationDataForOffset(elemOffset, 1); - - byte actual; - if (ptr.isOnHeap()) { - actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset); - } else { - actual = UNSAFE.getByte(ptr.getOffset() + elemOffset); - } - - if (expected != actual) { - throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) + - " size: 0x" + Long.toHexString(size) + - " elemOffset: 0x" + Long.toHexString(elemOffset) + - " expected: 0x" + Long.toHexString(expected) + - " != actual: 0x" + Long.toHexString(actual)); - } - } - } - - - /** - * Copy and byte swap data from the source to the destination - * - * This method will pre-populate the whole source and destination - * buffers with verification friendly data. It will then use - * copySwapMemory to fill part of the destination buffer with - * swapped data from the source. Some space (padding) will be - * left before and after the data in the destination buffer, which - * should not be touched/overwritten by the copy call. - * - * Note: Both source and destination buffers will be overwritten! - * - * @param src source buffer to copy from - * @param srcOffset the offset (in bytes) in the source buffer, relative to - * the first array element, at which to start reading data - * @param dst destination buffer to copy to - * @param dstOffset the offset (in bytes) in the destination - * buffer, relative to the first array element, at which to - * start writing data - * @param bufSize the size (in bytes) of the src and dst arrays - * @param copyBytes the size (in bytes) of the copy to perform, - * must be a multiple of elemSize - * @param elemSize the size (in bytes) of the elements to byte swap - * - * @throws RuntimeException if an error is found - */ - private void testCopySwap(GenericPointer src, long srcOffset, - GenericPointer dst, long dstOffset, - long bufSize, long copyBytes, long elemSize) { - if (!isAligned(copyBytes, elemSize)) { - throw new IllegalArgumentException( - "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")"); - } - if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) { - throw new IllegalArgumentException( - "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")"); - } - if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) { - throw new IllegalArgumentException( - "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")"); - } - if (srcOffset + copyBytes > bufSize) { - throw new IllegalArgumentException( - "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); - } - if (dstOffset + copyBytes > bufSize) { - throw new IllegalArgumentException( - "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); - } - - // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes) - initVerificationData(src, bufSize, elemSize); - if (!src.equals(dst)) { - initVerificationData(dst, bufSize, elemSize); - } - - if (DEBUG) { - System.out.println("===before==="); - for (int offset = 0; offset < bufSize; offset += elemSize) { - long srcValue = getArrayElem(src, offset, elemSize); - long dstValue = getArrayElem(dst, offset, elemSize); - - System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + - " src=0x" + Long.toHexString(srcValue) + - " dst=0x" + Long.toHexString(dstValue)); - } - } - - // Copy & swap data into the middle of the destination buffer - UNSAFE.copySwapMemory(src.getObject(), - src.getOffset() + srcOffset, - dst.getObject(), - dst.getOffset() + dstOffset, - copyBytes, - elemSize); - - if (DEBUG) { - System.out.println("===after==="); - for (int offset = 0; offset < bufSize; offset += elemSize) { - long srcValue = getArrayElem(src, offset, elemSize); - long dstValue = getArrayElem(dst, offset, elemSize); - - System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + - " src=0x" + Long.toHexString(srcValue) + - " dst=0x" + Long.toHexString(dstValue)); - } - } - - // Verify the the front padding is unchanged - verifyUnswappedData(dst, 0, dstOffset); - - // Verify swapped data - verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize); - - // Verify that the back back padding is unchanged - long frontAndDataBytes = dstOffset + copyBytes; - long trailingBytes = bufSize - frontAndDataBytes; - verifyUnswappedData(dst, frontAndDataBytes, trailingBytes); - } - - /** - * Test various configurations copy-swapping from one buffer to the other - * - * @param src the source buffer to copy from - * @param dst the destination buffer to copy to - * @param size size (in bytes) of the buffers - * @param elemSize size (in bytes) of the individual elements - * - * @throws RuntimeException if an error is found - */ - public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) { - // offset in source from which to start reading data - for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) { - - // offset in destination at which to start writing data - for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) { - - // number of bytes to copy - long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset); - for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) { - try { - testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize); - } catch (RuntimeException e) { - // Wrap the exception in another exception to catch the relevant configuration data - throw new RuntimeException("testBufferPair: " + - "src=" + src + - " dst=" + dst + - " elemSize=0x" + Long.toHexString(elemSize) + - " copyBytes=0x" + Long.toHexString(copyBytes) + - " srcOffset=0x" + Long.toHexString(srcOffset) + - " dstOffset=0x" + Long.toHexString(dstOffset), - e); - } - } - } - } - } - - /** - * Test copying between various permutations of buffers - * - * @param buffers buffers to permute (src x dst) - * @param size size (in bytes) of buffers - * @param elemSize size (in bytes) of individual elements - * - * @throws RuntimeException if an error is found - */ - public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) { - for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) { - for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) { - testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize); - } - } - } - - /** - * Test copying of a specific element size - * - * @param size size (in bytes) of buffers to allocate - * @param elemSize size (in bytes) of individual elements - * - * @throws RuntimeException if an error is found - */ - private void testElemSize(long size, long elemSize) { - long buf1Raw = 0; - long buf2Raw = 0; - - try { - buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); - long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT); - - buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); - long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT); - - GenericPointer[] buffers = { - new GenericPointer(buf1), - new GenericPointer(buf2), - new GenericPointer(allocArray(size, elemSize)), - new GenericPointer(allocArray(size, elemSize)) - }; - - testPermuteBuffers(buffers, size, elemSize); - } finally { - if (buf1Raw != 0) { - UNSAFE.freeMemory(buf1Raw); - } - if (buf2Raw != 0) { - UNSAFE.freeMemory(buf2Raw); - } - } - } - - /** - * Verify that small copy swaps work - */ - private void testSmallCopy() { - int smallBufSize = SMALL_COPY_SIZE; - - // Test various element types and heap/native combinations - for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) { - testElemSize(smallBufSize, elemSize); - } - } - - - /** - * Verify that large copy swaps work - */ - private void testLargeCopy() { - long size = 2 * GB + 8; - long bufRaw = 0; - - // Check that a large native copy succeeds - try { - try { - bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); - } catch (OutOfMemoryError e) { - // Accept failure, skip test - return; - } - - long buf = alignUp(bufRaw, BASE_ALIGNMENT); - - UNSAFE.copySwapMemory(null, buf, null, buf, size, 8); - } catch (Exception e) { - throw new RuntimeException("copySwapMemory of large buffer failed"); - } finally { - if (bufRaw != 0) { - UNSAFE.freeMemory(bufRaw); - } - } - } - - /** * Run positive tests * * @throws RuntimeException if an error is found */ private void testPositive() { - testSmallCopy(); - testLargeCopy(); + testSmallCopy(true); + testLargeCopy(true); } /** @@ -542,7 +53,7 @@ try { bufRaw = UNSAFE.allocateMemory(1024); - long buf = alignUp(bufRaw, BASE_ALIGNMENT); + long buf = CopyCommon.alignUp(bufRaw, CopyCommon.BASE_ALIGNMENT); short[] arr = new short[16]; // Check various illegal element sizes @@ -637,59 +148,4 @@ CopySwap cs = new CopySwap(); cs.test(); } - - /** - * Helper class to represent a "pointer" - either a heap array or - * a pointer to a native buffer. - * - * In the case of a native pointer, the Object is null and the offset is - * the absolute address of the native buffer. - * - * In the case of a heap object, the Object is a primitive array, and - * the offset will be set to the base offset to the first element, meaning - * the object and the offset together form a double-register pointer. - */ - static class GenericPointer { - private final Object o; - private final long offset; - - private GenericPointer(Object o, long offset) { - this.o = o; - this.offset = offset; - } - - public String toString() { - return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")"; - } - - public boolean equals(Object other) { - if (!(other instanceof GenericPointer)) { - return false; - } - - GenericPointer otherp = (GenericPointer)other; - - return o == otherp.o && offset == otherp.offset; - } - - GenericPointer(Object o) { - this(o, UNSAFE.arrayBaseOffset(o.getClass())); - } - - GenericPointer(long offset) { - this(null, offset); - } - - public boolean isOnHeap() { - return o != null; - } - - public Object getObject() { - return o; - } - - public long getOffset() { - return offset; - } - } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/java2d/marlin/CrashNaNTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/java2d/marlin/CrashNaNTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Path2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import static java.lang.Double.NaN; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8149338 + * @summary Verifies that Marlin supports NaN coordinates and no JVM crash happens ! + * @run main CrashNaNTest + */ +public class CrashNaNTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(String argv[]) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + final int width = 400; + final int height = 400; + + final BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setBackground(Color.WHITE); + g2d.clearRect(0, 0, width, height); + + final Path2D.Double path = new Path2D.Double(); + path.moveTo(30, 30); + path.lineTo(100, 100); + + for (int i = 0; i < 20000; i++) { + path.lineTo(110 + 0.01 * i, 110); + path.lineTo(111 + 0.01 * i, 100); + } + + path.lineTo(NaN, 200); + path.lineTo(200, 200); + path.lineTo(200, NaN); + path.lineTo(300, 300); + path.lineTo(NaN, NaN); + path.lineTo(100, 100); + path.closePath(); + + final Path2D.Double path2 = new Path2D.Double(); + path2.moveTo(0,0); + path2.lineTo(width,height); + path2.lineTo(10, 10); + path2.closePath(); + + for (int i = 0; i < 1; i++) { + final long start = System.nanoTime(); + g2d.setColor(Color.BLUE); + g2d.fill(path); + + g2d.fill(path2); + + final long time = System.nanoTime() - start; + System.out.println("paint: duration= " + (1e-6 * time) + " ms."); + } + + if (SAVE_IMAGE) { + try { + final File file = new File("CrashNaNTest.png"); + System.out.println("Writing file: " + + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + System.out.println("Writing file failure:"); + ex.printStackTrace(); + } + } + } finally { + g2d.dispose(); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/java2d/marlin/CrashPaintTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/java2d/marlin/CrashPaintTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.PaintContext; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.TexturePaint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8148886 + * @summary Verifies that Marlin supports reentrant operations (ThreadLocal) + * like in custom Paint or custom Composite + * @run main CrashPaintTest + */ +public class CrashPaintTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(String argv[]) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + // Force using thread-local storage: + System.setProperty("sun.java2d.renderer.useThreadLocal", "true"); + // Force smaller pixelsize to force using array caches: + System.setProperty("sun.java2d.renderer.pixelsize", "256"); + + final int width = 300; + final int height = 300; + + final BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setBackground(Color.WHITE); + g2d.clearRect(0, 0, width, height); + + final Ellipse2D.Double ellipse + = new Ellipse2D.Double(0, 0, width, height); + + final Paint paint = new CustomPaint(100); + + for (int i = 0; i < 20; i++) { + final long start = System.nanoTime(); + g2d.setPaint(paint); + g2d.fill(ellipse); + + g2d.setColor(Color.GREEN); + g2d.draw(ellipse); + + final long time = System.nanoTime() - start; + System.out.println("paint: duration= " + (1e-6 * time) + " ms."); + } + + if (SAVE_IMAGE) { + try { + final File file = new File("CrashPaintTest.png"); + System.out.println("Writing file: " + + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + System.out.println("Writing file failure:"); + ex.printStackTrace(); + } + } + + // Check image on few pixels: + final Raster raster = image.getData(); + + // 170, 175 = blue + checkPixel(raster, 170, 175, Color.BLUE.getRGB()); + // 50, 50 = blue + checkPixel(raster, 50, 50, Color.BLUE.getRGB()); + + // 190, 110 = pink + checkPixel(raster, 190, 110, Color.PINK.getRGB()); + // 280, 210 = pink + checkPixel(raster, 280, 210, Color.PINK.getRGB()); + + } finally { + g2d.dispose(); + } + } + + private static void checkPixel(final Raster raster, + final int x, final int y, + final int expected) { + + final int[] rgb = (int[]) raster.getDataElements(x, y, null); + + if (rgb[0] != expected) { + throw new IllegalStateException("bad pixel at (" + x + ", " + y + + ") = " + rgb[0] + " expected: " + expected); + } + } + + private static class CustomPaint extends TexturePaint { + private int size; + + CustomPaint(final int size) { + super(new BufferedImage(size, size, + BufferedImage.TYPE_INT_ARGB), + new Rectangle2D.Double(0, 0, size, size) + ); + this.size = size; + } + + @Override + public PaintContext createContext(ColorModel cm, + Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform at, + RenderingHints hints) { + + // Fill bufferedImage using + final Graphics2D g2d = (Graphics2D) getImage().getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setBackground(Color.PINK); + g2d.clearRect(0, 0, size, size); + + g2d.setColor(Color.BLUE); + g2d.drawRect(0, 0, size, size); + + g2d.fillOval(size / 10, size / 10, + size * 8 / 10, size * 8 / 10); + + } finally { + g2d.dispose(); + } + + return super.createContext(cm, deviceBounds, userBounds, at, hints); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/java2d/marlin/TextClipErrorTest.java --- a/jdk/test/sun/java2d/marlin/TextClipErrorTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -69,24 +69,12 @@ @Override public void publish(LogRecord record) { Throwable th = record.getThrown(); - // detect potential Throwable thrown by XxxArrayCache.check(): - if (th != null && th.getClass() == Throwable.class) { - StackTraceElement[] stackElements = th.getStackTrace(); - - for (int i = 0; i < stackElements.length; i++) { - StackTraceElement e = stackElements[i]; + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); - if (e.getClassName().startsWith("sun.java2d.marlin") - && e.getClassName().contains("ArrayCache") - && "check".equals(e.getMethodName())) - { - System.out.println("Test failed:\n" - + record.getMessage()); - th.printStackTrace(System.out); - - throw new RuntimeException("Test failed: ", th); - } - } + throw new RuntimeException("Test failed: ", th); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/security/krb5/auto/MaxRetries.java --- a/jdk/test/sun/security/krb5/auto/MaxRetries.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/sun/security/krb5/auto/MaxRetries.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 6844193 + * @key intermittent * @compile -XDignore.symbol.file MaxRetries.java * @run main/othervm/timeout=300 MaxRetries * @summary support max_retries in krb5.conf diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/security/krb5/auto/Unreachable.java --- a/jdk/test/sun/security/krb5/auto/Unreachable.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/sun/security/krb5/auto/Unreachable.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 7162687 + * @key intermittent * @summary enhance KDC server availability detection * @compile -XDignore.symbol.file Unreachable.java * @run main/othervm/timeout=10 Unreachable diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/security/mscapi/SignatureOffsets.java --- a/jdk/test/sun/security/mscapi/SignatureOffsets.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/sun/security/mscapi/SignatureOffsets.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ /* * @test * @bug 8050374 - * @key randomness + * @key randomness intermittent * @summary This test validates signature verification * Signature.verify(byte[], int, int). The test uses RandomFactory to * get random set of clear text data to sign. After the signature diff -r 0dc62e7c6a29 -r 74e9f4b90006 jdk/test/sun/security/mscapi/SmallPrimeExponentP.java --- a/jdk/test/sun/security/mscapi/SmallPrimeExponentP.java Mon Mar 21 08:42:00 2016 +0100 +++ b/jdk/test/sun/security/mscapi/SmallPrimeExponentP.java Mon Mar 21 11:21:08 2016 +0100 @@ -32,6 +32,7 @@ /* * @test * @bug 8023546 + * @key intermittent * @modules java.base/sun.security.x509 * java.base/sun.security.tools.keytool * @summary sun/security/mscapi/ShortRSAKey1024.sh fails intermittently diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/.hgtags --- a/langtools/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -351,3 +351,4 @@ dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106 7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107 fd18a155ad22f62e06a9b74850ab8609d415c752 jdk-9+108 +f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package com.sun.tools.javac.code; import java.io.IOException; -import java.io.File; +import java.nio.file.Path; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; @@ -45,7 +45,6 @@ import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.comp.Annotate; -import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.file.JRTIndex; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.jvm.ClassReader; @@ -535,25 +534,25 @@ if (fileManager instanceof StandardJavaFileManager) { StandardJavaFileManager fm = (StandardJavaFileManager)fileManager; if (haveSourcePath && wantSourceFiles) { - List path = List.nil(); - for (File file : fm.getLocation(SOURCE_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path sourcePath : fm.getLocationAsPaths(SOURCE_PATH)) { + path = path.prepend(sourcePath); } log.printVerbose("sourcepath", path.reverse().toString()); } else if (wantSourceFiles) { - List path = List.nil(); - for (File file : fm.getLocation(CLASS_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { + path = path.prepend(classPath); } log.printVerbose("sourcepath", path.reverse().toString()); } if (wantClassFiles) { - List path = List.nil(); - for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path platformPath : fm.getLocationAsPaths(PLATFORM_CLASS_PATH)) { + path = path.prepend(platformPath); } - for (File file : fm.getLocation(CLASS_PATH)) { - path = path.prepend(file); + for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { + path = path.prepend(classPath); } log.printVerbose("classpath", path.reverse().toString()); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package com.sun.tools.javac.file; -import java.io.File; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.InvalidPathException; diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java Mon Mar 21 11:21:08 2016 +0100 @@ -33,8 +33,7 @@ import com.sun.tools.javac.util.*; import static com.sun.tools.javac.code.Kinds.Kind.MTH; -import static com.sun.tools.javac.code.TypeTag.DOUBLE; -import static com.sun.tools.javac.code.TypeTag.LONG; +import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.jvm.ByteCodes.*; import static com.sun.tools.javac.tree.JCTree.Tag.PLUS; import com.sun.tools.javac.jvm.Items.*; @@ -143,6 +142,25 @@ } /** + * If the type is not accessible from current context, try to figure out the + * sharpest accessible supertype. + * + * @param originalType type to sharpen + * @return sharped type + */ + Type sharpestAccessible(Type originalType) { + if (originalType.hasTag(ARRAY)) { + return types.makeArrayType(sharpestAccessible(types.elemtype(originalType))); + } + + Type type = originalType; + while (!rs.isAccessible(gen.getAttrEnv(), type.asElement())) { + type = types.supertype(type); + } + return type; + } + + /** * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string * concatenation. */ @@ -314,7 +332,7 @@ if (arg.type == syms.botType) { dynamicArgs.add(types.boxedClass(syms.voidType).type); } else { - dynamicArgs.add(arg.type); + dynamicArgs.add(sharpestAccessible(arg.type)); } gen.genExpr(arg, arg.type).load(); } @@ -415,7 +433,7 @@ } else { // Ordinary arguments come through the dynamic arguments. recipe.append(TAG_ARG); - dynamicArgs.add(arg.type); + dynamicArgs.add(sharpestAccessible(arg.type)); gen.genExpr(arg, arg.type).load(); } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Mar 21 11:21:08 2016 +0100 @@ -31,6 +31,7 @@ import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Path; import java.util.*; import java.util.regex.*; import java.util.stream.Collectors; @@ -42,6 +43,7 @@ import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; + import static javax.tools.StandardLocation.*; import com.sun.source.util.TaskEvent; @@ -79,6 +81,7 @@ import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.ServiceLoader; + import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.main.Option.*; @@ -317,9 +320,9 @@ if (fileManager instanceof JavacFileManager) { StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager; - Iterable workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) - ? standardFileManager.getLocation(ANNOTATION_PROCESSOR_PATH) - : standardFileManager.getLocation(CLASS_PATH); + Iterable workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) + ? standardFileManager.getLocationAsPaths(ANNOTATION_PROCESSOR_PATH) + : standardFileManager.getLocationAsPaths(CLASS_PATH); if (needClassLoader(options.get(PROCESSOR), workingPath) ) handleException(key, e); @@ -1298,14 +1301,14 @@ * Called retroactively to determine if a class loader was required, * after we have failed to create one. */ - private boolean needClassLoader(String procNames, Iterable workingpath) { + private boolean needClassLoader(String procNames, Iterable workingpath) { if (procNames != null) return true; URL[] urls = new URL[1]; - for(File pathElement : workingpath) { + for(Path pathElement : workingpath) { try { - urls[0] = pathElement.toURI().toURL(); + urls[0] = pathElement.toUri().toURL(); if (ServiceProxy.hasService(Processor.class, urls)) return true; } catch (MalformedURLException ex) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ apple.laf.*: hidden apple.security.*: hidden -com.apple.concurrent.*: hidden com.apple.eawt.*: hidden com.apple.eawt.event.*: hidden com.apple.eio.*: hidden diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -104,11 +104,11 @@ sb.append(utils.getFullyQualifiedName(member)); if (!utils.isConstructor(member)) { sb.append("."); - sb.append(member.getSimpleName().toString()); + sb.append(member.getSimpleName()); } sb.append(utils.flatSignature((ExecutableElement) member)); - return writer.getDocLink(MEMBER, member, sb.toString()); + return writer.getDocLink(MEMBER, member, sb); } /** @@ -204,7 +204,7 @@ htmltree.addContent("("); String sep = ""; List parameters = member.getParameters(); - String indent = makeSpace(indentSize + 1); + CharSequence indent = makeSpace(indentSize + 1); TypeMirror rcvrType = member.getReceiverType(); if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { List annotationMirrors = rcvrType.getAnnotationMirrors(); @@ -260,7 +260,7 @@ protected void addExceptions(ExecutableElement member, Content htmltree, int indentSize) { List exceptions = member.getThrownTypes(); if (!exceptions.isEmpty()) { - String indent = makeSpace(indentSize + 1 - 7); + CharSequence indent = makeSpace(indentSize + 1 - 7); htmltree.addContent(DocletConstants.NL); htmltree.addContent(indent); htmltree.addContent("throws "); @@ -336,7 +336,7 @@ @Override @DefinedBy(Api.LANGUAGE_MODEL) protected Boolean defaultAction(TypeMirror e, Void p) { - buf.append(e.toString()); + buf.append(e); return foundTypeVariable; } }; diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -223,26 +223,6 @@ htmltree.addContent(name); } - protected String typeString(Element member) { - return new SimpleElementVisitor9() { - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public String visitExecutable(ExecutableElement e, Void p) { - return utils.isMethod(e) ? e.getReturnType().toString() : ""; - } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public String visitVariable(VariableElement e, Void p) { - return e.toString(); - } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - protected String defaultAction(Element e, Void p) { - return ""; - } - }.visit(member); - } - /** * Add the modifier for the member. The modifiers are ordered as specified * by The Java Language Specification. @@ -282,7 +262,7 @@ } } - protected String makeSpace(int len) { + protected CharSequence makeSpace(int len) { if (len <= 0) { return ""; } @@ -290,7 +270,7 @@ for (int i = 0; i < len; i++) { sb.append(' '); } - return sb.toString(); + return sb; } /** diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -199,8 +199,7 @@ Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel); Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); pkgNameDiv.addContent(getSpace()); - Content pkgNameContent = getPackageLink(pkg, - new StringContent(pkg.getQualifiedName().toString())); + Content pkgNameContent = getPackageLink(pkg, new StringContent(pkg.getQualifiedName())); pkgNameDiv.addContent(pkgNameContent); div.addContent(pkgNameDiv); } @@ -395,10 +394,10 @@ new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE, typeElement)); if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) { - li.addContent(utils.asTypeElement(type).getSimpleName().toString()); + li.addContent(utils.asTypeElement(type).getSimpleName()); li.addContent(typeParameters); } else { - li.addContent(utils.asTypeElement(type).getQualifiedName().toString()); + li.addContent(utils.asTypeElement(type).getQualifiedName()); li.addContent(typeParameters); } } else { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -244,7 +244,7 @@ PackageElement enclosingPackage = utils.containingPackage(typeElement); if (!enclosingPackage.isUnnamed()) { Content cb = new ContentBuilder(); - cb.addContent(enclosingPackage.getQualifiedName().toString()); + cb.addContent(enclosingPackage.getQualifiedName()); cb.addContent("."); cb.addContent(classlink); return getClassName(cb); @@ -332,7 +332,7 @@ */ private Content getNameColumn(VariableElement member) { Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY, - member, member.getSimpleName().toString(), false); + member, member.getSimpleName(), false); Content code = HtmlTree.CODE(nameContent); return HtmlTree.TD(code); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -166,6 +166,8 @@ HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV); + final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*"); + /** * Constructor to construct the HtmlStandardWriter object. * @@ -945,7 +947,7 @@ public Content getPackageName(PackageElement packageElement) { return packageElement == null || packageElement.isUnnamed() ? defaultPackageLabel - : getPackageLabel(packageElement.getQualifiedName().toString()); + : getPackageLabel(packageElement.getQualifiedName()); } /** @@ -954,7 +956,7 @@ * @param packageName the package name * @return the package name content */ - public Content getPackageLabel(String packageName) { + public Content getPackageLabel(CharSequence packageName) { return new StringContent(packageName); } @@ -1038,7 +1040,7 @@ * @param label the label for the link. * @return a content tree for the package link. */ - public Content getPackageLink(PackageElement packageElement, String label) { + public Content getPackageLink(PackageElement packageElement, CharSequence label) { return getPackageLink(packageElement, new StringContent(label)); } @@ -1081,7 +1083,7 @@ public Content interfaceName(TypeElement typeElement, boolean qual) { Content name = new StringContent((qual) - ? typeElement.getQualifiedName().toString() + ? typeElement.getQualifiedName() : utils.getSimpleName(typeElement)); return (utils.isInterface(typeElement)) ? HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name; } @@ -1279,7 +1281,7 @@ * @param label the label for the link * @return a content tree for the element link */ - public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label) { + public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, new StringContent(label)); } @@ -1293,7 +1295,7 @@ * @param strong true if the link should be strong. * @return the link for the given member. */ - public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label, + public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label, boolean strong) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong); } @@ -1311,7 +1313,7 @@ * @return the link for the given member. */ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, - String label, boolean strong) { + CharSequence label, boolean strong) { return getDocLink(context, typeElement, element, label, strong, false); } @@ -1334,13 +1336,14 @@ * @return the link for the given member. */ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, - String label, boolean strong, boolean isProperty) { + CharSequence label, boolean strong, boolean isProperty) { return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty); } - String check(String s) { - if (s.matches(".*[&<>].*")) { - throw new IllegalArgumentException(s); + CharSequence check(CharSequence s) { + Matcher m = IMPROPER_HTML_CHARS.matcher(s); + if (m.matches()) { + throw new IllegalArgumentException(s.toString()); } return s; } @@ -1426,7 +1429,7 @@ CommentHelper ch = utils.getCommentHelper(element); String tagName = ch.getTagName(see); - String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see))); + String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see)).toString()); // Check if @see is an href or "string" if (seetext.startsWith("<") || seetext.startsWith("\"")) { return new RawHtml(seetext); @@ -1452,7 +1455,7 @@ //@see is referencing an included package if (label.isEmpty()) label = plainOrCode(isLinkPlain, - new StringContent(refPackage.getQualifiedName().toString())); + new StringContent(refPackage.getQualifiedName())); return getPackageLink(refPackage, label); } else { // @see is not referencing an included class or package. Check for cross links. @@ -1695,7 +1698,7 @@ final Content result = new ContentBuilder() { @Override - public void addContent(String text) { + public void addContent(CharSequence text) { super.addContent(utils.normalizeNewlines(text)); } }; @@ -1741,7 +1744,7 @@ public Boolean visitAttribute(AttributeTree node, Content c) { StringBuilder sb = new StringBuilder(SPACER).append(node.getName()); if (node.getValueKind() == ValueKind.EMPTY) { - result.addContent(sb.toString()); + result.addContent(sb); return false; } sb.append("="); @@ -1758,7 +1761,7 @@ break; } sb.append(quote); - result.addContent(sb.toString()); + result.addContent(sb); Content docRootContent = new ContentBuilder(); for (DocTree dt : node.getValue()) { @@ -1767,16 +1770,15 @@ if (text.startsWith("/..") && !configuration.docrootparent.isEmpty()) { result.addContent(configuration.docrootparent); docRootContent = new ContentBuilder(); - text = textCleanup(text.substring(3), isLast(node)); + result.addContent(textCleanup(text.substring(3), isLast(node))); } else { if (!docRootContent.isEmpty()) { docRootContent = copyDocRootContent(docRootContent); } else { text = redirectRelativeLinks(element, (TextTree) dt); } - text = textCleanup(text, isLast(node)); + result.addContent(textCleanup(text, isLast(node))); } - result.addContent(text); } else { docRootContent = copyDocRootContent(docRootContent); dt.accept(this, docRootContent); @@ -1889,8 +1891,7 @@ @Override @DefinedBy(Api.COMPILER_TREE) public Boolean visitStartElement(StartElementTree node, Content c) { String text = "<" + node.getName(); - text = utils.normalizeNewlines(text); - RawHtml rawHtml = new RawHtml(text); + RawHtml rawHtml = new RawHtml(utils.normalizeNewlines(text)); result.addContent(rawHtml); for (DocTree dt : node.getAttributes()) { @@ -1900,11 +1901,11 @@ return false; } - private String textCleanup(String text, boolean isLast) { + private CharSequence textCleanup(String text, boolean isLast) { return textCleanup(text, isLast, false); } - private String textCleanup(String text, boolean isLast, boolean trimLeader) { + private CharSequence textCleanup(String text, boolean isLast, boolean trimLeader) { if (trimLeader) { text = removeLeadingWhitespace(text); } @@ -1912,16 +1913,14 @@ text = removeTrailingWhitespace(text); } text = utils.replaceTabs(text); - text = utils.normalizeNewlines(text); - return text; + return utils.normalizeNewlines(text); } @Override @DefinedBy(Api.COMPILER_TREE) public Boolean visitText(TextTree node, Content c) { String text = node.getBody(); - text = textCleanup(text, isLast(node), commentRemoved); + result.addContent(new RawHtml(textCleanup(text, isLast(node), commentRemoved))); commentRemoved = false; - result.addContent(new RawHtml(text)); return false; } @@ -2358,7 +2357,8 @@ private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo, ContentBuilder annotation, Mapmap, int indent, boolean linkBreak) { - linkInfo.label = new StringContent("@" + annotationDoc.getSimpleName().toString()); + linkInfo.label = new StringContent("@"); + linkInfo.label.addContent(annotationDoc.getSimpleName()); annotation.addContent(getLink(linkInfo)); if (!map.isEmpty()) { annotation.addContent("("); @@ -2372,7 +2372,7 @@ annotation.addContent(","); if (linkBreak) { annotation.addContent(DocletConstants.NL); - int spaces = annotationDoc.getSimpleName().toString().length() + 2; + int spaces = annotationDoc.getSimpleName().length() + 2; for (int k = 0; k < (spaces + indent); k++) { annotation.addContent(" "); } @@ -2496,7 +2496,7 @@ @Override @DefinedBy(Api.LANGUAGE_MODEL) public Content visitEnumConstant(VariableElement c, Void p) { return getDocLink(LinkInfoImpl.Kind.ANNOTATION, - c, c.getSimpleName().toString(), false); + c, c.getSimpleName(), false); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public Content visitArray(List vals, Void p) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -294,7 +294,7 @@ * Set the label for the link. * @param label plain-text label for the link */ - public LinkInfoImpl label(String label) { + public LinkInfoImpl label(CharSequence label) { this.label = new StringContent(label); return this; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -356,11 +356,10 @@ Content overriddenTypeLink = writer.getLink(new LinkInfoImpl(writer.configuration, context, overriddenType)); Content codeOverridenTypeLink = HtmlTree.CODE(overriddenTypeLink); - String name = method.getSimpleName().toString(); Content methlink = writer.getLink( new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER, holder) - .where(writer.getName(writer.getAnchor(method))).label(name)); + .where(writer.getName(writer.getAnchor(method))).label(method.getSimpleName())); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); dd.addContent(writer.getSpace()); @@ -395,7 +394,7 @@ dl.addContent(dt); Content methlink = writer.getDocLink( LinkInfoImpl.Kind.MEMBER, implementedMeth, - implementedMeth.getSimpleName().toString(), false); + implementedMeth.getSimpleName(), false); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); dd.addContent(writer.getSpace()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -123,7 +123,7 @@ packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME, packageLabel, "", "packageFrame"); } else { - packageLabel = getPackageLabel(pe.getQualifiedName().toString()); + packageLabel = getPackageLabel(pe.getQualifiedName()); packageLinkContent = getHyperLink(pathString(pe, DocPaths.PACKAGE_FRAME), packageLabel, "", "packageFrame"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -158,7 +158,7 @@ writer.getDocLink(LinkInfoImpl.Kind.PROPERTY_COPY, holder, property, utils.isIncluded(holder) - ? holder.toString() : utils.getFullyQualifiedName(holder), + ? holder.getSimpleName() : holder.getQualifiedName(), false); Content codeLink = HtmlTree.CODE(link); Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel, diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java Mon Mar 21 11:21:08 2016 +0100 @@ -91,8 +91,7 @@ */ protected Content codeTagOutput(Element element, DocTree tag) { CommentHelper ch = utils.getCommentHelper(element); - String str = utils.normalizeNewlines(ch.getText(tag)); - StringContent content = new StringContent(str); + StringContent content = new StringContent(utils.normalizeNewlines(ch.getText(tag))); Content result = HtmlTree.CODE(content); return result; } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,8 @@ * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,8 +50,8 @@ } @Override - public void addContent(String text) { - if (text.isEmpty()) + public void addContent(CharSequence text) { + if (text.length() == 0) return; ensureMutableContents(); Content c = contents.isEmpty() ? null : contents.get(contents.size() - 1); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,8 @@ * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,8 @@ * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Mon Mar 21 11:21:08 2016 +0100 @@ -132,7 +132,8 @@ * * @param stringContent string content that needs to be added */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { if (!content.isEmpty()) { Content lastContent = content.get(content.size() - 1); if (lastContent instanceof StringContent) diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Mon Mar 21 11:21:08 2016 +0100 @@ -475,7 +475,7 @@ addStyles(HtmlStyle.rowColor, vars); addStyles(HtmlStyle.tableTab, vars); addStyles(HtmlStyle.activeTableTab, vars); - script.addContent(new RawHtml(vars.toString())); + script.addContent(new RawHtml(vars)); } /** diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,8 +53,8 @@ * * @param rawHtml raw HTML text to be added */ - public RawHtml(String rawHtml) { - rawHtmlContent = nullCheck(rawHtml); + public RawHtml(CharSequence rawHtml) { + rawHtmlContent = rawHtml.toString(); } /** @@ -77,7 +77,8 @@ * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } @@ -103,7 +104,7 @@ return charCount(rawHtmlContent); } - static int charCount(String htmlText) { + static int charCount(CharSequence htmlText) { State state = State.TEXT; int count = 0; for (int i = 0; i < htmlText.length(); i++) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * * @param initialContent initial content for the object */ - public StringContent(String initialContent) { + public StringContent(CharSequence initialContent) { stringContent = new StringBuilder(); appendChars(initialContent); } @@ -83,7 +83,7 @@ * @param strContent string content to be added */ @Override - public void addContent(String strContent) { + public void addContent(CharSequence strContent) { appendChars(strContent); } @@ -118,7 +118,7 @@ return s.endsWith(DocletConstants.NL); } - private void appendChars(String s) { + private void appendChars(CharSequence s) { for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch (ch) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ * * @param stringContent the string content to be added */ - public abstract void addContent(String stringContent); + public abstract void addContent(CharSequence stringContent); /** * Writes content to a writer. diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Mon Mar 21 11:21:08 2016 +0100 @@ -1356,7 +1356,7 @@ return result.toString(); } - public String normalizeNewlines(String text) { + public CharSequence normalizeNewlines(CharSequence text) { StringBuilder sb = new StringBuilder(); final int textLength = text.length(); final String NL = DocletConstants.NL; @@ -1379,7 +1379,7 @@ } } sb.append(text, pos, textLength); - return sb.toString(); + return sb; } /** @@ -1746,6 +1746,8 @@ * A generic utility which returns the fully qualified names of an entity, * if the entity is not qualifiable then its enclosing entity, it is upto * the caller to add the elements name as required. + * @param e the element to get FQN for. + * @return the name */ public String getFullyQualifiedName(Element e) { return getFullyQualifiedName(e, true); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java Mon Mar 21 11:21:08 2016 +0100 @@ -38,7 +38,7 @@ "jdk.httpserver", "jdk.security.auth", "jdk.naming.dns", "jdk.naming.rmi", "jdk.management"), - FULL_JRE("Full JRE", 4, "java.se", "jdk.deploy.osx", "jdk.charsets", + FULL_JRE("Full JRE", 4, "java.se", "jdk.charsets", "jdk.crypto.ec", "jdk.crypto.pkcs11", "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat", "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.internal.jshell.tool; + +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * Parse command arguments, derived from StreamTokenizer by + * @author James Gosling + */ +class ArgTokenizer { + + private final String str; + private final int length; + private int next = 0; + private char buf[] = new char[20]; + private int mark; + + private final byte ctype[] = new byte[256]; + private static final byte CT_ALPHA = 0; + private static final byte CT_WHITESPACE = 1; + private static final byte CT_QUOTE = 8; + + private String sval; + private boolean isQuoted = false; + + ArgTokenizer(String arg) { + this.str = arg; + this.length = arg.length(); + quoteChar('"'); + quoteChar('\''); + whitespaceChars(0x09, 0x0D); + whitespaceChars(0x1C, 0x20); + whitespaceChars(0x85, 0x85); + whitespaceChars(0xA0, 0xA0); + } + + String next() { + nextToken(); + return sval; + } + + String[] next(String... strings) { + return next(Arrays.stream(strings)); + } + + String[] next(Stream stream) { + nextToken(); + if (sval == null) { + return null; + } + String[] matches = stream + .filter(s -> s.startsWith(sval)) + .toArray(size -> new String[size]); + return matches; + } + + String val() { + return sval; + } + + boolean isQuoted() { + return isQuoted; + } + + String whole() { + return str; + } + + void mark() { + mark = next; + } + + void rewind() { + next = mark; + } + + /** + * Reads a single character. + * + * @return The character read, or -1 if the end of the stream has been + * reached + */ + private int read() { + if (next >= length) { + return -1; + } + return str.charAt(next++); + } + + /** + * Specifies that all characters c in the range + * low <= c <= high + * are white space characters. White space characters serve only to + * separate tokens in the input stream. + * + *

    Any other attribute settings for the characters in the specified + * range are cleared. + * + * @param low the low end of the range. + * @param hi the high end of the range. + */ + private void whitespaceChars(int low, int hi) { + if (low < 0) + low = 0; + if (hi >= ctype.length) + hi = ctype.length - 1; + while (low <= hi) + ctype[low++] = CT_WHITESPACE; + } + + /** + * Specifies that matching pairs of this character delimit string + * constants in this tokenizer. + *

    + * If a string quote character is encountered, then a string is + * recognized, consisting of all characters after (but not including) + * the string quote character, up to (but not including) the next + * occurrence of that same string quote character, or a line + * terminator, or end of file. The usual escape sequences such as + * {@code "\u005Cn"} and {@code "\u005Ct"} are recognized and + * converted to single characters as the string is parsed. + * + *

    Any other attribute settings for the specified character are cleared. + * + * @param ch the character. + */ + private void quoteChar(int ch) { + if (ch >= 0 && ch < ctype.length) + ctype[ch] = CT_QUOTE; + } + + private int unicode2ctype(int c) { + switch (c) { + case 0x1680: + case 0x180E: + case 0x200A: + case 0x202F: + case 0x205F: + case 0x3000: + return CT_WHITESPACE; + default: + return CT_ALPHA; + } + } + + /** + * Parses the next token of this tokenizer. + */ + public void nextToken() { + byte ct[] = ctype; + int c; + int lctype; + sval = null; + isQuoted = false; + + do { + c = read(); + if (c < 0) { + return; + } + lctype = (c < 256) ? ct[c] : unicode2ctype(c); + } while (lctype == CT_WHITESPACE); + + if (lctype == CT_ALPHA) { + int i = 0; + do { + if (i >= buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[i++] = (char) c; + c = read(); + lctype = c < 0 ? CT_WHITESPACE : (c < 256)? ct[c] : unicode2ctype(c); + } while (lctype == CT_ALPHA); + if (c >= 0) --next; // push last back + sval = String.copyValueOf(buf, 0, i); + return; + } + + if (lctype == CT_QUOTE) { + int quote = c; + int i = 0; + /* Invariants (because \Octal needs a lookahead): + * (i) c contains char value + * (ii) d contains the lookahead + */ + int d = read(); + while (d >= 0 && d != quote) { + if (d == '\\') { + c = read(); + int first = c; /* To allow \377, but not \477 */ + if (c >= '0' && c <= '7') { + c = c - '0'; + int c2 = read(); + if ('0' <= c2 && c2 <= '7') { + c = (c << 3) + (c2 - '0'); + c2 = read(); + if ('0' <= c2 && c2 <= '7' && first <= '3') { + c = (c << 3) + (c2 - '0'); + d = read(); + } else + d = c2; + } else + d = c2; + } else { + switch (c) { + case 'a': + c = 0x7; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = 0xC; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = 0xB; + break; + } + d = read(); + } + } else { + c = d; + d = read(); + } + if (i >= buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[i++] = (char)c; + } + + if (d == quote) { + isQuoted = true; + } + sval = String.copyValueOf(buf, 0, i); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Mon Mar 21 11:21:08 2016 +0100 @@ -48,6 +48,7 @@ import jdk.internal.jline.NoInterruptUnixTerminal; import jdk.internal.jline.Terminal; import jdk.internal.jline.TerminalFactory; +import jdk.internal.jline.UnsupportedTerminal; import jdk.internal.jline.WindowsTerminal; import jdk.internal.jline.console.ConsoleReader; import jdk.internal.jline.console.KeyMap; @@ -68,7 +69,9 @@ this.repl = repl; this.input = new StopDetectingInputStream(() -> repl.state.stop(), ex -> repl.hard("Error on input: %s", ex)); Terminal term; - if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { + if (System.getProperty("test.jdk") != null) { + term = new UnsupportedTerminal(); + } else if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { term = new JShellWindowsTerminal(input); } else { term = new JShellUnixTerminal(input); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.internal.jshell.tool; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Feedback customization support + * + * @author Robert Field + */ +class Feedback { + + // Patern for substituted fields within a customized format string + private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(.*?)\\}"); + + // Current mode + private Mode mode = new Mode("", false); // initial value placeholder during start-up + + // Mapping of mode names to mode modes + private final Map modeMap = new HashMap<>(); + + public boolean shouldDisplayCommandFluff() { + return mode.commandFluff; + } + + public String getPre() { + return mode.pre; + } + + public String getPost() { + return mode.post; + } + + public String getErrorPre() { + return mode.errorPre; + } + + public String getErrorPost() { + return mode.errorPost; + } + + public String getFormat(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + return mode.getFormat(fc, fw, fa, fr, hasName, hasType, hasResult); + } + + public String getPrompt(String nextId) { + return mode.getPrompt(nextId); + } + + public String getContinuationPrompt(String nextId) { + return mode.getContinuationPrompt(nextId); + } + + public boolean setFeedback(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setFeedback(); + } + + public boolean setField(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setField(); + } + + public boolean setFormat(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setFormat(); + } + + public boolean setNewMode(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setNewMode(); + } + + public boolean setPrompt(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setPrompt(); + } + + public void printFeedbackHelp(JShellTool tool) { + new FormatSetter(tool, null).printFeedbackHelp(); + } + + public void printFieldHelp(JShellTool tool) { + new FormatSetter(tool, null).printFieldHelp(); + } + + public void printFormatHelp(JShellTool tool) { + new FormatSetter(tool, null).printFormatHelp(); + } + + public void printNewModeHelp(JShellTool tool) { + new FormatSetter(tool, null).printNewModeHelp(); + } + + public void printPromptHelp(JShellTool tool) { + new FormatSetter(tool, null).printPromptHelp(); + } + + /** + * Holds all the context of a mode mode + */ + private class Mode { + + // Use name of mode mode + + final String name; + + // Display command verification/information + final boolean commandFluff; + + // event cases: class, method + final EnumMap>> cases; + + // action names: add. modified, replaced, ... + final EnumMap> actions; + + // resolution status description format with %s for unresolved + final EnumMap> resolves; + + // primary snippet vs update + final EnumMap whens; + + // fixed map of how to get format string for a field, given a specific formatting contet + final EnumMap> fields; + + // format wrappers for name, type, and result + String fname = "%s"; + String ftype = "%s"; + String fresult = "%s"; + + // start and end, also used by hard-coded output + String pre = "| "; + String post = "\n"; + String errorPre = "| Error: "; + String errorPost = "\n"; + + String prompt = "\n-> "; + String continuationPrompt = ">> "; + + /** + * The context of a specific mode to potentially display. + */ + class Context { + + final FormatCase fc; + final FormatAction fa; + final FormatResolve fr; + final FormatWhen fw; + final boolean hasName; + final boolean hasType; + final boolean hasResult; + + Context(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + this.fc = fc; + this.fa = fa; + this.fr = fr; + this.fw = fw; + this.hasName = hasName; + this.hasType = hasType; + this.hasResult = hasResult; + } + + String when() { + return whens.get(fw); + } + + String action() { + return actions.get(fa).get(fw); + } + + String resolve() { + return String.format(resolves.get(fr).get(fw), FormatField.RESOLVE.form); + } + + String name() { + return hasName + ? String.format(fname, FormatField.NAME.form) + : ""; + } + + String type() { + return hasType + ? String.format(ftype, FormatField.TYPE.form) + : ""; + } + + String result() { + return hasResult + ? String.format(fresult, FormatField.RESULT.form) + : ""; + } + + /** + * Lookup format based on case, action, and whether it update. + * Replace fields with context specific formats. + * + * @return format string + */ + String format() { + String format = cases.get(fc).get(fa).get(fw); + if (format == null) { + return ""; + } + Matcher m = FIELD_PATTERN.matcher(format); + StringBuffer sb = new StringBuffer(format.length()); + while (m.find()) { + String fieldName = m.group(1).toUpperCase(Locale.US); + String sub = null; + for (FormatField f : FormatField.values()) { + if (f.name().startsWith(fieldName)) { + sub = fields.get(f).apply(this); + break; + } + } + if (sub != null) { + m.appendReplacement(sb, Matcher.quoteReplacement(sub)); + } + } + m.appendTail(sb); + return sb.toString(); + } + } + + { + // set fixed mappings of fields + fields = new EnumMap<>(FormatField.class); + fields.put(FormatField.WHEN, c -> c.when()); + fields.put(FormatField.ACTION, c -> c.action()); + fields.put(FormatField.RESOLVE, c -> c.resolve()); + fields.put(FormatField.NAME, c -> c.name()); + fields.put(FormatField.TYPE, c -> c.type()); + fields.put(FormatField.RESULT, c -> c.result()); + fields.put(FormatField.PRE, c -> pre); + fields.put(FormatField.POST, c -> post); + fields.put(FormatField.ERRORPRE, c -> errorPre); + fields.put(FormatField.ERRORPOST, c -> errorPost); + } + + /** + * Set up an empty mode. + * + * @param name + * @param commandFluff True if should display command fluff messages + */ + Mode(String name, boolean commandFluff) { + this.name = name; + this.commandFluff = commandFluff; + cases = new EnumMap<>(FormatCase.class); + for (FormatCase fc : FormatCase.values()) { + EnumMap> ac = new EnumMap<>(FormatAction.class); + cases.put(fc, ac); + for (FormatAction fa : FormatAction.values()) { + EnumMap aw = new EnumMap<>(FormatWhen.class); + ac.put(fa, aw); + for (FormatWhen fw : FormatWhen.values()) { + aw.put(fw, ""); + } + } + } + + actions = new EnumMap<>(FormatAction.class); + for (FormatAction fa : FormatAction.values()) { + EnumMap afw = new EnumMap<>(FormatWhen.class); + actions.put(fa, afw); + for (FormatWhen fw : FormatWhen.values()) { + afw.put(fw, fa.name() + "-" + fw.name()); + } + } + + resolves = new EnumMap<>(FormatResolve.class); + for (FormatResolve fr : FormatResolve.values()) { + EnumMap arw = new EnumMap<>(FormatWhen.class); + resolves.put(fr, arw); + for (FormatWhen fw : FormatWhen.values()) { + arw.put(fw, fr.name() + "-" + fw.name() + ": %s"); + } + } + + whens = new EnumMap<>(FormatWhen.class); + for (FormatWhen fw : FormatWhen.values()) { + whens.put(fw, fw.name()); + } + } + + /** + * Set up a copied mode. + * + * @param name + * @param commandFluff True if should display command fluff messages + * @param m Mode to copy + */ + Mode(String name, boolean commandFluff, Mode m) { + this.name = name; + this.commandFluff = commandFluff; + cases = new EnumMap<>(FormatCase.class); + for (FormatCase fc : FormatCase.values()) { + EnumMap> ac = new EnumMap<>(FormatAction.class); + EnumMap> mc = m.cases.get(fc); + cases.put(fc, ac); + for (FormatAction fa : FormatAction.values()) { + EnumMap aw = new EnumMap<>(mc.get(fa)); + ac.put(fa, aw); + } + } + + actions = new EnumMap<>(FormatAction.class); + for (FormatAction fa : FormatAction.values()) { + EnumMap afw = new EnumMap<>(m.actions.get(fa)); + actions.put(fa, afw); + } + + resolves = new EnumMap<>(FormatResolve.class); + for (FormatResolve fr : FormatResolve.values()) { + EnumMap arw = new EnumMap<>(m.resolves.get(fr)); + resolves.put(fr, arw); + } + + whens = new EnumMap<>(m.whens); + + this.fname = m.fname; + this.ftype = m.ftype; + this.fresult = m.fresult; + this.pre = m.pre; + this.post = m.post; + this.errorPre = m.errorPre; + this.errorPost = m.errorPost; + this.prompt = m.prompt; + this.continuationPrompt = m.continuationPrompt; + } + + String getFormat(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + Context context = new Context(fc, fw, fa, fr, + hasName, hasType, hasResult); + return context.format(); + } + + void setCases(String format, Collection cc, Collection ca, Collection cw) { + for (FormatCase fc : cc) { + EnumMap> ma = cases.get(fc); + for (FormatAction fa : ca) { + EnumMap mw = ma.get(fa); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + } + + void setActions(String format, Collection ca, Collection cw) { + for (FormatAction fa : ca) { + EnumMap mw = actions.get(fa); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + + void setResolves(String format, Collection cr, Collection cw) { + for (FormatResolve fr : cr) { + EnumMap mw = resolves.get(fr); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + + void setWhens(String format, Collection cw) { + for (FormatWhen fw : cw) { + whens.put(fw, format); + } + } + + void setName(String s) { + fname = s; + } + + void setType(String s) { + ftype = s; + } + + void setResult(String s) { + fresult = s; + } + + void setPre(String s) { + pre = s; + } + + void setPost(String s) { + post = s; + } + + void setErrorPre(String s) { + errorPre = s; + } + + void setErrorPost(String s) { + errorPost = s; + } + + String getPre() { + return pre; + } + + String getPost() { + return post; + } + + String getErrorPre() { + return errorPre; + } + + String getErrorPost() { + return errorPost; + } + + void setPrompts(String prompt, String continuationPrompt) { + this.prompt = prompt; + this.continuationPrompt = continuationPrompt; + } + + String getPrompt(String nextId) { + return String.format(prompt, nextId); + } + + String getContinuationPrompt(String nextId) { + return String.format(continuationPrompt, nextId); + } + } + + /** + * The brace delimited substitutions + */ + public enum FormatField { + WHEN, + ACTION, + RESOLVE("%1$s"), + NAME("%2$s"), + TYPE("%3$s"), + RESULT("%4$s"), + PRE, + POST, + ERRORPRE, + ERRORPOST; + String form; + + FormatField(String s) { + this.form = s; + } + + FormatField() { + this.form = null; + } + } + + /** + * The event cases + */ + public enum FormatCase { + IMPORT("import declaration: {action} {name}"), + CLASS("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + INTERFACE("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + ENUM("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + ANNOTATION("annotation interface declaration: {action} {name} {resolve}"), + METHOD("method declaration: {action} {name} {type}==parameter-types {resolve}"), + VARDECL("variable declaration: {action} {name} {type} {resolve}"), + VARDECLRECOVERABLE("recoverably failed variable declaration: {action} {name} {resolve}"), + VARINIT("variable declaration with init: {action} {name} {type} {resolve} {result}"), + VARRESET("variable reset on update: {action} {name}"), + EXPRESSION("expression: {action}=='Saved to scratch variable' {name} {type} {result}"), + VARVALUE("variable value expression: {action} {name} {type} {result}"), + ASSIGNMENT("assign variable: {action} {name} {type} {result}"), + STATEMENT("statement: {action}"); + String doc; + + private FormatCase(String doc) { + this.doc = doc; + } + } + + /** + * The event actions + */ + public enum FormatAction { + ADDED("snippet has been added"), + MODIFIED("an existing snippet has been modified"), + REPLACED("an existing snippet has been replaced with a new snippet"), + OVERWROTE("an existing snippet has been overwritten"), + DROPPED("snippet has been dropped"), + REJECTED("snippet has failed and been rejected"); + String doc; + + private FormatAction(String doc) { + this.doc = doc; + } + } + + /** + * When the event occurs: primary or update + */ + public enum FormatWhen { + PRIMARY("the entered snippet"), + UPDATE("an update to a dependent snippet"); + String doc; + + private FormatWhen(String doc) { + this.doc = doc; + } + } + + /** + * Resolution problems with event + */ + public enum FormatResolve { + OK("resolved correctly"), + DEFINED("defined despite recoverably unresolved references"), + NOTDEFINED("not defined because of recoverably unresolved references"); + String doc; + + private FormatResolve(String doc) { + this.doc = doc; + } + } + + // Class used to set custom eval output formats + // For both /set format and /set field -- Parse arguments, setting custom format, or printing error + private class FormatSetter { + + private final ArgTokenizer at; + private final JShellTool tool; + boolean valid = true; + + class Case, E2 extends Enum, E3 extends Enum> { + + Set e1; + Set e2; + Set e3; + + Case(Set e1, Set e2, Set e3) { + this.e1 = e1; + this.e2 = e2; + this.e3 = e3; + } + + Case(Set e1, Set e2) { + this.e1 = e1; + this.e2 = e2; + } + } + + FormatSetter(JShellTool tool, ArgTokenizer at) { + this.tool = tool; + this.at = at; + } + + void hard(String format, Object... args) { + tool.hard(format, args); + } + + > void hardEnums(EnumSet es, Function e2s) { + hardPairs(es.stream(), ev -> ev.name().toLowerCase(Locale.US), e2s); + } + + void hardPairs(Stream stream, Function a, Function b) { + tool.hardPairs(stream, a, b); + } + + void fluff(String format, Object... args) { + tool.fluff(format, args); + } + + void error(String format, Object... args) { + tool.error(format, args); + } + + void errorat(String format, Object... args) { + Object[] a2 = Arrays.copyOf(args, args.length + 1); + a2[args.length] = at.whole(); + tool.error(format + " -- /set %s", a2); + } + + void fluffRaw(String format, Object... args) { + tool.fluffRaw(format, args); + } + + // For /set prompt "" "" + boolean setPrompt() { + Mode m = nextMode(); + String prompt = nextFormat(); + String continuationPrompt = nextFormat(); + if (valid) { + m.setPrompts(prompt, continuationPrompt); + } else { + fluff("See '/help /set prompt' for help"); + } + return valid; + } + + // For /set newmode [command|quiet []] + boolean setNewMode() { + String umode = at.next(); + if (umode == null) { + errorat("Expected new feedback mode"); + valid = false; + } + if (modeMap.containsKey(umode)) { + errorat("Expected a new feedback mode name. %s is a known feedback mode", umode); + valid = false; + } + String[] fluffOpt = at.next("command", "quiet"); + boolean fluff = fluffOpt == null || fluffOpt.length != 1 || "command".equals(fluffOpt[0]); + if (fluffOpt != null && fluffOpt.length != 1) { + errorat("Specify either 'command' or 'quiet'"); + valid = false; + } + Mode om = null; + String omode = at.next(); + if (omode != null) { + om = toMode(omode); + } + if (valid) { + Mode nm = (om != null) + ? new Mode(umode, fluff, om) + : new Mode(umode, fluff); + modeMap.put(umode, nm); + fluff("Created new feedback mode: %s", nm.name); + } else { + fluff("See '/help /set newmode' for help"); + } + return valid; + } + + // For /set feedback + boolean setFeedback() { + Mode m = nextMode(); + if (valid && m != null) { + mode = m; + fluff("Feedback mode: %s", mode.name); + } else { + fluff("See '/help /set feedback' for help"); + } + return valid; + } + + // For /set format "" ... + boolean setFormat() { + Mode m = nextMode(); + String format = nextFormat(); + if (valid) { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatCase(d, 0), + parseFormatAction(d, 1), + parseFormatWhen(d, 2) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format in the specified cases + specs.stream() + .forEach(c -> m.setCases(format, c.e1, c.e2, c.e3)); + } + } + if (!valid) { + fluff("See '/help /set format' for help"); + } + return valid; + } + + // For /set field mode "" ... + boolean setField() { + Mode m = nextMode(); + String fieldName = at.next(); + FormatField field = parseFormatSelector(fieldName, EnumSet.allOf(FormatField.class), "field"); + String format = nextFormat(); + if (valid) { + switch (field) { + case ACTION: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatAction(d, 0), + parseFormatWhen(d, 1) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified actions + specs.stream() + .forEach(c -> m.setActions(format, c.e1, c.e2)); + } + break; + } + case RESOLVE: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatResolve(d, 0), + parseFormatWhen(d, 1) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified resolves + specs.stream() + .forEach(c -> m.setResolves(format, c.e1, c.e2)); + } + break; + } + case WHEN: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatWhen(d, 1), + null + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified whens + specs.stream() + .forEach(c -> m.setWhens(format, c.e1)); + } + break; + } + case NAME: { + m.setName(format); + break; + } + case TYPE: { + m.setType(format); + break; + } + case RESULT: { + m.setResult(format); + break; + } + case PRE: { + m.setPre(format); + break; + } + case POST: { + m.setPost(format); + break; + } + case ERRORPRE: { + m.setErrorPre(format); + break; + } + case ERRORPOST: { + m.setErrorPost(format); + break; + } + } + } + if (!valid) { + fluff("See '/help /set field' for help"); + } + return valid; + } + + Mode nextMode() { + String umode = at.next(); + return toMode(umode); + } + + Mode toMode(String umode) { + if (umode == null) { + errorat("Expected a feedback mode"); + valid = false; + return null; + } + Mode m = modeMap.get(umode); + if (m != null) { + return m; + } + // Failing an exact match, go searching + Mode[] matches = modeMap.entrySet().stream() + .filter(e -> e.getKey().startsWith(umode)) + .map(e -> e.getValue()) + .toArray(size -> new Mode[size]); + if (matches.length == 1) { + return matches[0]; + } else { + valid = false; + if (matches.length == 0) { + errorat("Does not match any current feedback mode: %s", umode); + } else { + errorat("Matchs more then one current feedback mode: %s", umode); + } + fluff("The feedback mode should be one of the following:"); + modeMap.keySet().stream() + .forEach(mk -> fluff(" %s", mk)); + fluff("You may also use just enough letters to make it unique."); + return null; + } + } + + // Test if the format string is correctly + final String nextFormat() { + String format = at.next(); + if (format == null) { + errorat("Expected format missing"); + valid = false; + return null; + } + if (!at.isQuoted()) { + errorat("Format '%s' must be quoted", format); + valid = false; + return null; + } + return format; + } + + final Set parseFormatCase(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatCase.class, EnumSet.allOf(FormatCase.class), "case"); + } + + final Set parseFormatAction(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatAction.class, + EnumSet.of(FormatAction.ADDED, FormatAction.MODIFIED, FormatAction.REPLACED), "action"); + } + + final Set parseFormatResolve(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatResolve.class, + EnumSet.of(FormatResolve.DEFINED, FormatResolve.NOTDEFINED), "resolve"); + } + + final Set parseFormatWhen(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatWhen.class, EnumSet.of(FormatWhen.PRIMARY), "when"); + } + + /** + * In a selector x-y-z , parse x, y, or z -- whether they are missing, + * or a comma separated list of identifiers and stars. + * + * @param The enum this selector should belong to + * @param sa The array of selector strings + * @param i The index of which selector string to use + * @param klass The class of the enum that should be used + * @param defaults The set of enum values to use if the selector is + * missing + * @return The set of enum values specified by this selector + */ + final > Set parseFormatSelectorStar(String[] sa, int i, Class klass, EnumSet defaults, String label) { + String s = sa.length > i + ? sa[i] + : null; + if (s == null || s.isEmpty()) { + return defaults; + } + Set set = EnumSet.noneOf(klass); + EnumSet values = EnumSet.allOf(klass); + for (String as : s.split(",")) { + if (as.equals("*")) { + set.addAll(values); + } else if (!as.isEmpty()) { + set.add(parseFormatSelector(as, values, label)); + } + } + return set; + } + + /** + * In a x-y-a,b selector, parse an x, y, a, or b -- that is an + * identifier + * + * @param The enum this selector should belong to + * @param s The string to parse: x, y, or z + * @param values The allowed of this enum + * @return The enum value + */ + final > E parseFormatSelector(String s, EnumSet values, String label) { + if (s == null) { + valid = false; + return null; + } + String u = s.toUpperCase(Locale.US); + for (E c : values) { + if (c.name().startsWith(u)) { + return c; + } + } + + errorat("Not a valid %s: %s, must be one of: %s", label, s, + values.stream().map(v -> v.name().toLowerCase(Locale.US)).collect(Collectors.joining(" "))); + valid = false; + return values.iterator().next(); + } + + final void printFormatHelp() { + hard("Set the format for reporting a snippet event."); + hard(""); + hard("/set format \"\" ..."); + hard(""); + hard("Where is the name of a previously defined feedback mode -- see '/help /set newmode'."); + hard("Where is a quoted string which will have these field substitutions:"); + hard(" {action} == The action, e.g.: Added, Modified, Assigned, ..."); + hard(" {name} == The name, e.g.: the variable name, ..."); + hard(" {type} == The type name"); + hard(" {resolve} == Unresolved info, e.g.: ', however, it cannot be invoked until'"); + hard(" {result} == The result value"); + hard(" {when} == The entered snippet or a resultant update"); + hard(" {pre} == The feedback prefix"); + hard(" {post} == The feedback postfix"); + hard(" {errorpre} == The error prefix"); + hard(" {errorpost} == The error postfix"); + hard("Use '/set field' to set the format of these substitutions."); + hard("Where is the context in which the format is applied."); + hard("The structure of selector is: [-[-]]"); + hard("Where each field component may be missing (indicating defaults),"); + hard("star (indicating all), or a comma separated list of field values."); + hard("For case, the field values are:"); + hardEnums(EnumSet.allOf(FormatCase.class), ev -> ev.doc); + hard("For action, the field values are:"); + hardEnums(EnumSet.allOf(FormatAction.class), ev -> ev.doc); + hard("For when, the field values are:"); + hardEnums(EnumSet.allOf(FormatWhen.class), ev -> ev.doc); + hard(""); + hard("Example:"); + hard(" /set format example '{pre}{action} variable {name}, reset to null{post}' varreset-*-update"); + } + + final void printFieldHelp() { + hard("Set the format of a field substitution as used in '/set format'."); + hard(""); + hard("/set field \"\" ..."); + hard(""); + hard("Where is the name of a previously defined feedback mode -- see '/set newmode'."); + hard("Where is context-specific format to set, each with its own selector structure:"); + hard(" action == The action. The selector: -."); + hard(" name == The name. '%%s' is the name. No selectors."); + hard(" type == The type name. '%%s' is the type. No selectors."); + hard(" resolve == Unresolved info. '%%s' is the unresolved list. The selector: -."); + hard(" result == The result value. '%%s' is the result value. No selectors."); + hard(" when == The entered snippet or a resultant update. The selector: "); + hard(" pre == The feedback prefix. No selectors."); + hard(" post == The feedback postfix. No selectors."); + hard(" errorpre == The error prefix. No selectors."); + hard(" errorpost == The error postfix. No selectors."); + hard("Where is a quoted string -- see the description specific to the field (above)."); + hard("Where is the context in which the format is applied (see above)."); + hard("For action, the field values are:"); + hardEnums(EnumSet.allOf(FormatAction.class), ev -> ev.doc); + hard("For when, the field values are:"); + hardEnums(EnumSet.allOf(FormatWhen.class), ev -> ev.doc); + hard("For resolve, the field values are:"); + hardEnums(EnumSet.allOf(FormatResolve.class), ev -> ev.doc); + hard(""); + hard("Example:"); + hard(" /set field example resolve ' which cannot be invoked until%%s is declared' defined-update"); + } + + final void printFeedbackHelp() { + hard("Set the feedback mode describing displayed feedback for entered snippets and commands."); + hard(""); + hard("/set feedback "); + hard(""); + hard("Where is the name of a previously defined feedback mode."); + hard("Currently defined feedback modes:"); + modeMap.keySet().stream() + .forEach(m -> hard(" %s", m)); + hard("User-defined modes can be added, see '/help /set newmode'"); + } + + final void printNewModeHelp() { + hard("Create a user-defined feedback mode, optionally copying from an existing mode."); + hard(""); + hard("/set newmode [command|quiet []]"); + hard(""); + hard("Where is the name of a mode you wish to create."); + hard("Where is the name of a previously defined feedback mode."); + hard("If is present, its settings are copied to the new mode."); + hard("'command' vs 'quiet' determines if informative/verifying command feedback is displayed."); + hard(""); + hard("Once the new mode is created, use '/set format', '/set field', and '/set prompt' to configure it."); + hard("Use '/set feedback' to use the new mode."); + } + + final void printPromptHelp() { + hard("Set the prompts. Both the normal prompt and the continuation-prompt must be set."); + hard(""); + hard("/set prompt \"\" \"\""); + hard(""); + hard("Where is the name of a previously defined feedback mode."); + hard("Where and are quoted strings printed as input promptds;"); + hard("Both may optionally contain '%%s' which will be substituted with the next snippet id --"); + hard("note that what is entered may not be assigned that id, for example it may be an error or command."); + hard("The continuation-prompt is used on the second and subsequent lines of a multi-line snippet."); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +34,6 @@ import java.io.InputStream; import java.io.PrintStream; import java.io.Reader; -import java.io.StreamTokenizer; import java.io.StringReader; import java.nio.charset.Charset; import java.nio.file.AccessDeniedException; @@ -66,24 +64,25 @@ import jdk.internal.jshell.debug.InternalDebugControl; import jdk.internal.jshell.tool.IOContext.InputInterruptedException; +import jdk.jshell.DeclarationSnippet; import jdk.jshell.Diag; import jdk.jshell.EvalException; +import jdk.jshell.ExpressionSnippet; +import jdk.jshell.ImportSnippet; import jdk.jshell.JShell; -import jdk.jshell.Snippet; -import jdk.jshell.DeclarationSnippet; -import jdk.jshell.TypeDeclSnippet; +import jdk.jshell.JShell.Subscription; import jdk.jshell.MethodSnippet; import jdk.jshell.PersistentSnippet; -import jdk.jshell.VarSnippet; -import jdk.jshell.ExpressionSnippet; +import jdk.jshell.Snippet; import jdk.jshell.Snippet.Status; +import jdk.jshell.Snippet.SubKind; +import jdk.jshell.SnippetEvent; import jdk.jshell.SourceCodeAnalysis; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; import jdk.jshell.SourceCodeAnalysis.Suggestion; -import jdk.jshell.SnippetEvent; +import jdk.jshell.TypeDeclSnippet; import jdk.jshell.UnresolvedReferenceException; -import jdk.jshell.Snippet.SubKind; -import jdk.jshell.JShell.Subscription; +import jdk.jshell.VarSnippet; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; @@ -94,7 +93,13 @@ import java.util.Spliterators; import java.util.function.Function; import java.util.function.Supplier; +import jdk.internal.jshell.tool.Feedback.FormatAction; +import jdk.internal.jshell.tool.Feedback.FormatCase; +import jdk.internal.jshell.tool.Feedback.FormatResolve; +import jdk.internal.jshell.tool.Feedback.FormatWhen; import static java.util.stream.Collectors.toList; +import static jdk.jshell.Snippet.Kind.METHOD; +import static java.util.stream.Collectors.toMap; import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; /** @@ -103,6 +108,7 @@ */ public class JShellTool { + private static final String LINE_SEP = System.getProperty("line.separator"); private static final Pattern LINEBREAK = Pattern.compile("\\R"); private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile( "((?(all|history|start))(\\z|\\p{javaWhitespace}+))?(?.*)"); @@ -116,6 +122,8 @@ final PrintStream userout; final PrintStream usererr; + final Feedback feedback = new Feedback(); + /** * The constructor for the tool (used by tool launch via main and by test * harnesses to capture ins and outs. @@ -137,6 +145,70 @@ this.userin = userin; this.userout = userout; this.usererr = usererr; + initializeFeedbackModes(); + } + + /** + * Create the default set of feedback modes + */ + final void initializeFeedbackModes() { + // Initialize normal feedback mode + cmdSet("newmode normal command"); + cmdSet("prompt normal '\n-> ' '>> '"); + cmdSet("field normal pre '| '"); + cmdSet("field normal post '%n'"); + cmdSet("field normal errorpre '| '"); + cmdSet("field normal errorpost '%n'"); + cmdSet("field normal action 'Added' added-primary"); + cmdSet("field normal action 'Modified' modified-primary"); + cmdSet("field normal action 'Replaced' replaced-primary"); + cmdSet("field normal action 'Overwrote' overwrote-primary"); + cmdSet("field normal action 'Dropped' dropped-primary"); + cmdSet("field normal action 'Rejected' rejected-primary"); + cmdSet("field normal action ' Update added' added-update"); + cmdSet("field normal action ' Update modified' modified-update"); + cmdSet("field normal action ' Update replaced' replaced-update"); + cmdSet("field normal action ' Update overwrote' overwrote-update"); + cmdSet("field normal action ' Update dropped' dropped-update"); + cmdSet("field normal action ' Update rejected' rejected-update"); + cmdSet("field normal resolve '' ok-*"); + cmdSet("field normal resolve ', however, it cannot be invoked until%s is declared' defined-primary"); + cmdSet("field normal resolve ', however, it cannot be referenced until%s is declared' notdefined-primary"); + cmdSet("field normal resolve ' which cannot be invoked until%s is declared' defined-update"); + cmdSet("field normal resolve ' which cannot be referenced until%s is declared' notdefined-update"); + cmdSet("field normal name '%s'"); + cmdSet("field normal type '%s'"); + cmdSet("field normal result '%s'"); + + cmdSet("format normal '' *-*-*"); + + cmdSet("format normal '{pre}{action} class {name}{resolve}{post}' class"); + cmdSet("format normal '{pre}{action} interface {name}{resolve}{post}' interface"); + cmdSet("format normal '{pre}{action} enum {name}{resolve}{post}' enum"); + cmdSet("format normal '{pre}{action} annotation interface {name}{resolve}{post}' annotation"); + + cmdSet("format normal '{pre}{action} method {name}({type}){resolve}{post}' method"); + + cmdSet("format normal '{pre}{action} variable {name} of type {type}{resolve}{post}' vardecl"); + cmdSet("format normal '{pre}{action} variable {name} of type {type} with initial value {result}{resolve}{post}' varinit"); + cmdSet("format normal '{pre}{action} variable {name}{resolve}{post}' vardeclrecoverable"); + cmdSet("format normal '{pre}{action} variable {name}, reset to null{post}' varreset-*-update"); + + cmdSet("format normal '{pre}Expression value is: {result}{post}" + + "{pre} assigned to temporary variable {name} of type {type}{post}' expression"); + cmdSet("format normal '{pre}Variable {name} of type {type} has value {result}{post}' varvalue"); + cmdSet("format normal '{pre}Variable {name} has been assigned the value {result}{post}' assignment"); + + cmdSet("feedback normal"); + + // Initialize off feedback mode + cmdSet("newmode off quiet"); + cmdSet("prompt off '-> ' '>> '"); + cmdSet("field off pre '| '"); + cmdSet("field off post '%n'"); + cmdSet("field off errorpre '| '"); + cmdSet("field off errorpost '%n'"); + cmdSet("format off '' *-*-*"); } private IOContext input = null; @@ -150,7 +222,6 @@ private boolean debug = false; private boolean displayPrompt = true; public boolean testPrompt = false; - private Feedback feedback = Feedback.Default; private String cmdlineClasspath = null; private String cmdlineStartup = null; private String[] editor = null; @@ -185,6 +256,15 @@ Map mapSnippet; + /** + * Is the input/output currently interactive + * + * @return true if console + */ + boolean interactive() { + return input != null && input.interactiveOutput(); + } + void debug(String format, Object... args) { if (debug) { cmderr.printf(format + "\n", args); @@ -192,38 +272,98 @@ } /** - * For more verbose feedback modes + * Base output for command output -- no pre- or post-fix + * + * @param printf format + * @param printf args + */ + void rawout(String format, Object... args) { + cmdout.printf(format, args); + } + + /** + * Must show command output + * + * @param format printf format + * @param args printf args + */ + void hard(String format, Object... args) { + rawout(feedback.getPre() + format + feedback.getPost(), args); + } + + /** + * Error command output + * + * @param format printf format + * @param args printf args + */ + void error(String format, Object... args) { + rawout(feedback.getErrorPre() + format + feedback.getErrorPost(), args); + } + + /** + * Optional output + * * @param format printf format * @param args printf args */ void fluff(String format, Object... args) { - if (feedback() != Feedback.Off && feedback() != Feedback.Concise) { + if (feedback.shouldDisplayCommandFluff() && interactive()) { hard(format, args); } } /** - * For concise feedback mode only + * Optional output -- with embedded per- and post-fix + * * @param format printf format * @param args printf args */ - void concise(String format, Object... args) { - if (feedback() == Feedback.Concise) { - hard(format, args); + void fluffRaw(String format, Object... args) { + if (feedback.shouldDisplayCommandFluff() && interactive()) { + rawout(format, args); + } + } + + void hardPairs(Stream stream, Function a, Function b) { + Map a2b = stream.collect(toMap(a, b, + (m1, m2) -> m1, + () -> new LinkedHashMap<>())); + int aLen = 0; + for (String av : a2b.keySet()) { + aLen = Math.max(aLen, av.length()); + } + String format = " %-" + aLen + "s -- %s"; + String indentedNewLine = LINE_SEP + feedback.getPre() + + String.format(" %-" + (aLen + 4) + "s", ""); + for (Entry e : a2b.entrySet()) { + hard(format, e.getKey(), e.getValue().replaceAll("\n", indentedNewLine)); } } /** - * For all feedback modes -- must show - * @param format printf format - * @param args printf args + * User custom feedback mode only + * + * @param fcase Event to report + * @param update Is this an update (rather than primary) + * @param fa Action + * @param fr Resolution status + * @param name Name string + * @param type Type string or null + * @param result Result value or null + * @param unresolved The unresolved symbols */ - void hard(String format, Object... args) { - cmdout.printf("| " + format + "\n", args); + void custom(FormatCase fcase, boolean update, FormatAction fa, FormatResolve fr, + String name, String type, String unresolved, String result) { + String format = feedback.getFormat(fcase, + (update ? FormatWhen.UPDATE : FormatWhen.PRIMARY), fa, fr, + name != null, type != null, result != null); + fluffRaw(format, unresolved, name, type, result); } /** * Trim whitespace off end of string + * * @param s * @return */ @@ -276,8 +416,8 @@ } if (regenerateOnDeath) { - fluff("Welcome to JShell -- Version %s", version()); - fluff("Type /help for help"); + hard("Welcome to JShell -- Version %s", version()); + hard("Type /help for help"); } try { @@ -369,14 +509,14 @@ } private void printUsage() { - cmdout.printf("Usage: jshell \n"); - cmdout.printf("where possible options include:\n"); - cmdout.printf(" -classpath Specify where to find user class files\n"); - cmdout.printf(" -cp Specify where to find user class files\n"); - cmdout.printf(" -startup One run replacement for the start-up definitions\n"); - cmdout.printf(" -nostartup Do not run the start-up definitions\n"); - cmdout.printf(" -help Print a synopsis of standard options\n"); - cmdout.printf(" -version Version information\n"); + rawout("Usage: jshell \n"); + rawout("where possible options include:\n"); + rawout(" -classpath Specify where to find user class files\n"); + rawout(" -cp Specify where to find user class files\n"); + rawout(" -startup One run replacement for the start-up definitions\n"); + rawout(" -nostartup Do not run the start-up definitions\n"); + rawout(" -help Print a synopsis of standard options\n"); + rawout(" -version Version information\n"); } private void resetState() { @@ -460,10 +600,8 @@ ? "\u0005" //ENQ : "\u0006" //ACK : incomplete.isEmpty() - ? feedback() == Feedback.Concise - ? "-> " - : "\n-> " - : ">> " + ? feedback.getPrompt(currentNameSpace.tidNext()) + : feedback.getContinuationPrompt(currentNameSpace.tidNext()) ; } else { prompt = ""; @@ -541,7 +679,7 @@ Command[] candidates = findCommand(cmd, c -> c.kind.isRealCommand); if (candidates.length == 0) { if (!rerunHistoryEntryById(cmd.substring(1))) { - hard("No such command or snippet id: %s", cmd); + error("No such command or snippet id: %s", cmd); fluff("Type /help for help."); } } else if (candidates.length == 1) { @@ -552,7 +690,7 @@ addToReplayHistory((command.command + " " + arg).trim()); } } else { - hard("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", "))); + error("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", "))); fluff("Type /help for help."); } } @@ -635,45 +773,6 @@ } } - class ArgTokenizer extends StreamTokenizer { - - ArgTokenizer(String arg) { - super(new StringReader(arg)); - resetSyntax(); - wordChars(0x00, 0xFF); - quoteChar('"'); - quoteChar('\''); - - whitespaceChars(0x09, 0x0D); - whitespaceChars(0x1C, 0x20); - whitespaceChars(0x85, 0x85); - whitespaceChars(0xA0, 0xA0); - whitespaceChars(0x1680, 0x1680); - whitespaceChars(0x180E, 0x180E); - whitespaceChars(0x2000, 0x200A); - whitespaceChars(0x202F, 0x202F); - whitespaceChars(0x205F, 0x205F); - whitespaceChars(0x3000, 0x3000); - } - - String next() { - try { - nextToken(); - } catch (Throwable t) { - return null; - } - return sval; - } - - String val() { - return sval; - } - - boolean isQuoted() { - return ttype == '\'' || ttype == '"'; - } - } - static final class FixedCompletionProvider implements CompletionProvider { private final String[] alternatives; @@ -801,16 +900,9 @@ " -- List the snippet with the specified snippet id\n", arg -> cmdList(arg), editKeywordCompletion())); - registerCommand(new Command("/seteditor", "", "set the external editor command to use", - "Specify the command to launch for the /edit command.\n" + - "The command is an operating system dependent string.\n" + - "The command may include space-separated arguments (such as flags).\n" + - "When /edit is used, temporary file to edit will be appended as the last argument.\n", - arg -> cmdSetEditor(arg), - EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/edit", "", "edit a source entry referenced by name or id", "Edit a snippet or snippets of source in an external editor.\n" + - "The editor to use is set with /seteditor.\n" + + "The editor to use is set with /set editor.\n" + "If no editor has been set, a simple editor will be launched.\n\n" + "/edit \n" + " -- Edit the snippet or snippets with the specified name (preference for active snippets)\n" + @@ -875,7 +967,7 @@ " * Start-up code is re-executed.\n" + " * The execution state is restarted.\n" + " * The classpath is cleared.\n" + - "Tool settings are maintained: /feedback, /prompt, and /seteditor\n" + + "Tool settings are maintained, as set with: /set ...\n" + "Save any work before using this command\n", arg -> cmdReset(), EMPTY_COMPLETION_PROVIDER)); @@ -895,25 +987,6 @@ " -- With the 'quiet' argument the replay is not shown. Errors will display.\n", arg -> cmdReload(arg), reloadCompletion())); - registerCommand(new Command("/feedback", "", "feedback information: off, concise, normal, verbose, default, or ?", - "Set the level of feedback describing the effect of commands and snippets.\n\n" + - "/feedback off\n" + - " -- Give no feedback\n" + - "/feedback concise\n" + - " -- Brief and generally symbolic feedback\n" + - "/feedback normal\n" + - " -- Give a natural language description of the actions\n" + - "/feedback verbose\n" + - " -- Like normal but with side-effects described\n" + - "/feedback default\n" + - " -- Same as normal for user input, off for input from a file\n", - arg -> cmdFeedback(arg), - new FixedCompletionProvider("off", "concise", "normal", "verbose", "default", "?"))); - registerCommand(new Command("/prompt", null, "toggle display of a prompt", - "Toggle between displaying an input prompt and not displaying a prompt.\n" + - "Particularly useful when pasting large amounts of text.\n", - arg -> cmdPrompt(), - EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/classpath", "", "add a path to the classpath", "Append a additional path to the classpath.\n", arg -> cmdClasspath(arg), @@ -923,10 +996,6 @@ "Display the history of snippet and command input since this jshell was launched.\n", arg -> cmdHistory(), EMPTY_COMPLETION_PROVIDER)); - registerCommand(new Command("/setstart", "", "read file and set as the new start-up definitions", - "The contents of the specified file become the default start-up snippets and commands.\n", - arg -> cmdSetStart(arg), - FILE_COMPLETION_PROVIDER)); registerCommand(new Command("/debug", null, "toggle debugging of the jshell", "Display debugging information for the jshelll implementation.\n" + "0: Debugging off\n" + @@ -951,6 +1020,37 @@ " -- Display information about the specified help subject. Example: /help intro\n", arg -> cmdHelp(arg), EMPTY_COMPLETION_PROVIDER)); + registerCommand(new Command("/set", "editor|start|feedback|newmode|prompt|format|field ...", "set jshell configuration information", + "Set jshell configuration information, including:\n" + + "the external editor to use, the start-up definitions to use, a new feedback mode,\n" + + "the command prompt, the feedback mode to use, or the format of output.\n" + + "\n" + + "/set editor ...\n" + + " -- Specify the command to launch for the /edit command.\n" + + " The is an operating system dependent string.\n" + + "\n" + + "/set start \n" + + " -- The contents of the specified become the default start-up snippets and commands.\n" + + "\n" + + "/set feedback \n" + + " -- Set the feedback mode describing displayed feedback for entered snippets and commands.\n" + + "\n" + + "/set newmode [command|quiet []]\n" + + " -- Create a user-defined feedback mode, optionally copying from an existing mode.\n" + + "\n" + + "/set prompt \"\" \"\"\n" + + " -- Set the displayed prompts for a given feedback mode.\n" + + "\n" + + "/set format \"\" ...\n" + + " -- Configure a feedback mode by setting the format to use in a specified set of cases.\n" + + "\n" + + "/set field name|type|result|when|action|resolve|pre|post|errorpre|errorpost \"\" ...\n" + + " -- Set the format of a field within the of a \"/set format\" command\n" + + "\n" + + "To get more information about one of these forms, use /help with the form specified.\n" + + "For example: /help /set format\n", + arg -> cmdSet(arg), + new FixedCompletionProvider("format", "field", "feedback", "prompt", "newmode", "start", "editor"))); registerCommand(new Command("/?", "", "get information about jshell", "Display information about jshell (abbreviation for /help).\n" + "/?\n" + @@ -1051,21 +1151,138 @@ // --- Command implementations --- - boolean cmdSetEditor(String arg) { - if (arg.isEmpty()) { - hard("/seteditor requires a path argument"); + private static final String[] setSub = new String[]{ + "format", "field", "feedback", "newmode", "prompt", "editor", "start"}; + + // The /set command. Currently /set format, /set field and /set feedback. + // Other commands will fold here, see: 8148317 + final boolean cmdSet(String arg) { + ArgTokenizer at = new ArgTokenizer(arg.trim()); + String which = setSubCommand(at); + if (which == null) { return false; - } else { - List ed = new ArrayList<>(); - ArgTokenizer at = new ArgTokenizer(arg); - String n; - while ((n = at.next()) != null) ed.add(n); - editor = ed.toArray(new String[ed.size()]); - fluff("Editor set to: %s", arg); - return true; + } + switch (which) { + case "format": + return feedback.setFormat(this, at); + case "field": + return feedback.setField(this, at); + case "feedback": + return feedback.setFeedback(this, at); + case "newmode": + return feedback.setNewMode(this, at); + case "prompt": + return feedback.setPrompt(this, at); + case "editor": { + String prog = at.next(); + if (prog == null) { + hard("The '/set editor' command requires a path argument"); + return false; + } else { + List ed = new ArrayList<>(); + ed.add(prog); + String n; + while ((n = at.next()) != null) { + ed.add(n); + } + editor = ed.toArray(new String[ed.size()]); + fluff("Editor set to: %s", arg); + return true; + } + } + case "start": { + String filename = at.next(); + if (filename == null) { + hard("The '/set start' command requires a filename argument."); + } else { + try { + byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); + String init = new String(encoded); + PREFS.put(STARTUP_KEY, init); + } catch (AccessDeniedException e) { + hard("File '%s' for /set start is not accessible.", filename); + return false; + } catch (NoSuchFileException e) { + hard("File '%s' for /set start is not found.", filename); + return false; + } catch (Exception e) { + hard("Exception while reading start set file: %s", e); + return false; + } + } + return true; + } + default: + hard("Error: Invalid /set argument: %s", which); + return false; } } + boolean printSetHelp(ArgTokenizer at) { + String which = setSubCommand(at); + if (which == null) { + return false; + } + switch (which) { + case "format": + feedback.printFormatHelp(this); + return true; + case "field": + feedback.printFieldHelp(this); + return true; + case "feedback": + feedback.printFeedbackHelp(this); + return true; + case "newmode": + feedback.printNewModeHelp(this); + return true; + case "prompt": + feedback.printPromptHelp(this); + return true; + case "editor": + hard("Specify the command to launch for the /edit command."); + hard(""); + hard("/set editor ..."); + hard(""); + hard("The is an operating system dependent string."); + hard("The may include space-separated arguments (such as flags) -- ...."); + hard("When /edit is used, the temporary file to edit will be appended as the last argument."); + return true; + case "start": + hard("Set the start-up configuration -- a sequence of snippets and commands read at start-up."); + hard(""); + hard("/set start "); + hard(""); + hard("The contents of the specified become the default start-up snippets and commands --"); + hard("which are run when the jshell tool is started or reset."); + return true; + default: + hard("Error: Invalid /set argument: %s", which); + return false; + } + } + + String setSubCommand(ArgTokenizer at) { + String[] matches = at.next(setSub); + if (matches == null) { + error("The /set command requires arguments. See: /help /set"); + return null; + } else if (matches.length == 0) { + error("Not a valid argument to /set: %s", at.val()); + fluff("/set is followed by one of: %s", Arrays.stream(setSub) + .collect(Collectors.joining(", ")) + ); + return null; + } else if (matches.length > 1) { + error("Ambiguous argument to /set: %s", at.val()); + fluff("Use one of: %s", Arrays.stream(matches) + .collect(Collectors.joining(", ")) + ); + return null; + } + return matches[0]; + } + boolean cmdClasspath(String arg) { if (arg.isEmpty()) { hard("/classpath requires a path argument"); @@ -1137,91 +1354,50 @@ return true; } - private boolean cmdFeedback(String arg) { - switch (arg) { - case "": - case "d": - case "default": - feedback = Feedback.Default; - break; - case "o": - case "off": - feedback = Feedback.Off; - break; - case "c": - case "concise": - feedback = Feedback.Concise; - break; - case "n": - case "normal": - feedback = Feedback.Normal; - break; - case "v": - case "verbose": - feedback = Feedback.Verbose; - break; - default: - hard("Follow /feedback with of the following:"); - hard(" off (errors and critical output only)"); - hard(" concise"); - hard(" normal"); - hard(" verbose"); - hard(" default"); - hard("You may also use just the first letter, for example: /f c"); - hard("In interactive mode 'default' is the same as 'normal', from a file it is the same as 'off'"); - return false; + boolean cmdHelp(String arg) { + ArgTokenizer at = new ArgTokenizer(arg); + String subject = at.next(); + if (subject != null) { + Command[] matches = commands.values().stream() + .filter(c -> c.command.startsWith(subject)) + .toArray(size -> new Command[size]); + at.mark(); + String sub = at.next(); + if (sub != null && matches.length == 1 && matches[0].command.equals("/set")) { + at.rewind(); + return printSetHelp(at); + } + if (matches.length > 0) { + for (Command c : matches) { + hard(""); + hard("%s", c.command); + hard(""); + hard("%s", c.help.replaceAll("\n", LINE_SEP + feedback.getPre())); + } + return true; + } else { + error("No commands or subjects start with the provided argument: %s\n\n", arg); + } } - fluff("Feedback mode: %s", feedback.name().toLowerCase()); - return true; - } - - boolean cmdHelp(String arg) { - if (!arg.isEmpty()) { - StringBuilder sb = new StringBuilder(); - commands.values().stream() - .filter(c -> c.command.startsWith(arg)) - .forEach(c -> { - sb.append("\n"); - sb.append(c.command); - sb.append("\n\n"); - sb.append(c.help); - sb.append("\n"); - }); - if (sb.length() > 0) { - cmdout.print(sb); - return true; - } - cmdout.printf("No commands or subjects start with the provided argument: %s\n\n", arg); - } - int synopsisLen = 0; - Map synopsis2Description = new LinkedHashMap<>(); - for (Command cmd : new LinkedHashSet<>(commands.values())) { - if (!cmd.kind.showInHelp) - continue; - StringBuilder synopsis = new StringBuilder(); - synopsis.append(cmd.command); - if (cmd.params != null) - synopsis.append(" ").append(cmd.params); - synopsis2Description.put(synopsis.toString(), cmd.description); - synopsisLen = Math.max(synopsisLen, synopsis.length()); - } - cmdout.println("Type a Java language expression, statement, or declaration."); - cmdout.println("Or type one of the following commands:\n"); - for (Entry e : synopsis2Description.entrySet()) { - cmdout.print(String.format("%-" + synopsisLen + "s", e.getKey())); - cmdout.print(" -- "); - String indentedNewLine = System.getProperty("line.separator") + - String.format("%-" + (synopsisLen + 4) + "s", ""); - cmdout.println(e.getValue().replace("\n", indentedNewLine)); - } - cmdout.println(); - cmdout.println("For more information type '/help' followed by the name of command or a subject."); - cmdout.println("For example '/help /list' or '/help intro'. Subjects:\n"); - commands.values().stream() - .filter(c -> c.kind == CommandKind.HELP_SUBJECT) - .forEach(c -> { - cmdout.printf("%-12s -- %s\n", c.command, c.description); - }); + hard("Type a Java language expression, statement, or declaration."); + hard("Or type one of the following commands:"); + hard(""); + hardPairs(commands.values().stream() + .filter(cmd -> cmd.kind.showInHelp), + cmd -> (cmd.params != null) + ? cmd.command + " " + cmd.params + : cmd.command, + cmd -> cmd.description + ); + hard(""); + hard("For more information type '/help' followed by the name of command or a subject."); + hard("For example '/help /list' or '/help intro'. Subjects:"); + hard(""); + hardPairs(commands.values().stream() + .filter(cmd -> cmd.kind == CommandKind.HELP_SUBJECT), + cmd -> cmd.command, + cmd -> cmd.description + ); return true; } @@ -1482,13 +1658,6 @@ return true; } - private boolean cmdPrompt() { - displayPrompt = !displayPrompt; - fluff("Prompt will %sdisplay. Use /prompt to toggle.", displayPrompt ? "" : "NOT "); - concise("Prompt: %s", displayPrompt ? "on" : "off"); - return true; - } - private boolean cmdReset() { live = false; fluff("Resetting state."); @@ -1577,28 +1746,6 @@ return true; } - private boolean cmdSetStart(String filename) { - if (filename.isEmpty()) { - hard("The /setstart command requires a filename argument."); - } else { - try { - byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); - String init = new String(encoded); - PREFS.put(STARTUP_KEY, init); - } catch (AccessDeniedException e) { - hard("File '%s' for /setstart is not accessible.", filename); - return false; - } catch (NoSuchFileException e) { - hard("File '%s' for /setstart is not found.", filename); - return false; - } catch (Exception e) { - hard("Exception while reading start set file: %s", e); - return false; - } - } - return true; - } - private boolean cmdVars() { for (VarSnippet vk : state.variables()) { String val = state.status(vk) == Status.VALID @@ -1831,14 +1978,10 @@ printDiagnostics(source, diagnostics, true); } else { // Update - SubKind subkind = sn.subKind(); - if (sn instanceof DeclarationSnippet - && (feedback() == Feedback.Verbose - || ste.status() == Status.OVERWRITTEN - || subkind == SubKind.VAR_DECLARATION_SUBKIND - || subkind == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND)) { - // Under the conditions, display update information - displayDeclarationAndValue(ste, true, null); + if (sn instanceof DeclarationSnippet) { + // display update information + displayDeclarationAndValue(ste, true, ste.value()); + List other = errorsOnly(diagnostics); if (other.size() > 0) { printDiagnostics(source, other, true); @@ -1851,118 +1994,117 @@ @SuppressWarnings("fallthrough") private void displayDeclarationAndValue(SnippetEvent ste, boolean update, String value) { Snippet key = ste.snippet(); - String declared; + FormatAction action; Status status = ste.status(); switch (status) { case VALID: case RECOVERABLE_DEFINED: case RECOVERABLE_NOT_DEFINED: if (ste.previousStatus().isActive) { - declared = ste.isSignatureChange() - ? "Replaced" - : "Modified"; + action = ste.isSignatureChange() + ? FormatAction.REPLACED + : FormatAction.MODIFIED; } else { - declared = "Added"; + action = FormatAction.ADDED; } break; case OVERWRITTEN: - declared = "Overwrote"; + action = FormatAction.OVERWROTE; break; case DROPPED: - declared = "Dropped"; + action = FormatAction.DROPPED; break; case REJECTED: - declared = "Rejected"; + action = FormatAction.REJECTED; break; case NONEXISTENT: default: // Should not occur - declared = ste.previousStatus().toString() + "=>" + status.toString(); + error("Unexpected status: " + ste.previousStatus().toString() + "=>" + status.toString()); + return; } - if (update) { - declared = " Update " + declared.toLowerCase(); - } - String however; + FormatResolve resolution; + String unresolved; if (key instanceof DeclarationSnippet && (status == Status.RECOVERABLE_DEFINED || status == Status.RECOVERABLE_NOT_DEFINED)) { - String cannotUntil = (status == Status.RECOVERABLE_NOT_DEFINED) - ? " cannot be referenced until" - : " cannot be invoked until"; - however = (update? " which" : ", however, it") + cannotUntil + unresolved((DeclarationSnippet) key); + resolution = (status == Status.RECOVERABLE_NOT_DEFINED) + ? FormatResolve.NOTDEFINED + : FormatResolve.DEFINED; + unresolved = unresolved((DeclarationSnippet) key); } else { - however = ""; + resolution = FormatResolve.OK; + unresolved = ""; } switch (key.subKind()) { case CLASS_SUBKIND: - fluff("%s class %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.CLASS, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case INTERFACE_SUBKIND: - fluff("%s interface %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.INTERFACE, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case ENUM_SUBKIND: - fluff("%s enum %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.ENUM, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case ANNOTATION_TYPE_SUBKIND: - fluff("%s annotation interface %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.ANNOTATION, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case METHOD_SUBKIND: - fluff("%s method %s(%s)%s", declared, ((MethodSnippet) key).name(), - ((MethodSnippet) key).parameterTypes(), however); + custom(FormatCase.METHOD, update, action, resolution, + ((MethodSnippet) key).name(), ((MethodSnippet) key).parameterTypes(), unresolved, null); break; case VAR_DECLARATION_SUBKIND: - if (!update) { - VarSnippet vk = (VarSnippet) key; - if (status == Status.RECOVERABLE_NOT_DEFINED) { - fluff("%s variable %s%s", declared, vk.name(), however); - } else { - fluff("%s variable %s of type %s%s", declared, vk.name(), vk.typeName(), however); - } - break; - } - // Fall through case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: { VarSnippet vk = (VarSnippet) key; if (status == Status.RECOVERABLE_NOT_DEFINED) { - if (!update) { - fluff("%s variable %s%s", declared, vk.name(), however); - break; - } - } else if (update) { - if (ste.isSignatureChange()) { - hard("%s variable %s, reset to null", declared, vk.name()); - } + custom(FormatCase.VARDECLRECOVERABLE, update, action, resolution, + vk.name(), null, unresolved, null); + } else if (update && ste.isSignatureChange()) { + custom(FormatCase.VARRESET, update, action, resolution, + vk.name(), null, unresolved, value); + } else if (key.subKind() == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND) { + custom(FormatCase.VARINIT, update, action, resolution, + vk.name(), vk.typeName(), unresolved, value); } else { - fluff("%s variable %s of type %s with initial value %s", - declared, vk.name(), vk.typeName(), value); - concise("%s : %s", vk.name(), value); + custom(FormatCase.VARDECL, update, action, resolution, + vk.name(), vk.typeName(), unresolved, value); } break; } case TEMP_VAR_EXPRESSION_SUBKIND: { VarSnippet vk = (VarSnippet) key; - if (update) { - hard("%s temporary variable %s, reset to null", declared, vk.name()); - } else { - fluff("Expression value is: %s", (value)); - fluff(" assigned to temporary variable %s of type %s", vk.name(), vk.typeName()); - concise("%s : %s", vk.name(), value); - } + custom(FormatCase.EXPRESSION, update, action, resolution, + vk.name(), vk.typeName(), null, value); break; } case OTHER_EXPRESSION_SUBKIND: - fluff("Expression value is: %s", (value)); + error("Unexpected expression form -- value is: %s", (value)); break; case VAR_VALUE_SUBKIND: { ExpressionSnippet ek = (ExpressionSnippet) key; - fluff("Variable %s of type %s has value %s", ek.name(), ek.typeName(), (value)); - concise("%s : %s", ek.name(), value); + custom(FormatCase.VARVALUE, update, action, resolution, + ek.name(), ek.typeName(), null, value); break; } case ASSIGNMENT_SUBKIND: { ExpressionSnippet ek = (ExpressionSnippet) key; - fluff("Variable %s has been assigned the value %s", ek.name(), (value)); - concise("%s : %s", ek.name(), value); + custom(FormatCase.ASSIGNMENT, update, action, resolution, + ek.name(), ek.typeName(), null, value); break; } + case SINGLE_TYPE_IMPORT_SUBKIND: + case TYPE_IMPORT_ON_DEMAND_SUBKIND: + case SINGLE_STATIC_IMPORT_SUBKIND: + case STATIC_IMPORT_ON_DEMAND_SUBKIND: + custom(FormatCase.IMPORT, update, action, resolution, + ((ImportSnippet) key).name(), null, null, null); + break; + case STATEMENT_SUBKIND: + custom(FormatCase.STATEMENT, update, action, resolution, + null, null, null, null); + break; } } //where @@ -1998,7 +2140,7 @@ } //where void printUnresolved(UnresolvedReferenceException ex) { - MethodSnippet corralled = ex.getMethodSnippet(); + DeclarationSnippet corralled = ex.getSnippet(); List otherErrors = errorsOnly(state.diagnostics(corralled)); StringBuilder sb = new StringBuilder(); if (otherErrors.size() > 0) { @@ -2014,7 +2156,10 @@ sb.append("."); } - hard("Attempted to call %s which cannot be invoked until%s", corralled.name(), + String format = corralled.kind() == METHOD + ? "Attempted to call %s which cannot be invoked until%s" + : "Attempted to use %s which cannot be accessed until%s"; + hard(format, corralled.name(), unresolved(corralled), sb.toString()); if (otherErrors.size() > 0) { printDiagnostics(corralled.source(), otherErrors, true); @@ -2048,34 +2193,9 @@ sb.append(", "); } } - switch (unr.size()) { - case 0: - break; - case 1: - sb.append(" is declared"); - break; - default: - sb.append(" are declared"); - break; - } return sb.toString(); } - enum Feedback { - Default, - Off, - Concise, - Normal, - Verbose - } - - Feedback feedback() { - if (feedback == Feedback.Default) { - return input == null || input.interactiveOutput() ? Feedback.Normal : Feedback.Off; - } - return feedback; - } - /** The current version number as a string. */ static String version() { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,7 +231,7 @@ // Declarations and type parameters (thus expressions) EXTENDS(TokenKind.EXTENDS, XEXPR|XDECL), // extends - COMMA(TokenKind.COMMA, XEXPR|XDECL|XSTART), // , + COMMA(TokenKind.COMMA, XEXPR|XDECL), // , AMP(TokenKind.AMP, XEXPR|XDECL), // & GT(TokenKind.GT, XEXPR|XDECL), // > LT(TokenKind.LT, XEXPR|XDECL1), // < diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.jshell; + +import java.util.List; +import com.sun.source.tree.ArrayTypeTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import jdk.jshell.Wrap.Range; +import static java.util.stream.Collectors.toList; + +/** + * Produce a corralled version of the Wrap for a snippet. + * + * @author Robert Field + */ +class Corraller { + + private final int index; + private final String compileSource; + private final TreeDissector dis; + + Corraller(int index, String compileSource, TreeDissector dis) { + this.index = index; + this.compileSource = compileSource; + this.dis = dis; + } + + Wrap corralTree(Tree tree, String enclosingType, int indent) { + switch (tree.getKind()) { + case VARIABLE: + return corralVariable((VariableTree) tree, indent); + case CLASS: + case ENUM: + case ANNOTATION_TYPE: + case INTERFACE: + return corralType((ClassTree) tree, indent); + case METHOD: + return corralMethod((MethodTree) tree, enclosingType, indent); + default: + return null; + } + } + + Wrap corralMethod(MethodTree mt) { + return corralMethod(mt, null, 1); + } + + Wrap corralMethod(MethodTree mt, String enclosingType, int indent) { + Range modRange = dis.treeToRange(mt.getModifiers()); + Range tpRange = dis.treeListToRange(mt.getTypeParameters()); + Range typeRange = dis.treeToRange(mt.getReturnType()); + String name = mt.getName().toString(); + if ("".equals(name)) { + name = enclosingType; + } + Range paramRange = dis.treeListToRange(mt.getParameters()); + Range throwsRange = dis.treeListToRange(mt.getThrows()); + return Wrap.corralledMethod(compileSource, + modRange, tpRange, typeRange, name, paramRange, throwsRange, index, indent); + } + + Wrap corralVariable(VariableTree vt, int indent) { + String name = vt.getName().toString(); + Range modRange = dis.treeToRange(vt.getModifiers()); + Tree baseType = vt.getType(); + StringBuilder sbBrackets = new StringBuilder(); + while (baseType instanceof ArrayTypeTree) { + //TODO handle annotations too + baseType = ((ArrayTypeTree) baseType).getType(); + sbBrackets.append("[]"); + } + Range rtype = dis.treeToRange(baseType); + Range runit = dis.treeToRange(vt); + runit = new Range(runit.begin, runit.end - 1); + ExpressionTree it = vt.getInitializer(); + int nameMax; + if (it != null) { + Range rinit = dis.treeToRange(it); + nameMax = rinit.begin - 1; + } else { + nameMax = runit.end - 1; + } + int nameStart = compileSource.lastIndexOf(name, nameMax); + if (nameStart < 0) { + throw new AssertionError("Name '" + name + "' not found"); + } + int nameEnd = nameStart + name.length(); + Range rname = new Range(nameStart, nameEnd); + return Wrap.corralledVar(compileSource, modRange, rtype, sbBrackets.toString(), rname, indent); + } + + Wrap corralType(ClassTree ct, int indent) { + boolean isClass; + switch (ct.getKind()) { + case CLASS: + isClass = true; + break; + case INTERFACE: + isClass = false; + break; + default: + return null; + } + Range modRange = dis.treeToRange(ct.getModifiers()); + String name = ct.getSimpleName().toString(); + Range tpRange = dis.treeListToRange(ct.getTypeParameters()); + Range extendsRange = dis.treeToRange(ct.getExtendsClause()); + List implementsRanges = ct.getImplementsClause().stream() + .map(ic -> dis.treeToRange(ic)) + .collect(toList()); + List members = ct.getMembers().stream() + .map(t -> corralTree(t, name, indent + 1)) + .filter(w -> w != null) + .collect(toList()); + boolean hasConstructor = ct.getMembers().stream() + .anyMatch(t -> t.getKind() == Tree.Kind.METHOD && ((MethodTree) t).getName().toString().equals("")); + Wrap wrap = Wrap.corralledType(compileSource, modRange, ct.getKind(), name, tpRange, + extendsRange, implementsRanges, members, isClass && !hasConstructor, index, indent); + return wrap; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Mon Mar 21 11:21:08 2016 +0100 @@ -53,6 +53,7 @@ import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; +import jdk.jshell.Key.TypeDeclKey; import jdk.jshell.Snippet.SubKind; import jdk.jshell.TaskFactory.AnalyzeTask; import jdk.jshell.TaskFactory.BaseTask; @@ -300,7 +301,8 @@ ClassTree klassTree = (ClassTree) unitTree; String name = klassTree.getSimpleName().toString(); Wrap guts = Wrap.classMemberWrap(compileSource); - Wrap corralled = null; //TODO + TypeDeclKey key = state.keyMap.keyForClass(name); + Wrap corralled = new Corraller(key.index(), compileSource, dis).corralType(klassTree, 1); Snippet snip = new TypeDeclSnippet(state.keyMap.keyForClass(name), userSource, guts, name, snippetKind, corralled, tds.declareReferences(), tds.bodyReferences()); @@ -362,12 +364,8 @@ String unitName = mt.getName().toString(); Wrap guts = Wrap.classMemberWrap(compileSource); - Range modRange = dis.treeToRange(mt.getModifiers()); - Range tpRange = dis.treeListToRange(mt.getTypeParameters()); Range typeRange = dis.treeToRange(mt.getReturnType()); String name = mt.getName().toString(); - Range paramRange = dis.treeListToRange(mt.getParameters()); - Range throwsRange = dis.treeListToRange(mt.getThrows()); String parameterTypes = mt.getParameters() @@ -378,8 +376,7 @@ MethodKey key = state.keyMap.keyForMethod(name, parameterTypes); // rewrap with correct Key index - Wrap corralled = Wrap.corralledMethod(compileSource, - modRange, tpRange, typeRange, name, paramRange, throwsRange, key.index()); + Wrap corralled = new Corraller(key.index(), compileSource, dis).corralMethod(mt); Snippet snip = new MethodSnippet(key, userSource, guts, unitName, signature, corralled, tds.declareReferences(), tds.bodyReferences()); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Mon Mar 21 11:21:08 2016 +0100 @@ -225,7 +225,7 @@ int id = in.readInt(); StackTraceElement[] elems = readStackTrace(); Snippet si = maps.getSnippet(id); - throw new UnresolvedReferenceException((MethodSnippet) si, elems); + throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); } case RESULT_KILLED: { proc.out.println("Killed."); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Mon Mar 21 11:21:08 2016 +0100 @@ -61,6 +61,7 @@ import javax.tools.FileObject; import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; import jdk.jshell.ClassTracker.ClassInfo; +import jdk.Version; /** * The primary interface to the compiler API. Parsing, analysis, and @@ -73,6 +74,7 @@ private final MemoryFileManager fileManager; private final JShell state; private String classpath = System.getProperty("java.class.path"); + private final static Version INITIAL_SUPPORTED_VER = Version.parse("9"); TaskFactory(JShell state) { this.state = state; @@ -80,7 +82,8 @@ if (compiler == null) { throw new UnsupportedOperationException("Compiler not available, must be run with full JDK 9."); } - if (!System.getProperty("java.specification.version").equals("9")) { + Version current = Version.parse(System.getProperty("java.specification.version")); + if (INITIAL_SUPPORTED_VER.compareToIgnoreOpt(current) > 0) { throw new UnsupportedOperationException("Wrong compiler, must be run with full JDK 9."); } this.fileManager = new MemoryFileManager( diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,33 +28,33 @@ /** * Exception reported on attempting to execute a * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * method. + * snippet. *

    * The stack can be queried by methods on Exception. * Note that in stack trace frames representing JShell Snippets, * StackTraceElement.getFileName() will return "#" followed by * the Snippet id and for snippets without a method name (for example an - * expression) StackTraceElement.getMethodName() will be the + * expression) StackTraceElement.getName() will be the * empty string. */ @SuppressWarnings("serial") // serialVersionUID intentionally omitted public class UnresolvedReferenceException extends Exception { - final MethodSnippet methodSnippet; + final DeclarationSnippet snippet; - UnresolvedReferenceException(MethodSnippet methodSnippet, StackTraceElement[] stackElements) { - super("Attempt to invoke method with unresolved references"); - this.methodSnippet = methodSnippet; + UnresolvedReferenceException(DeclarationSnippet snippet, StackTraceElement[] stackElements) { + super("Attempt to use definition snippet with unresolved references"); + this.snippet = snippet; this.setStackTrace(stackElements); } /** - * Return the method Snippet which has the unresolved reference(s). - * @return the MethodSnippet of the + * Return the Snippet which has the unresolved reference(s). + * @return the Snippet of the * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * method. + * definition snippet. */ - public MethodSnippet getMethodSnippet() { - return methodSnippet; + public DeclarationSnippet getSnippet() { + return snippet; } } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import com.sun.source.tree.Tree; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; /** @@ -58,9 +59,18 @@ return methodWrap("", source, ""); } - public static Wrap corralledMethod(String source, Range modRange, Range tpRange, Range typeRange, String name, Range paramRange, Range throwsRange, int id) { + private static String indent(int n) { + return " ".substring(0, n * 4); + } + + private static String nlindent(int n) { + return "\n" + indent(n); + } + + public static Wrap corralledMethod(String source, Range modRange, Range tpRange, + Range typeRange, String name, Range paramRange, Range throwsRange, int id, int indent) { List l = new ArrayList<>(); - l.add(" public static\n "); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); if (!modRange.isEmpty()) { l.add(new RangeWrap(source, modRange)); l.add(" "); @@ -70,17 +80,81 @@ l.add(new RangeWrap(source, tpRange)); l.add("> "); } - l.add(new RangeWrap(source, typeRange)); - l.add(" " + name + "(\n "); - if (paramRange != null) { + if (!typeRange.isEmpty()) { + l.add(new RangeWrap(source, typeRange)); + l.add(" "); + } + l.add(name + "("); + if (paramRange != null && !paramRange.isEmpty()) { + l.add(nlindent(indent + 1)); l.add(new RangeWrap(source, paramRange)); } - l.add(") "); + l.add(")"); if (throwsRange != null) { - l.add("throws "); + l.add(" throws "); l.add(new RangeWrap(source, throwsRange)); } - l.add(" {\n throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");\n}\n"); + l.add(" {" + + nlindent(indent+1) + + "throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");" + + nlindent(indent) + + "}\n"); + return new CompoundWrap(l.toArray()); + } + + public static Wrap corralledType(String source, Range modRange, Tree.Kind kind, String name, Range tpRange, + Range extendsRange, List implementsRanges, List members, + boolean defaultConstructor, int id, int indent) { + boolean isInterface = kind == Tree.Kind.INTERFACE; + List l = new ArrayList<>(); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); + if (!modRange.isEmpty()) { + l.add(new RangeWrap(source, modRange)); + l.add(" "); + } + l.add((isInterface ? "interface " : "class ") + name); + if (tpRange != null) { + l.add("<"); + l.add(new RangeWrap(source, tpRange)); + l.add("> "); + } + if (extendsRange != null && !extendsRange.isEmpty()) { + l.add(" extends "); + l.add(new RangeWrap(source, extendsRange)); + } + for (int i = 0; i < implementsRanges.size(); ++i) { + Range ir = implementsRanges.get(i); + l.add(i == 0 ? " implements " : ", "); + l.add(new RangeWrap(source, ir)); + } + if (defaultConstructor) { + l.add(" {" + + nlindent(indent+1) + + ((indent == 1)? "public " : "") + name + "() {" + + nlindent(indent+2) + + "throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");" + + nlindent(indent+1) + + "}\n"); + } else { + l.add(" {\n"); + } + l.addAll(members); + l.add(indent(indent) + "}\n"); + return new CompoundWrap(l.toArray()); + } + + public static Wrap corralledVar(String source, Range modRange, Range typeRange, String brackets, Range nameRange, int indent) { + RangeWrap wname = new RangeWrap(source, nameRange); + List l = new ArrayList<>(); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); + if (!modRange.isEmpty()) { + l.add(new RangeWrap(source, modRange)); + l.add(" "); + } + l.add(new RangeWrap(source, typeRange)); + l.add(" "); + l.add(wname); + l.add(semi(wname)); return new CompoundWrap(l.toArray()); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/ClassesTest.java --- a/langtools/test/jdk/jshell/ClassesTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/ClassesTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -43,12 +43,13 @@ import jdk.jshell.Diag; import static jdk.jshell.Snippet.Status.VALID; import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED; +import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED; import static jdk.jshell.Snippet.Status.DROPPED; import static jdk.jshell.Snippet.Status.REJECTED; +import static jdk.jshell.Snippet.Status.OVERWRITTEN; import static jdk.jshell.Snippet.SubKind.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; -import static jdk.jshell.Snippet.Status.OVERWRITTEN; @Test public class ClassesTest extends KullaTesting { @@ -82,10 +83,10 @@ TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", - ste(c1, REJECTED, RECOVERABLE_NOT_DEFINED, false, null))); - assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0); + ste(c1, REJECTED, RECOVERABLE_DEFINED, true, null))); + assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); assertDrop(c2, - ste(c2, RECOVERABLE_NOT_DEFINED, DROPPED, false, null)); + ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); } public void classDeclaration() { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/CommandCompletionTest.java --- a/langtools/test/jdk/jshell/CommandCompletionTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/CommandCompletionTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,13 +50,9 @@ public class CommandCompletionTest extends ReplToolTesting { public void testCommand() { - assertCompletion("/f|", false, "/feedback "); assertCompletion("/deb|", false); - assertCompletion("/feedback v|", false, "verbose"); assertCompletion("/c|", false, "/classes ", "/classpath "); assertCompletion("/h|", false, "/help ", "/history "); - assertCompletion("/feedback |", false, - "?", "concise", "default", "normal", "off", "verbose"); } public void testList() { @@ -108,7 +104,7 @@ public void testSave() throws IOException { Compiler compiler = new Compiler(); - assertCompletion("/s|", false, "/save ", "/seteditor ", "/setstart "); + assertCompletion("/s|", false, "/save ", "/set "); List p1 = listFiles(Paths.get("")); Collections.addAll(p1, "all ", "history ", "start "); FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString())); diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/CompletenessTest.java --- a/langtools/test/jdk/jshell/CompletenessTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/CompletenessTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 8149524 * @summary Test SourceCodeAnalysis * @build KullaTesting TestingInputStream * @run testng CompletenessTest @@ -60,6 +61,7 @@ "try { } finally { }", "try (java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName)) { }", "foo: while (true) { printf(\"Innn\"); break foo; }", + "class Case, E2 extends Enum, E3 extends Enum> {}", ";", }; diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/DropTest.java --- a/langtools/test/jdk/jshell/DropTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/DropTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8081431 + * @bug 8081431 8080069 * @summary Test of JShell#drop(). * @build KullaTesting TestingInputStream * @run testng DropTest @@ -31,6 +31,7 @@ import jdk.jshell.DeclarationSnippet; import jdk.jshell.PersistentSnippet; +import jdk.jshell.VarSnippet; import org.testng.annotations.Test; import static jdk.jshell.Snippet.Status.*; @@ -45,21 +46,27 @@ assertDrop(var, ste(var, VALID, DROPPED, true, null), ste(method, VALID, RECOVERABLE_DEFINED, false, var)); - //assertDrop(method, - // ste(method, RECOVERABLE_DEFINED, DROPPED, false, null), - // ste(clazz, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, method)); - //assertDeclareFail("new C();", "compiler.err.cant.resolve.location"); + assertDrop(method, + ste(method, RECOVERABLE_DEFINED, DROPPED, true, null), + ste(clazz, VALID, RECOVERABLE_DEFINED, false, method)); + VarSnippet cc = varKey(assertEval("C c;")); + assertEvalUnresolvedException("new C();", "C", 1, 0); assertVariables(); assertMethods(); assertClasses(); assertActiveKeys(); + method = methodKey(assertEval("int mu() { return x * 4; }", + ste(MAIN_SNIPPET, DROPPED, RECOVERABLE_DEFINED, true, null), + ste(clazz, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); assertEval("int x = 10;", "10", - ste(var, DROPPED, VALID, true, null), + ste(MAIN_SNIPPET, DROPPED, VALID, true, null), ste(method, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)); PersistentSnippet c0 = varKey(assertEval("C c0 = new C();")); assertEval("c0.v();", "\"#40\""); - assertEval("C c = new C();"); + assertEval("C c = new C();", + ste(MAIN_SNIPPET, VALID, VALID, false, null), + ste(cc, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("c.v();", "\"#40\""); assertEval("int mu() { return x * 3; }", ste(MAIN_SNIPPET, VALID, VALID, false, null), @@ -144,9 +151,10 @@ DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(x, VALID, DROPPED, true, null), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, x)); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable x"); - assertDeclareFail("new A().a;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, x)); + assertEval("A foo() { return null; }"); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable x"); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertVariables(); assertActiveKeys(); } @@ -158,9 +166,9 @@ DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(x, VALID, DROPPED, true, null), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, x)); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "method x()"); - assertDeclareFail("new A().a;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, x)); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method x()"); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertMethods(); assertActiveKeys(); } diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/ExternalEditorTest.java --- a/langtools/test/jdk/jshell/ExternalEditorTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/ExternalEditorTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -113,7 +113,7 @@ @Override public void testEditor(boolean defaultStartup, String[] args, ReplTest... tests) { ReplTest[] t = new ReplTest[tests.length + 1]; - t[0] = a -> assertCommandCheckOutput(a, "/seteditor " + executionScript, + t[0] = a -> assertCommandCheckOutput(a, "/set editor " + executionScript, assertStartsWith("| Editor set to: " + executionScript)); System.arraycopy(tests, 0, t, 1, tests.length); super.testEditor(defaultStartup, args, t); @@ -193,8 +193,8 @@ @Test public void setUnknownEditor() { test( - a -> assertCommand(a, "/seteditor", "| /seteditor requires a path argument\n"), - a -> assertCommand(a, "/seteditor UNKNOWN", "| Editor set to: UNKNOWN\n"), + a -> assertCommand(a, "/set editor", "| /set editor requires a path argument\n"), + a -> assertCommand(a, "/set editor UNKNOWN", "| Editor set to: UNKNOWN\n"), a -> assertCommand(a, "int a;", null), a -> assertCommand(a, "/e 1", "| Edit Error: process IO failure: Cannot run program \"UNKNOWN\": error=2, No such file or directory\n") @@ -204,7 +204,7 @@ @Test(enabled = false) public void testRemoveTempFile() { test(new String[]{"-nostartup"}, - a -> assertCommandCheckOutput(a, "/seteditor " + executionScript, + a -> assertCommandCheckOutput(a, "/set editor " + executionScript, assertStartsWith("| Editor set to: " + executionScript)), a -> assertVariable(a, "int", "a", "0", "0"), a -> assertEditOutput(a, "/e 1", assertStartsWith("| Edit Error: Failure read edit file:"), () -> { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/KullaTesting.java --- a/langtools/test/jdk/jshell/KullaTesting.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/KullaTesting.java Mon Mar 21 11:21:08 2016 +0100 @@ -191,14 +191,14 @@ return key; } - public MethodSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { + public DeclarationSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { List events = assertEval(input, null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); SnippetEvent ste = events.get(0); - MethodSnippet methodKey = ((UnresolvedReferenceException) ste.exception()).getMethodSnippet(); - assertEquals(methodKey.name(), name, "Given input: " + input + ", checking name"); - assertEquals(getState().unresolvedDependencies(methodKey).size(), unresolvedSize, "Given input: " + input + ", checking unresolved"); - assertEquals(getState().diagnostics(methodKey).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics"); - return methodKey; + DeclarationSnippet sn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); + assertEquals(sn.name(), name, "Given input: " + input + ", checking name"); + assertEquals(getState().unresolvedDependencies(sn).size(), unresolvedSize, "Given input: " + input + ", checking unresolved"); + assertEquals(getState().diagnostics(sn).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics"); + return sn; } public Snippet assertKeyMatch(String input, boolean isExecutable, SubKind expectedSubKind, STEInfo mainInfo, STEInfo... updates) { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/ReplToolTesting.java --- a/langtools/test/jdk/jshell/ReplToolTesting.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/ReplToolTesting.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -397,6 +397,15 @@ assertCommand(after, cmd, out, "", null, "", ""); } + public void assertCommandOutputContains(boolean after, String cmd, String has) { + assertCommandCheckOutput(after, cmd, (s) -> + assertTrue(s.contains(has), "Output: \'" + s + "' does not contain: " + has)); + } + + public void assertCommandOutputStartsWith(boolean after, String cmd, String starts) { + assertCommandCheckOutput(after, cmd, assertStartsWith(starts)); + } + public void assertCommandCheckOutput(boolean after, String cmd, Consumer check) { if (!after) { assertCommand(false, cmd, null); @@ -437,13 +446,13 @@ } private List computeCompletions(String code, boolean isSmart) { - JShellTool repl = this.repl != null ? this.repl + JShellTool js = this.repl != null ? this.repl : new JShellTool(null, null, null, null, null, null, null); int cursor = code.indexOf('|'); code = code.replace("|", ""); assertTrue(cursor > -1, "'|' not found: " + code); List completions = - repl.commandCompletionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now + js.commandCompletionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now return completions.stream() .filter(s -> isSmart == s.isSmart) .map(s -> s.continuation) @@ -481,6 +490,15 @@ return name.hashCode(); } + @Override + public boolean equals(Object o) { + if (o instanceof MemberInfo) { + MemberInfo mi = (MemberInfo) o; + return name.equals(mi.name); + } + return false; + } + public abstract Consumer checkOutput(); public String getSource() { @@ -537,6 +555,11 @@ } @Override + public int hashCode() { + return name.hashCode(); + } + + @Override public boolean equals(Object o) { if (o instanceof VariableInfo) { VariableInfo v = (VariableInfo) o; @@ -585,6 +608,10 @@ return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s); } + @Override + public int hashCode() { + return (name.hashCode() << 2) ^ type.hashCode() ; + } @Override public boolean equals(Object o) { @@ -616,6 +643,11 @@ } @Override + public int hashCode() { + return name.hashCode() ; + } + + @Override public boolean equals(Object o) { if (o instanceof ClassInfo) { ClassInfo c = (ClassInfo) o; @@ -641,6 +673,11 @@ } @Override + public int hashCode() { + return (name.hashCode() << 2) ^ type.hashCode() ; + } + + @Override public boolean equals(Object o) { if (o instanceof ImportInfo) { ImportInfo i = (ImportInfo) o; diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/ReplaceTest.java --- a/langtools/test/jdk/jshell/ReplaceTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/ReplaceTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* - * @test + * @test 8080069 * @summary Test of Snippet redefinition and replacement. * @build KullaTesting TestingInputStream * @run testng ReplaceTest @@ -30,6 +30,7 @@ import java.util.Collection; +import java.util.List; import jdk.jshell.Snippet; import jdk.jshell.MethodSnippet; import jdk.jshell.PersistentSnippet; @@ -38,9 +39,11 @@ import jdk.jshell.DeclarationSnippet; import org.testng.annotations.Test; +import jdk.jshell.SnippetEvent; +import jdk.jshell.UnresolvedReferenceException; +import static org.testng.Assert.assertEquals; import static jdk.jshell.Snippet.Status.*; import static jdk.jshell.Snippet.SubKind.*; -import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @Test @@ -259,7 +262,7 @@ ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), ste(f, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); - MethodSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1); + DeclarationSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1); assertTrue(exsn == f, "Identity must not change"); assertActiveKeys(); } @@ -289,13 +292,95 @@ } public void testForwardVarToClass() { - DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_NOT_DEFINED))); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable g"); + DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g"); + Snippet g = varKey(assertEval("int g = 10;", "10", + added(VALID), + ste(a, RECOVERABLE_DEFINED, VALID, false, null))); + assertEval("new A().f();", "10"); + assertEval("double g = 10;", "10.0", null, + DiagCheck.DIAG_OK, + DiagCheck.DIAG_ERROR, + ste(MAIN_SNIPPET, VALID, VALID, true, null), + ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); + assertUnresolvedDependencies(a, 0); + assertActiveKeys(); + } + + public void testForwardVarToClassGeneric() { + DeclarationSnippet a = classKey(assertEval("class A { final T x; A(T v) { this.x = v; } ; T get() { return x; } int core() { return g; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g"); + + List events = assertEval("A as = new A<>(\"hi\");", null, + UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); + SnippetEvent ste = events.get(0); + Snippet assn = ste.snippet(); + DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); + assertEquals(unsn.name(), "A", "Wrong with unresolved"); + assertEquals(getState().unresolvedDependencies(unsn).size(), 1, "Wrong size unresolved"); + assertEquals(getState().diagnostics(unsn).size(), 0, "Expected no diagnostics"); + Snippet g = varKey(assertEval("int g = 10;", "10", added(VALID), + ste(a, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); + assertEval("A as = new A<>(\"low\");", + ste(MAIN_SNIPPET, VALID, VALID, false, null), + ste(assn, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); + assertEval("as.get();", "\"low\""); + assertUnresolvedDependencies(a, 0); + assertActiveKeys(); + } + + public void testForwardVarToClassExtendsImplements() { + DeclarationSnippet ik = classKey(assertEval("interface I { default int ii() { return 1; } }", added(VALID))); + DeclarationSnippet jk = classKey(assertEval("interface J { default int jj() { return 2; } }", added(VALID))); + DeclarationSnippet ck = classKey(assertEval("class C { int cc() { return 3; } }", added(VALID))); + DeclarationSnippet dk = classKey(assertEval("class D extends C implements I,J { int dd() { return g; } }", added(RECOVERABLE_DEFINED))); + DeclarationSnippet ek = classKey(assertEval("class E extends D { int ee() { return 5; } }", added(VALID))); + assertUnresolvedDependencies1(dk, RECOVERABLE_DEFINED, "variable g"); + assertEvalUnresolvedException("new D();", "D", 1, 0); + assertEvalUnresolvedException("new E();", "D", 1, 0); + VarSnippet g = varKey(assertEval("int g = 10;", "10", + added(VALID), + ste(dk, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); + assertEval("E e = new E();"); + assertDrop(g, + ste(g, VALID, DROPPED, true, null), + ste(dk, VALID, RECOVERABLE_DEFINED, false, g)); + assertEvalUnresolvedException("new D();", "D", 1, 0); + assertEvalUnresolvedException("new E();", "D", 1, 0); + assertEval("e.ee();", "5"); + assertEvalUnresolvedException("e.dd();", "D", 1, 0); + assertEval("e.cc();", "3"); + assertEval("e.jj();", "2"); + assertEval("e.ii();", "1"); + assertActiveKeys(); + } + + public void testForwardVarToInterface() { + DeclarationSnippet i = classKey(assertEval("interface I { default int f() { return x; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(i, RECOVERABLE_DEFINED, "variable x"); + DeclarationSnippet c = classKey(assertEval("class C implements I { int z() { return 2; } }", added(VALID))); + assertEval("C c = new C();"); + assertEval("c.z();", "2"); + assertEvalUnresolvedException("c.f()", "I", 1, 0); + Snippet g = varKey(assertEval("int x = 55;", "55", + added(VALID), + ste(i, RECOVERABLE_DEFINED, VALID, false, null))); + assertEval("c.f();", "55"); + assertUnresolvedDependencies(i, 0); + assertActiveKeys(); + } + + public void testForwardVarToEnum() { + DeclarationSnippet a = classKey(assertEval("enum E { Q, W, E; float ff() { return fff; } }", added(RECOVERABLE_NOT_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable fff"); + Snippet g = varKey(assertEval("float fff = 4.5f;", "4.5", + added(VALID), ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); - assertEval("new A().f();", "10"); - assertEval("double g = 10;", "10.0", null, + assertEval("E.Q.ff();", "4.5"); + assertEval("double fff = 3.3;", "3.3", null, DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), @@ -305,20 +390,21 @@ assertActiveKeys(); } - public void testForwardMethodToClass() { - DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_NOT_DEFINED))); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "method g()"); + DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method g()"); + assertEval("A foo() { return null; }"); + assertEvalUnresolvedException("new A();", "A", 1, 0); Snippet g = methodKey(assertEval("int g() { return 10; }", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + ste(a, RECOVERABLE_DEFINED, VALID, false, null))); assertEval("new A().f();", "10"); assertEval("double g() { return 10; }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); assertUnresolvedDependencies(a, 0); assertActiveKeys(); } @@ -336,8 +422,8 @@ DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); - assertDeclareFail("new A().b;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, MAIN_SNIPPET)); + assertEvalUnresolvedException("new A().b;", "A", 0, 1); assertActiveKeys(); } @@ -503,42 +589,42 @@ public void testForwardSingleImportMethodToClass1() { PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.format;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s;", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET))); - assertDeclareFail("new A().s;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardSingleImportMethodToClass2() { PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.format;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s();", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardSingleImportClassToClass1() { @@ -589,42 +675,44 @@ public void testForwardImportOnDemandMethodToClass1() { PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); - assertEval("new A().s;", "\"10\""); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); + assertEval("A x = new A();"); + assertEval("x.s;", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); + assertEval("x.s;", "\"10\""); } public void testForwardImportOnDemandMethodToClass2() { PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s();", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardImportOnDemandClassToClass1() { @@ -673,86 +761,87 @@ public void testForwardSingleImportFieldToClass1() { PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.PI;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, false, list)); } public void testForwardSingleImportFieldToClass2() { PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.PI;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, true, null)); assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, true, list)); } public void testForwardImportOnDemandFieldToClass1() { PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, false, list)); } public void testForwardImportOnDemandFieldToClass2() { PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, true, null)); assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, true, list)); + assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); } public void testReplaceCausesMethodReferenceError() { diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/ToolBasicTest.java --- a/langtools/test/jdk/jshell/ToolBasicTest.java Mon Mar 21 08:42:00 2016 +0100 +++ b/langtools/test/jdk/jshell/ToolBasicTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 + * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 * @requires os.family != "solaris" * @summary Tests for Basic tests for REPL tool * @library /tools/lib @@ -90,8 +90,7 @@ public void elideStartUpFromList() { test( - (a) -> assertCommandCheckOutput(a, "123", (s) -> - assertTrue(s.contains("type int"), s)), + (a) -> assertCommandOutputContains(a, "123", "type int"), (a) -> assertCommandCheckOutput(a, "/list", (s) -> { int cnt; try (Scanner scanner = new Scanner(s)) { @@ -112,8 +111,7 @@ Compiler compiler = new Compiler(); Path path = compiler.getPath("myfile"); test( - (a) -> assertCommandCheckOutput(a, "123", - (s) -> assertTrue(s.contains("type int"), s)), + (a) -> assertCommandOutputContains(a, "123", "type int"), (a) -> assertCommand(a, "/save " + path.toString(), "") ); try (Stream lines = Files.lines(path)) { @@ -594,12 +592,12 @@ (a) -> assertMethod(a, "void f() {}", "()V", "f"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommand(a, "/save " + startUpFile.toString(), null), - (a) -> assertCommand(a, "/setstart " + startUpFile.toString(), null) + (a) -> assertCommand(a, "/set start " + startUpFile.toString(), null) ); Path unknown = compiler.getPath("UNKNOWN"); test( - (a) -> assertCommand(a, "/setstart " + unknown.toString(), - "| File '" + unknown + "' for /setstart is not found.\n") + (a) -> assertCommand(a, "/set start " + unknown.toString(), + "| File '" + unknown + "' for /set start is not found.\n") ); test(false, new String[0], (a) -> { @@ -619,7 +617,7 @@ } private void removeStartup() { - Preferences preferences = Preferences.userRoot().node("tool/REPL"); + Preferences preferences = Preferences.userRoot().node("tool/JShell"); if (preferences != null) { preferences.remove("STARTUP"); } @@ -636,7 +634,7 @@ } public void testNoArgument() { - String[] commands = {"/save", "/open", "/setstart"}; + String[] commands = {"/save", "/open", "/set start"}; test(Stream.of(commands) .map(cmd -> { String c = cmd; @@ -670,8 +668,7 @@ test( a -> assertVariable(a, "int", "x"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), - a -> assertCommandCheckOutput(a, "System.exit(5);", s -> - assertTrue(s.contains("terminated"), s)), + a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"), a -> assertCommandCheckOutput(a, "/vars", s -> assertTrue(s.trim().isEmpty(), s)), a -> assertMethod(a, "void f() { }", "()void", "f"), @@ -699,8 +696,7 @@ s -> assertEquals(s, "| No definition or id named " + arg + " found. There are no active definitions.\n")), a -> assertVariable(a, "int", "aardvark"), - a -> assertCommandCheckOutput(a, "/list aardvark", - s -> assertTrue(s.contains("aardvark"))), + a -> assertCommandOutputContains(a, "/list aardvark", "aardvark"), a -> assertCommandCheckOutput(a, "/list start", s -> checkLineToList(s, START_UP)), a -> assertCommandCheckOutput(a, "/list all", @@ -714,14 +710,14 @@ } public void testFeedbackNegative() { - test(a -> assertCommandCheckOutput(a, "/feedback aaaa", - assertStartsWith("| Follow /feedback with of the following"))); + test(a -> assertCommandCheckOutput(a, "/set feedback aaaa", + assertStartsWith("| Does not match any current feedback mode"))); } public void testFeedbackOff() { for (String off : new String[]{"o", "off"}) { test( - a -> assertCommand(a, "/feedback " + off, ""), + a -> assertCommand(a, "/set feedback " + off, ""), a -> assertCommand(a, "int a", ""), a -> assertCommand(a, "void f() {}", ""), a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")), @@ -730,23 +726,6 @@ } } - public void testFeedbackConcise() { - Compiler compiler = new Compiler(); - Path testConciseFile = compiler.getPath("testConciseFeedback"); - String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; - compiler.writeToFile(testConciseFile, sources); - for (String concise : new String[]{"c", "concise"}) { - test( - a -> assertCommand(a, "/feedback " + concise, ""), - a -> assertCommand(a, sources[0], ""), - a -> assertCommand(a, sources[1], ""), - a -> assertCommand(a, sources[2], ""), - a -> assertCommand(a, sources[3], "| a : 10\n"), - a -> assertCommand(a, "/o " + testConciseFile.toString(), "| a : 10\n") - ); - } - } - public void testFeedbackNormal() { Compiler compiler = new Compiler(); Path testNormalFile = compiler.getPath("testConciseNormal"); @@ -759,58 +738,20 @@ "| Variable a has been assigned the value 10\n" }; compiler.writeToFile(testNormalFile, sources2); - for (String feedback : new String[]{"/f", "/feedback"}) { - for (String feedbackState : new String[]{"n", "normal", "v", "verbose"}) { - String f = null; - if (feedbackState.startsWith("n")) { - f = "normal"; - } else if (feedbackState.startsWith("v")) { - f = "verbose"; - } - final String finalF = f; + for (String feedback : new String[]{"/set f", "/set feedback"}) { + for (String feedbackState : new String[]{"n", "normal", "o", "off"}) { test( - a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: " + finalF +"\n"), + a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: normal\n"), a -> assertCommand(a, sources[0], output[0]), a -> assertCommand(a, sources[1], output[1]), a -> assertCommand(a, sources[2], output[2]), a -> assertCommand(a, sources[3], output[3]), - a -> assertCommand(a, "/o " + testNormalFile.toString(), - "| Modified variable a of type int\n" + - "| Modified method f()\n" + - "| Update overwrote method f()\n" + - "| Modified class A\n" + - "| Update overwrote class A\n" + - "| Variable a has been assigned the value 10\n") + a -> assertCommand(a, "/o " + testNormalFile.toString(), "") ); } } } - public void testFeedbackDefault() { - Compiler compiler = new Compiler(); - Path testDefaultFile = compiler.getPath("testDefaultFeedback"); - String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; - String[] output = new String[] { - "| Added variable a of type int\n", - "| Added method f()\n", - "| Added class A\n", - "| Variable a has been assigned the value 10\n" - }; - compiler.writeToFile(testDefaultFile, sources); - for (String defaultFeedback : new String[]{"", "d", "default"}) { - test( - a -> assertCommand(a, "/feedback o", ""), - a -> assertCommand(a, "int x", ""), - a -> assertCommand(a, "/feedback " + defaultFeedback, "| Feedback mode: default\n"), - a -> assertCommand(a, sources[0], output[0]), - a -> assertCommand(a, sources[1], output[1]), - a -> assertCommand(a, sources[2], output[2]), - a -> assertCommand(a, sources[3], output[3]), - a -> assertCommand(a, "/o " + testDefaultFile.toString(), "") - ); - } - } - public void testDrop() { test(false, new String[]{"-nostartup"}, a -> assertVariable(a, "int", "a"), @@ -906,7 +847,7 @@ public void testCommandPrefix() { test(a -> assertCommandCheckOutput(a, "/s", - assertStartsWith("| Command: /s is ambiguous: /seteditor, /save, /setstart")), + assertStartsWith("| Command: /s is ambiguous: /save, /set")), a -> assertCommand(a, "int var", "| Added variable var of type int\n"), a -> assertCommandCheckOutput(a, "/va", assertStartsWith("| int var = 0")), diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/jdk/jshell/ToolFormatTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/jdk/jshell/ToolFormatTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8148316 8148317 + * @summary Tests for output customization + * @library /tools/lib + * @build KullaTesting TestingInputStream ToolBox Compiler + * @run testng ToolFormatTest + */ +import org.testng.annotations.Test; + +@Test +public class ToolFormatTest extends ReplToolTesting { + + public void testSetFormat() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode test command", "| Created new feedback mode: test"), + (a) -> assertCommand(a, "/set field test pre '$ '", ""), + (a) -> assertCommand(a, "/set field test post ''", ""), + (a) -> assertCommand(a, "/set field test action 'ADD ' added-primary", ""), + (a) -> assertCommand(a, "/set field test action 'MOD ' modified-primary", ""), + (a) -> assertCommand(a, "/set field test action 'REP ' replaced-primary", ""), + (a) -> assertCommand(a, "/set field test action 'UP-ADD ' added-update", ""), + (a) -> assertCommand(a, "/set field test action 'UP-MOD ' modified-update", ""), + (a) -> assertCommand(a, "/set field test action 'UP-REP ' replaced-update", ""), + (a) -> assertCommand(a, "/set field test resolve 'OK' ok-*", ""), + (a) -> assertCommand(a, "/set field test resolve 'DEF' defined-*", ""), + (a) -> assertCommand(a, "/set field test resolve 'NODEF' notdefined-*", ""), + (a) -> assertCommand(a, "/set field test name ':%s ' ", ""), + (a) -> assertCommand(a, "/set field test type '[%s]' ", ""), + (a) -> assertCommand(a, "/set field test result '=%s ' ", ""), + (a) -> assertCommand(a, "/set format test '{pre}{action}{type}{name}{result}{resolve}' *-*-*", ""), + (a) -> assertCommand(a, "/set format test '{pre}HI this is enum' enum", ""), + (a) -> assertCommand(a, "/set feedback test", "$ Feedback mode: test"), + (a) -> assertCommand(a, "class D {}", "$ ADD :D OK"), + (a) -> assertCommand(a, "void m() {}", "$ ADD []:m OK"), + (a) -> assertCommand(a, "interface EX extends EEX {}", "$ ADD :EX NODEF"), + (a) -> assertCommand(a, "56", "$ ADD [int]:$4 =56 OK"), + (a) -> assertCommand(a, "class D { int hh; }", "$ REP :D OK$ OVERWROTE-UPDATE:D OK"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testNewModeQuiet() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode nmq quiet normal", "| Created new feedback mode: nmq"), + (a) -> assertCommand(a, "/set feedback nmq", ""), + (a) -> assertCommand(a, "/se ne nmq2 q nor", ""), + (a) -> assertCommand(a, "/se fee nmq2", ""), + (a) -> assertCommand(a, "/set newmode nmc command normal", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"), + (a) -> assertCommandOutputStartsWith(a, "/set newmode nm", "| Created new feedback mode: nm"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetError() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"), + (a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback te", ""), + (a) -> assertCommandCheckOutput(a, "/set ", assertStartsWith("ERROR: The /set command requires arguments")), + (a) -> assertCommandCheckOutput(a, "/set xyz", assertStartsWith("ERROR: Not a valid argument to /set")), + (a) -> assertCommandCheckOutput(a, "/set f", assertStartsWith("ERROR: Ambiguous argument to /set")), + (a) -> assertCommandCheckOutput(a, "/set feedback", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set feedback xyz", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format xyz", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set format te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa'", assertStartsWith("ERROR: At least one selector required")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa' frog", assertStartsWith("ERROR: Not a valid case")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa' import-frog", assertStartsWith("ERROR: Not a valid action")), + (a) -> assertCommandCheckOutput(a, "/set newmode", assertStartsWith("ERROR: Expected new feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set newmode te", assertStartsWith("ERROR: Expected a new feedback mode name")), + (a) -> assertCommandCheckOutput(a, "/set newmode x xyz", assertStartsWith("ERROR: Specify either 'command' or 'quiet'")), + (a) -> assertCommandCheckOutput(a, "/set newmode x quiet y", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set prompt te aaa xyz", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa' xyz", assertStartsWith("ERROR: Format 'xyz' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set prompt te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa'", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set field", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set field xyz", assertStartsWith("ERROR: Does not match any current feedback mode: xyz")), + (a) -> assertCommandCheckOutput(a, "/set field te xyz", assertStartsWith("ERROR: Not a valid field: xyz, must be one of: when")), + (a) -> assertCommandCheckOutput(a, "/set field te action", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set field te action 'act'", assertStartsWith("ERROR: At least one selector required")) + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetHelp() { + try { + test( + (a) -> assertCommandOutputContains(a, "/help /set", "command to launch"), + (a) -> assertCommandOutputContains(a, "/help /set format", "vardecl"), + (a) -> assertCommandOutputContains(a, "/hel /se for", "vardecl"), + (a) -> assertCommandOutputContains(a, "/help /set editor", "temporary file") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetHelpError() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"), + (a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback te", "| Feedback mode: te"), + (a) -> assertCommandOutputContains(a, "/help /set xyz", "ERROR: Not a valid argument to /set: xyz"), + (a) -> assertCommandOutputContains(a, "/help /set f", "ERROR: Ambiguous argument to /set: f") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.BootstrapMethods_attribute.BootstrapMethodSpecifier; +import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info; +import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info; + +import java.io.File; + +/* + * @test + * @bug 8148483 8151516 8151223 + * @summary Test that StringConcat is working for JDK >= 9 + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean TestIndyStringConcat* + * @compile -source 6 -target 6 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -source 7 -target 7 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -source 8 -target 8 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat true + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat true + */ +public class TestIndyStringConcat { + + static String other; + + public static String test() { + return "Foo" + other; + } + + public static void main(String[] args) throws Exception { + boolean expected = Boolean.valueOf(args[0]); + boolean actual = hasStringConcatFactoryCall("test"); + if (expected != actual) { + throw new AssertionError("expected = " + expected + ", actual = " + actual); + } + } + + public static boolean hasStringConcatFactoryCall(String methodName) throws Exception { + ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."), + TestIndyStringConcat.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + BootstrapMethods_attribute bsm_attr = + (BootstrapMethods_attribute)classFile + .getAttribute(Attribute.BootstrapMethods); + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals(methodName)) { + Code_attribute code = (Code_attribute) method.attributes + .get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = + (CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1)); + + BootstrapMethodSpecifier bsmSpec = + bsm_attr.bootstrap_method_specifiers[indyInfo.bootstrap_method_attr_index]; + + CONSTANT_MethodHandle_info bsmInfo = + (CONSTANT_MethodHandle_info) constantPool.get(bsmSpec.bootstrap_method_ref); + + if (bsmInfo.getCPRefInfo().getClassName().equals("java/lang/invoke/StringConcatFactory")) { + return true; + } + } + } + } + } + return false; + } + +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/Holder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/Holder.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Holder { + public Private_PublicClass c1 = new Private_PublicClass(); + public Private_PublicInterface c2 = new Private_PublicInterface(); + public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); + public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); + + public Public_PublicClass c5 = new Public_PublicClass(); + public Public_PublicInterface c6 = new Public_PublicInterface(); + public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); + public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); + + public Private_PublicClass[] ac1 = new Private_PublicClass[0]; + public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; + public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; + public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; + + public Public_PublicClass[] ac5 = new Public_PublicClass[0]; + public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; + public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; + public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; + + public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; + public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; + public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; + public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; + + public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; + public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; + public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; + public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; + + public PublicInterface i1 = new Private_PublicInterface(); + public PrivateInterface1 i2 = new Private_PrivateInterface1(); + public PrivateInterface2 i3 = new Private_PrivateInterface2(); + + public PublicInterface[] ai1 = new Private_PublicInterface[0]; + public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; + public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; + + public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; + public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; + public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; +} + +interface PrivateInterface1 { +} + +interface PrivateInterface2 extends PublicInterface { +} + +class Private_PublicClass extends PublicClass { + public String toString() { + return "passed"; + } +} + +class Private_PublicInterface implements PublicInterface { + public String toString() { + return "passed"; + } +} + +class Private_PrivateInterface1 implements PrivateInterface1 { + public String toString() { + return "passed"; + } +} + +class Private_PrivateInterface2 implements PrivateInterface2 { + public String toString() { + return "passed"; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/PublicClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/PublicClass.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class PublicClass { +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/PublicInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/PublicInterface.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public interface PublicInterface { +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PrivateInterface1 implements PrivateInterface1 { + public String toString() { + return "passed"; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PrivateInterface2 implements PrivateInterface2 { + public String toString() { + return "passed"; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PublicClass { + public String toString() { + return "passed"; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PublicInterface implements PublicInterface { + public String toString() { + return "passed"; + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/StringConcat/access/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/StringConcat/access/Test.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/* + * @test + * @bug 8151223 + * @summary String concatenation fails with implicit toString() on package-private class + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean * + * @compile -XDstringConcat=indy Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + * + * @clean * + * @compile -XDstringConcat=indyWithConstants Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + */ + +public class Test { + static List actualTypes; + + public static void main(String[] argv) throws Exception { + readIndyTypes(); + + p1.Holder holder = new p1.Holder(); + + int idx = 0; + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass c1 = new Private_PublicClass(); + test("" + holder.c1, idx++, "(Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface c2 = new Private_PublicInterface(); + test("" + holder.c2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); + test("" + holder.c3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); + test("" + holder.c4, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass c5 = new Public_PublicClass(); + test("" + holder.c5, idx++, "(Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface c6 = new Public_PublicInterface(); + test("" + holder.c6, idx++, "(Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); + test("" + holder.c7, idx++, "(Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); + test("" + holder.c8, idx++, "(Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass[] ac1 = new Private_PublicClass[0]; + test("" + holder.ac1, idx++, "([Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; + test("" + holder.ac2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; + test("" + holder.ac3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; + test("" + holder.ac4, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass[] ac5 = new Public_PublicClass[0]; + test("" + holder.ac5, idx++, "([Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; + test("" + holder.ac6, idx++, "([Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; + test("" + holder.ac7, idx++, "([Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; + test("" + holder.ac8, idx++, "([Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; + test("" + holder.aac1, idx++, "([[Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; + test("" + holder.aac2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; + test("" + holder.aac3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; + test("" + holder.aac4, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; + test("" + holder.aac5, idx++, "([[Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; + test("" + holder.aac6, idx++, "([[Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; + test("" + holder.aac7, idx++, "([[Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; + test("" + holder.aac8, idx++, "([[Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public PublicInterface i1 = new Private_PublicInterface(); + test("" + holder.i1, idx++, "(Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1 i2 = new Private_PrivateInterface1(); + test("" + holder.i2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2 i3 = new Private_PrivateInterface2(); + test("" + holder.i3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public PublicInterface[] ai1 = new Private_PublicInterface[0]; + test("" + holder.ai1, idx++, "([Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; + test("" + holder.ai2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; + test("" + holder.ai3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; + test("" + holder.aai1, idx++, "([[Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; + test("" + holder.aai2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; + test("" + holder.aai3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + } + + public static void test(String actual, int index, String expectedType) { + if (!"passed".equals(actual) && !actual.startsWith("[")) { + throw new IllegalStateException("Unexpected result: " + actual); + } + String actualType = actualTypes.get(index); + if (!actualType.equals(expectedType)) { + throw new IllegalStateException("Unexpected type: expected = " + expectedType + ", actual = " + actualType); + } + } + + public static void readIndyTypes() throws Exception { + actualTypes = new ArrayList(); + + ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."), + Test.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals("main")) { + Code_attribute code = (Code_attribute) method.attributes + .get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = (CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1)); + CONSTANT_NameAndType_info natInfo = indyInfo.getNameAndTypeInfo(); + actualTypes.add(natInfo.getType()); + } + } + } + } + } +} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8139474 + * @summary -release 7 -verbose causes Javac exception + * @compile -release 7 -verbose DashRelease7DashVerboseTest.java +*/ + +public class DashRelease7DashVerboseTest {} diff -r 0dc62e7c6a29 -r 74e9f4b90006 langtools/test/tools/javac/TestIndyStringConcat.java --- a/langtools/test/tools/javac/TestIndyStringConcat.java Mon Mar 21 08:42:00 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test that StringConcat is working for JDK >= 9 - * @compile -source 6 -target 6 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -source 7 -target 7 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -source 8 -target 8 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat true - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat true - */ -public class TestIndyStringConcat { - - private static class MyObject { - public String toString() { - throw new RuntimeException("Boyyaa"); - } - } - - class Inner { } - - public static void main(String[] args) { - boolean useIndyConcat = Boolean.valueOf(args[0]); - try { - String s = "Foo" + new MyObject(); - } catch (RuntimeException ex) { - boolean indifiedStringConcat = false; - ex.printStackTrace(); - for (StackTraceElement e : ex.getStackTrace()) { - if (e.getClassName().contains("$$StringConcat") && - e.getMethodName().equals("concat")) { - indifiedStringConcat = true; - break; - } - } - if (indifiedStringConcat != useIndyConcat) { - throw new AssertionError(); - } - } - } -} diff -r 0dc62e7c6a29 -r 74e9f4b90006 make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Mon Mar 21 08:42:00 2016 +0100 +++ b/make/CompileJavaModules.gmk Mon Mar 21 11:21:08 2016 +0100 @@ -368,21 +368,7 @@ ################################################################################ jdk.hotspot.agent_ADD_JAVAC_FLAGS := $(DISABLE_WARNINGS),-overrides -jdk.hotspot.agent_COPY := .png sa.js .properties - -ifeq ($(MODULE), jdk.hotspot.agent) - ### Copy gif files - # Special handling to copy gif files in images/toolbarButtonGraphics \ - # -> classes/toolbarButtonGraphics. - # These can't be handled by COPY to SetupJavaCompilation since they chop off - # one directory level. - $(eval $(call SetupCopyFiles, COPY_SA_IMAGES, \ - SRC := $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/images, \ - DEST := $(JDK_OUTPUTDIR)/modules/$(MODULE), \ - FILES := $(wildcard $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/images/*/*/*.gif), \ - )) - jdk.hotspot.agent: $(COPY_SA_IMAGES) -endif +jdk.hotspot.agent_COPY := .gif .png sa.js .properties ################################################################################ diff -r 0dc62e7c6a29 -r 74e9f4b90006 make/Images.gmk --- a/make/Images.gmk Mon Mar 21 08:42:00 2016 +0100 +++ b/make/Images.gmk Mon Mar 21 11:21:08 2016 +0100 @@ -62,10 +62,6 @@ PROVIDER_MODULES += jdk.crypto.ucrypto endif -ifeq ($(OPENJDK_TARGET_OS), macosx) - MAIN_MODULES += jdk.deploy.osx -endif - JRE_MODULES := $(filter-out $(MODULES_FILTER), $(MAIN_MODULES) $(PROVIDER_MODULES)) JDK_MODULES := $(filter-out $(MODULES_FILTER), $(JRE_MODULES) $(TOOLS_MODULES)) diff -r 0dc62e7c6a29 -r 74e9f4b90006 make/Main.gmk --- a/make/Main.gmk Mon Mar 21 08:42:00 2016 +0100 +++ b/make/Main.gmk Mon Mar 21 11:21:08 2016 +0100 @@ -413,9 +413,6 @@ # Declare dependencies from all other -lib to java.base-lib $(foreach t, $(filter-out java.base-libs, $(LIBS_TARGETS)), \ $(eval $t: java.base-libs)) - # Declare the special case dependency for jdk.deploy.osx where libosx - # links against libosxapp. - jdk.deploy.osx-libs: java.desktop-libs # jdk.accessibility depends on java.desktop jdk.accessibility-libs: java.desktop-libs diff -r 0dc62e7c6a29 -r 74e9f4b90006 make/common/NON_CORE_PKGS.gmk --- a/make/common/NON_CORE_PKGS.gmk Mon Mar 21 08:42:00 2016 +0100 +++ b/make/common/NON_CORE_PKGS.gmk Mon Mar 21 11:21:08 2016 +0100 @@ -98,8 +98,7 @@ SCTPAPI_PKGS = com.sun.nio.sctp ifeq ($(PLATFORM), macosx) - APPLE_EXT_PKGS = com.apple.concurrent \ - com.apple.eawt \ + APPLE_EXT_PKGS = com.apple.eawt \ com.apple.eawt.event \ com.apple.eio endif diff -r 0dc62e7c6a29 -r 74e9f4b90006 make/devkit/createWindowsDevkit.sh --- a/make/devkit/createWindowsDevkit.sh Mon Mar 21 08:42:00 2016 +0100 +++ b/make/devkit/createWindowsDevkit.sh Mon Mar 21 11:21:08 2016 +0100 @@ -74,6 +74,10 @@ cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/ cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/amd64/ cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/amd64/ + # The msvcdis dll is needed to run some of the tools in VC/bin but is not + # shipped in that directory. Copy it from the common dir. + cp "$VS_INSTALL_DIR/Common7/IDE/msvcdis${VS_VERSION_NUM_NODOT}.dll" \ + $DEVKIT_ROOT/VC/bin/ fi ################################################################################ diff -r 0dc62e7c6a29 -r 74e9f4b90006 modules.xml --- a/modules.xml Mon Mar 21 08:42:00 2016 +0100 +++ b/modules.xml Mon Mar 21 11:21:08 2016 +0100 @@ -239,6 +239,7 @@ java.xml jdk.charsets jdk.management.resource + jdk.jfr jdk.net jdk.scripting.nashorn jdk.vm.ci @@ -250,6 +251,22 @@ jdk.jvmstat + jdk.internal.org.xml.sax + jdk.jfr + + + jdk.internal.org.xml.sax.helpers + jdk.jfr + + + jdk.internal.util.xml + jdk.jfr + + + jdk.internal.util.xml.impl + jdk.jfr + + jdk.internal.org.objectweb.asm java.instrument jdk.jfr @@ -300,7 +317,6 @@ java.xml jdk.charsets jdk.crypto.pkcs11 - jdk.deploy.osx jdk.httpserver jdk.jartool jdk.jconsole @@ -314,6 +330,7 @@ jdk.vm.ci jdk.zipfs java.instrument + jdk.jfr sun.net @@ -421,7 +438,6 @@ sun.security.pkcs jdk.crypto.ec - jdk.deploy.osx jdk.jartool @@ -462,7 +478,6 @@ jdk.crypto.mscapi jdk.crypto.pkcs11 jdk.crypto.ucrypto - jdk.deploy.osx jdk.jartool jdk.policytool jdk.security.auth @@ -473,7 +488,6 @@ java.naming jdk.crypto.ec jdk.crypto.pkcs11 - jdk.deploy.osx jdk.jartool jdk.security.auth @@ -926,6 +940,7 @@ sun.management.spi jdk.management jdk.management.cmm + jdk.management.jfr @@ -1707,11 +1722,6 @@ java.base - jdk.deploy.osx - java.base - java.desktop - - jdk.dev java.base diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/.hgignore --- a/nashorn/.hgignore Mon Mar 21 08:42:00 2016 +0100 +++ b/nashorn/.hgignore Mon Mar 21 11:21:08 2016 +0100 @@ -28,3 +28,4 @@ .project .externalToolBuilders/* .settings/* +NashornProfile.txt diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/.hgtags --- a/nashorn/.hgtags Mon Mar 21 08:42:00 2016 +0100 +++ b/nashorn/.hgtags Mon Mar 21 11:21:08 2016 +0100 @@ -342,3 +342,4 @@ cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107 58409eff7e3e0c07f12f543341769964619c0acf jdk-9+108 +70f0c397021116d7dbd79b01c6711c5d2e68dab4 jdk-9+109 diff -r 0dc62e7c6a29 -r 74e9f4b90006 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 Mon Mar 21 08:42:00 2016 +0100 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Mar 21 11:21:08 2016 +0100 @@ -2724,12 +2724,9 @@ // Retrieve current state of ENV variables. env.putAll(System.getenv(), scriptEnv._strict); - // Some platforms, e.g., Windows, do not define the PWD environment - // variable, so that the $ENV.PWD property needs to be explicitly - // set. - if (!env.containsKey(ScriptingFunctions.PWD_NAME)) { - env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); - } + // Set the PWD variable to a value that is guaranteed to be understood + // by the underlying platform. + env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); } addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java Mon Mar 21 08:42:00 2016 +0100 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java Mon Mar 21 11:21:08 2016 +0100 @@ -64,6 +64,9 @@ return System.getProperty("os.name").contains("Windows"); }); + // Cygwin drive alias prefix. + private static final String CYGDRIVE = "/cygdrive/"; + // User's home directory private static final String HOME_DIRECTORY = AccessController.doPrivileged((PrivilegedAction)() -> { @@ -246,18 +249,22 @@ // Stream to copy to. private final OutputStream output; + private final Thread thread; + Piper(final InputStream input, final OutputStream output) { this.input = input; this.output = output; + this.thread = new Thread(this, "$EXEC Piper"); } /** * start - start the Piper in a new daemon thread + * @return this Piper */ - void start() { - Thread thread = new Thread(this, "$EXEC Piper"); + Piper start() { thread.setDaemon(true); thread.start(); + return this; } /** @@ -292,6 +299,10 @@ } } + public void join() throws InterruptedException { + thread.join(); + } + // Exit thread. } @@ -388,7 +399,7 @@ * @return resolved Path to file */ private static Path resolvePath(final String cwd, final String fileName) { - return Paths.get(cwd).resolve(fileName).normalize(); + return Paths.get(sanitizePath(cwd)).resolve(fileName).normalize(); } /** @@ -402,7 +413,8 @@ switch (cmd.get(0)) { // Set current working directory. case "cd": - // If zero args then use home dirrectory as cwd else use first arg. + final boolean cygpath = IS_WINDOWS && cwd.startsWith(CYGDRIVE); + // If zero args then use home directory as cwd else use first arg. final String newCWD = cmd.size() < 2 ? HOME_DIRECTORY : cmd.get(1); // Normalize the cwd final Path cwdPath = resolvePath(cwd, newCWD); @@ -418,7 +430,13 @@ } // Set PWD environment variable to be picked up as cwd. - environment.put("PWD", cwdPath.toString()); + // Make sure Cygwin paths look like Unix paths. + String scwd = cwdPath.toString(); + if (cygpath && scwd.length() >= 2 && + Character.isLetter(scwd.charAt(0)) && scwd.charAt(1) == ':') { + scwd = CYGDRIVE + Character.toLowerCase(scwd.charAt(0)) + "/" + scwd.substring(2); + } + environment.put("PWD", scwd); return true; // Set an environment variable. @@ -445,7 +463,8 @@ } /** - * preprocessCommand - scan the command for redirects + * preprocessCommand - scan the command for redirects, and sanitize the + * executable path * @param tokens command tokens * @param cwd current working directory * @param redirectInfo redirection information @@ -471,10 +490,39 @@ command.add(stripQuotes(token)); } + if (command.size() > 0) { + command.set(0, sanitizePath(command.get(0))); + } + return command; } /** + * Sanitize a path in case the underlying platform is Cygwin. In that case, + * convert from the {@code /cygdrive/x} drive specification to the usual + * Windows {@code X:} format. + * + * @param d a String representing a path + * @return a String representing the same path in a form that can be + * processed by the underlying platform + */ + private static String sanitizePath(final String d) { + if (!IS_WINDOWS || (IS_WINDOWS && !d.startsWith(CYGDRIVE))) { + return d; + } + final String pd = d.substring(CYGDRIVE.length()); + if (pd.length() >= 2 && pd.charAt(1) == '/') { + // drive letter plus / -> convert /cygdrive/x/... to X:/... + return pd.charAt(0) + ":" + pd.substring(1); + } else if (pd.length() == 1) { + // just drive letter -> convert /cygdrive/x to X: + return pd.charAt(0) + ":"; + } + // remaining case: /cygdrive/ -> can't convert + return d; + } + + /** * createProcessBuilder - create a ProcessBuilder for the command. * @param command command tokens * @param cwd current working directory @@ -485,7 +533,7 @@ // Create new ProcessBuilder. final ProcessBuilder pb = new ProcessBuilder(command); // Set current working directory. - pb.directory(new File(cwd)); + pb.directory(new File(sanitizePath(cwd))); // Map environment variables. final Map processEnvironment = pb.environment(); @@ -523,7 +571,7 @@ // Create ProcessBuilder with cwd and redirects set. createProcessBuilder(command, cwd, redirectInfo); - // If piped the wait for the next command. + // If piped, wait for the next command. if (isPiped) { return; } @@ -581,15 +629,17 @@ ByteArrayOutputStream byteOutputStream = null; ByteArrayOutputStream byteErrorStream = null; + final List piperThreads = new ArrayList<>(); + // If input is not redirected. if (inputIsPipe) { // If inputStream other than System.in is provided. if (inputStream != null) { // Pipe inputStream to first process output stream. - new Piper(inputStream, firstProcess.getOutputStream()).start(); + piperThreads.add(new Piper(inputStream, firstProcess.getOutputStream()).start()); } else { // Otherwise assume an input string has been provided. - new Piper(new ByteArrayInputStream(inputString.getBytes()), firstProcess.getOutputStream()).start(); + piperThreads.add(new Piper(new ByteArrayInputStream(inputString.getBytes()), firstProcess.getOutputStream()).start()); } } @@ -598,11 +648,11 @@ // If outputStream other than System.out is provided. if (outputStream != null ) { // Pipe outputStream from last process input stream. - new Piper(lastProcess.getInputStream(), outputStream).start(); + piperThreads.add(new Piper(lastProcess.getInputStream(), outputStream).start()); } else { // Otherwise assume an output string needs to be prepared. byteOutputStream = new ByteArrayOutputStream(BUFFER_SIZE); - new Piper(lastProcess.getInputStream(), byteOutputStream).start(); + piperThreads.add(new Piper(lastProcess.getInputStream(), byteOutputStream).start()); } } @@ -610,11 +660,11 @@ if (errorIsPipe) { // If errorStream other than System.err is provided. if (errorStream != null) { - new Piper(lastProcess.getErrorStream(), errorStream).start(); + piperThreads.add(new Piper(lastProcess.getErrorStream(), errorStream).start()); } else { // Otherwise assume an error string needs to be prepared. byteErrorStream = new ByteArrayOutputStream(BUFFER_SIZE); - new Piper(lastProcess.getErrorStream(), byteErrorStream).start(); + piperThreads.add(new Piper(lastProcess.getErrorStream(), byteErrorStream).start()); } } @@ -622,13 +672,13 @@ for (int i = 0, n = processes.size() - 1; i < n; i++) { final Process prev = processes.get(i); final Process next = processes.get(i + 1); - new Piper(prev.getInputStream(), next.getOutputStream()).start(); + piperThreads.add(new Piper(prev.getInputStream(), next.getOutputStream()).start()); } // Wind up processes. try { // Get the user specified timeout. - long timeout = envVarLongValue("JJS_TIMEOUT"); + final long timeout = envVarLongValue("JJS_TIMEOUT"); // If user specified timeout (milliseconds.) if (timeout != 0) { @@ -643,6 +693,10 @@ // Wait for last process and get exit code. exitCode = lastProcess.waitFor(); } + // Wait for all piper threads to terminate + for (final Piper piper : piperThreads) { + piper.join(); + } // Accumulate the output and error streams. outputString += byteOutputStream != null ? byteOutputStream.toString() : ""; @@ -765,7 +819,7 @@ /** * process - process a command array of strings - * @param script command script to be processed + * @param tokens command script to be processed */ void process(final List tokens) { // Prepare to accumulate command tokens. diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Mon Mar 21 08:42:00 2016 +0100 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Mon Mar 21 11:21:08 2016 +0100 @@ -72,7 +72,7 @@ public static final String EXIT_NAME = "$EXIT"; /** Names of special properties used by $ENV API. */ - public static final String ENV_NAME = "$ENV"; + public static final String ENV_NAME = "$ENV"; /** Name of the environment variable for the current working directory. */ public static final String PWD_NAME = "PWD"; diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/test/script/nosecurity/JDK-8151291.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/nosecurity/JDK-8151291.js Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Test $EXEC and $ENV.PWD handling across platforms. + * There must be a java executable in the PATH. + * + * @test + * @option -scripting + * @run + */ + +$EXEC(["java", "-version"]) +if ($EXIT != 0) { + throw 'java executable problem: ' + $ERR +} + +function eq(p, q, e) { + if (p != q) { + throw e + } +} + +function neq(p, q, e) { + if (p == q) { + throw e + } +} + +var File = Java.type("java.io.File"), + System = Java.type("java.lang.System"), + win = System.getProperty("os.name").startsWith("Windows"), + sep = File.separator, + startwd = $ENV.PWD, + upwd = startwd.substring(0, startwd.lastIndexOf(sep)) + +$EXEC("ls") +var ls_startwd = $OUT +$EXEC("cd ..; ls") +var ls_cdupwd = $OUT +eq($ENV.PWD, startwd, 'PWD changed during $EXEC cd') +neq(ls_startwd, ls_cdupwd, 'same ls result for startwd and upwd with $EXEC cd') + +$ENV.PWD = upwd +eq($ENV.PWD, upwd, '$ENV.PWD change had no effect') +$EXEC("ls") +var ls_epupwd = $OUT +neq(ls_startwd, ls_epupwd, 'same ls result for startwd and upwd with $ENV.PWD cd') diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/test/script/trusted/JDK-8087292.js --- a/nashorn/test/script/trusted/JDK-8087292.js Mon Mar 21 08:42:00 2016 +0100 +++ b/nashorn/test/script/trusted/JDK-8087292.js Mon Mar 21 11:21:08 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,26 +29,58 @@ * @run */ +load(__DIR__ + "JDK-util.js") + +var jHomePath = System.getenv("JAVA_HOME") +var jLauncher = "${jHomePath}/bin/java" +var altjLauncher = which('java') + +if (windows) { + if(winCyg) { + jLauncher = "${jHomePath}" + "/bin/java.exe" + jLauncher = cygpath(jLauncher,outPath.windows) + } + else { + jLauncher = "${jHomePath}" + "\\bin\\java.exe" + altjLauncher = which('java.exe') + altjLauncher = cygpath(altjLauncher,outPath.windows) + } +} + +function exists(f) { + return Files.exists(Paths.get(f)) +} + +var javaLauncher = exists(jLauncher) ? jLauncher : altjLauncher + + +if (!exists(javaLauncher)) { + throw "no java launcher found; tried ${jLauncher} and ${altjLauncher}" +} + function tryExec() { try { - `java` + $EXEC("${javaLauncher}") } catch (e) { - print(e); + print(e) } // make sure we got non-zero ("failure") exit code! if ($EXIT == 0) { - print("Error: expected $EXIT code to be non-zero"); + print("Error: expected $EXIT code to be non-zero") } } +//convert windows paths to cygwin +if (windows) + javaLauncher = (winCyg) ? cygpath(javaLauncher,outPath.mixed).trim() : cygpath(javaLauncher,outPath.windows).trim() // no exception now! -tryExec(); +tryExec() // turn on error with non-zero exit code -$ENV.JJS_THROW_ON_EXIT = "1"; -tryExec(); +$ENV.JJS_THROW_ON_EXIT = "1" +tryExec() // no exception after this -$ENV.JJS_THROW_ON_EXIT = "0"; -tryExec(); +$ENV.JJS_THROW_ON_EXIT = "0" +tryExec() diff -r 0dc62e7c6a29 -r 74e9f4b90006 nashorn/test/script/trusted/JDK-util.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/trusted/JDK-util.js Mon Mar 21 11:21:08 2016 +0100 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This file contains utility functions used by other tests. + * @subtest + */ + +var Files = Java.type('java.nio.file.Files'), + Paths = Java.type('java.nio.file.Paths'), + System = Java.type('java.lang.System') + +var File = java.io.File +var windows = System.getProperty("os.name").startsWith("Windows") +var winCyg = false + +var outPath = { + windows:0, //C:\dir + mixed:1 //C:/dir +} + +if (windows) { + //Is there any better way to diffrentiate between cygwin/command prompt on windows + var term = System.getenv("TERM") + winCyg = term ? true:false +} + +/** + * Returns which command is selected from PATH + * @param cmd name of the command searched from PATH + */ +function which(cmd) { + var path = System.getenv("PATH") + var st = new java.util.StringTokenizer(path, File.pathSeparator) + while (st.hasMoreTokens()) { + var file = new File(st.nextToken(), cmd) + if (file.exists()) { + return (file.getAbsolutePath()) + } + } +} + +/** + * Unix cygpath implementation + * Supports only two outputs,windows(C:\dir\) and mixed(C:/dir/) + */ +function cygpath(path,mode) { + + var newpath = path + if(path.startsWith("/cygdrive/")){ + var str = path.substring(10) + var index = str.indexOf('/',0) + var drv = str.substring(0,index) + var rstr = drv.toUpperCase() + ":" + newpath = str.replaceFirst(drv,rstr) + } + if (mode == outPath.windows) + return Paths.get(newpath).toString() + else { + newpath = newpath.replaceAll('\\\\','/') + return newpath + } + +} + diff -r 0dc62e7c6a29 -r 74e9f4b90006 test/lib/sun/hotspot/WhiteBox.java --- a/test/lib/sun/hotspot/WhiteBox.java Mon Mar 21 08:42:00 2016 +0100 +++ b/test/lib/sun/hotspot/WhiteBox.java Mon Mar 21 11:21:08 2016 +0100 @@ -119,6 +119,28 @@ return getConstantPool0(aClass); } + private native int getConstantPoolCacheIndexTag0(); + public int getConstantPoolCacheIndexTag() { + return getConstantPoolCacheIndexTag0(); + } + + private native int getConstantPoolCacheLength0(Class aClass); + public int getConstantPoolCacheLength(Class aClass) { + Objects.requireNonNull(aClass); + return getConstantPoolCacheLength0(aClass); + } + + private native int remapInstructionOperandFromCPCache0(Class aClass, int index); + public int remapInstructionOperandFromCPCache(Class aClass, int index) { + Objects.requireNonNull(aClass); + return remapInstructionOperandFromCPCache0(aClass, index); + } + + private native int encodeConstantPoolIndyIndex0(int index); + public int encodeConstantPoolIndyIndex(int index) { + return encodeConstantPoolIndyIndex0(index); + } + // JVMTI private native void addToBootstrapClassLoaderSearch0(String segment); public void addToBootstrapClassLoaderSearch(String segment){ @@ -185,7 +207,7 @@ // Compiler public native int matchesMethod(Executable method, String pattern); public native int matchesInline(Executable method, String pattern); - public native boolean shouldPrintAssembly(Executable method); + public native boolean shouldPrintAssembly(Executable method, int comp_level); public native int deoptimizeFrames(boolean makeNotEntrant); public native void deoptimizeAll();