# HG changeset patch # User herrick # Date 1549310429 18000 # Node ID e7ba8c89abe755eaadb058fc34cd407feed30ec8 # Parent 3dcb33ce7ced09fd4d60174c42629ae0fdfc8084# Parent 53c72d9d962b30a6e3a2211a265f6ae8c3788506 Merge diff -r 3dcb33ce7ced -r e7ba8c89abe7 .hgtags --- a/.hgtags Sun Feb 03 08:16:08 2019 -0500 +++ b/.hgtags Mon Feb 04 15:00:29 2019 -0500 @@ -538,3 +538,5 @@ 659b004b6a1bd8c31e766cbdf328d8f8473fd4d7 jdk-12+28 e3ed960609927b5fdfd0a797159835cd83a81a31 jdk-13+5 44f41693631f9b5ac78ff4d2bfabd6734fe46df2 jdk-12+29 +b5f05fe4a6f8b3996a000c20078b356d991ca8ec jdk-13+6 +6c377af36a5c4203f16aed8a5e4c2ecc08fcd8bd jdk-12+30 diff -r 3dcb33ce7ced -r e7ba8c89abe7 make/GenerateLinkOptData.gmk --- a/make/GenerateLinkOptData.gmk Sun Feb 03 08:16:08 2019 -0500 +++ b/make/GenerateLinkOptData.gmk Mon Feb 04 15:00:29 2019 -0500 @@ -59,6 +59,8 @@ INTERIM_IMAGE_DIR := $(BUILD_JDK) endif +# Save the stderr output of the command and print it along with stdout in case +# something goes wrong. $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR) $(call MakeDir, $(LINK_OPT_DIR)) $(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@)) @@ -67,7 +69,14 @@ -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \ -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \ build.tools.classlist.HelloClasslist \ - $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE) + 2> $(LINK_OPT_DIR)/stderr > $(JLI_TRACE_FILE) \ + || ( \ + exitcode=$$? ; \ + $(ECHO) "ERROR: Failed to generate link optimization data." \ + "This is likely a problem with the newly built JVM/JDK." ; \ + $(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \ + exit $$exitcode \ + ) $(GREP) -v HelloClasslist $@.raw > $@ # The jli trace is created by the same recipe as classlist. By declaring these diff -r 3dcb33ce7ced -r e7ba8c89abe7 make/autoconf/build-performance.m4 --- a/make/autoconf/build-performance.m4 Sun Feb 03 08:16:08 2019 -0500 +++ b/make/autoconf/build-performance.m4 Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. # 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,11 @@ NUM_CORES=`/usr/sbin/sysctl -n hw.ncpu` FOUND_CORES=yes elif test "x$OPENJDK_BUILD_OS" = xaix ; then - NUM_CORES=`/usr/sbin/prtconf | grep "^Number Of Processors" | awk '{ print [$]4 }'` - FOUND_CORES=yes + NUM_LCPU=`lparstat -m 2> /dev/null | $GREP -o "lcpu=[[0-9]]*" | $CUT -d "=" -f 2` + if test -n "$NUM_LCPU"; then + NUM_CORES=$NUM_LCPU + FOUND_CORES=yes + fi elif test -n "$NUMBER_OF_PROCESSORS"; then # On windows, look in the env NUM_CORES=$NUMBER_OF_PROCESSORS diff -r 3dcb33ce7ced -r e7ba8c89abe7 make/autoconf/lib-freetype.m4 --- a/make/autoconf/lib-freetype.m4 Sun Feb 03 08:16:08 2019 -0500 +++ b/make/autoconf/lib-freetype.m4 Mon Feb 04 15:00:29 2019 -0500 @@ -92,7 +92,7 @@ # This setup is to verify access to system installed freetype header and libraries. # On Windows and MacOS this does not apply and using these options will report an error. - # On other platforms (Linux, Solaris, and perhaps AIX), they will default to using + # On other platforms (Linux, Solaris), they will default to using # the system libraries. If they are found automatically, nothing need be done. # If they are not found, the configure "--with-freetype-*" options may be used to fix that. # If the preference is to bundle on these platforms then use --with-freetype=bundled @@ -106,7 +106,8 @@ fi FREETYPE_TO_USE=bundled - if (test "x$OPENJDK_TARGET_OS" != "xwindows" && test "x$OPENJDK_TARGET_OS" != "xmacosx"); then + if (test "x$OPENJDK_TARGET_OS" != "xwindows" && test "x$OPENJDK_TARGET_OS" != "xmacosx" \ + && test "x$OPENJDK_TARGET_OS" != "xaix"); then FREETYPE_TO_USE=system fi if (test "x$with_freetype" != "x"); then diff -r 3dcb33ce7ced -r e7ba8c89abe7 make/conf/jib-profiles.js --- a/make/conf/jib-profiles.js Sun Feb 03 08:16:08 2019 -0500 +++ b/make/conf/jib-profiles.js Mon Feb 04 15:00:29 2019 -0500 @@ -861,7 +861,7 @@ var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { - linux_x64: "gcc7.3.0-OEL6.4+1.2", + linux_x64: "gcc7.3.0-OEL6.4+1.1", macosx_x64: "Xcode9.4-MacOSX10.13+1.0", solaris_x64: "SS12u4-Solaris11u1+1.0", solaris_sparcv9: "SS12u6-Solaris11u3+1.0", diff -r 3dcb33ce7ced -r e7ba8c89abe7 make/data/lsrdata/language-subtag-registry.txt --- a/make/data/lsrdata/language-subtag-registry.txt Sun Feb 03 08:16:08 2019 -0500 +++ b/make/data/lsrdata/language-subtag-registry.txt Mon Feb 04 15:00:29 2019 -0500 @@ -1,4 +1,4 @@ -File-Date: 2018-10-31 +File-Date: 2018-11-30 %% Type: language Subtag: aa @@ -593,6 +593,7 @@ Type: language Subtag: lg Description: Ganda +Description: Luganda Added: 2005-10-16 %% Type: language diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/aarch64/frame_aarch64.cpp --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -34,7 +34,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/monitorChunk.hpp" -#include "runtime/os.hpp" +#include "runtime/os.inline.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/aarch64/templateTable_aarch64.cpp --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -2720,7 +2720,7 @@ { Label notVolatile; __ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); - __ membar(MacroAssembler::StoreStore); + __ membar(MacroAssembler::StoreStore | MacroAssembler::LoadStore); __ bind(notVolatile); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/arm/frame_arm.cpp --- a/src/hotspot/cpu/arm/frame_arm.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/arm/frame_arm.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -32,6 +32,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/monitorChunk.hpp" +#include "runtime/os.inline.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/ppc/frame_ppc.cpp --- a/src/hotspot/cpu/ppc/frame_ppc.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -34,6 +34,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/monitorChunk.hpp" +#include "runtime/os.inline.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/s390/frame_s390.cpp --- a/src/hotspot/cpu/s390/frame_s390.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/s390/frame_s390.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -32,6 +32,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/monitorChunk.hpp" +#include "runtime/os.inline.hpp" #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/sparc/stubGenerator_sparc.cpp --- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -4219,7 +4219,7 @@ // save F48:F54 in temp registers __ movdtox(F54,G2); __ movdtox(F52,G3); - __ movdtox(F50,G6); + __ movdtox(F50,L6); __ movdtox(F48,G1); for ( int i = 46; i >= 14; i -= 8 ) { __ aes_dround23(as_FloatRegister(i), F0, F2, F4); @@ -4247,7 +4247,7 @@ // re-init F48:F54 with their original values __ movxtod(G2,F54); __ movxtod(G3,F52); - __ movxtod(G6,F50); + __ movxtod(L6,F50); __ movxtod(G1,F48); __ movxtod(L0,F6); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/cpu/zero/cppInterpreter_zero.cpp --- a/src/hotspot/cpu/zero/cppInterpreter_zero.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/cpu/zero/cppInterpreter_zero.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -41,6 +41,7 @@ #include "runtime/atomic.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/orderAccess.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -561,8 +561,7 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Aix::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); - print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4); + print_instructions(st, pc, /*instrsize=*/4); st->cr(); // Try to decode the instructions. diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1021,8 +1021,8 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Bsd::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" INTPTR_FORMAT ")", (intptr_t)pc); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); + st->cr(); } void os::print_register_info(outputStream *st, const void *context) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -606,8 +606,8 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Linux::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); + st->cr(); } void os::print_register_info(outputStream *st, const void *context) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -543,8 +543,8 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Linux::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" INTPTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc - 32, pc + 32, Assembler::InstructionSize); + print_instructions(st, pc, Assembler::InstructionSize); + st->cr(); } void os::print_register_info(outputStream *st, const void *context) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -574,8 +574,7 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Linux::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4); + print_instructions(st, pc, /*instrsize=*/4); st->cr(); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -605,9 +605,7 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Linux::ucontext_get_pc(uc); - if (Verbose) { st->print_cr("pc at " PTR_FORMAT, p2i(pc)); } - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc-64, pc+64, /*intrsize=*/4); + print_instructions(st, pc, /*intrsize=*/4); st->cr(); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp --- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -232,8 +232,8 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Linux::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" INTPTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); + st->cr(); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -755,8 +755,8 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = os::Linux::ucontext_get_pc(uc); - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc)); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); + st->cr(); } void os::print_register_info(outputStream *st, const void *context) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp --- a/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -655,8 +655,8 @@ // this at the end, and hope for the best. ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc); address pc = epc.pc(); - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); + st->cr(); } void os::print_register_info(outputStream *st, const void *context) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp --- a/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -779,8 +779,8 @@ // this at the end, and hope for the best. ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc); address pc = epc.pc(); - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); + st->cr(); } void os::print_register_info(outputStream *st, const void *context) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -585,8 +585,7 @@ // point to garbage if entry point in an nmethod is corrupted. Leave // this at the end, and hope for the best. address pc = (address)uc->REG_PC; - st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); - print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); + print_instructions(st, pc, sizeof(char)); st->cr(); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/aot/aotLoader.cpp --- a/src/hotspot/share/aot/aotLoader.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/aot/aotLoader.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include "memory/allocation.inline.hpp" #include "oops/method.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/os.hpp" +#include "runtime/os.inline.hpp" #include "runtime/timerTrace.hpp" GrowableArray* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (2, true); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/c1/c1_GraphBuilder.cpp --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1942,7 +1942,8 @@ // Use CHA on the receiver to select a more precise method. cha_monomorphic_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv); } else if (code == Bytecodes::_invokeinterface && callee_holder->is_loaded() && receiver != NULL) { - // if there is only one implementor of this interface then we + assert(callee_holder->is_interface(), "invokeinterface to non interface?"); + // If there is only one implementor of this interface then we // may be able bind this invoke directly to the implementing // klass but we need both a dependence on the single interface // and on the method we bind to. Additionally since all we know @@ -1950,53 +1951,44 @@ // interface we have to insert a check that it's the class we // expect. Interface types are not checked by the verifier so // they are roughly equivalent to Object. + // The number of implementors for declared_interface is less or + // equal to the number of implementors for target->holder() so + // if number of implementors of target->holder() == 1 then + // number of implementors for decl_interface is 0 or 1. If + // it's 0 then no class implements decl_interface and there's + // no point in inlining. ciInstanceKlass* singleton = NULL; - if (target->holder()->nof_implementors() == 1) { - singleton = target->holder()->implementor(); - assert(singleton != NULL && singleton != target->holder(), - "just checking"); - - assert(holder->is_interface(), "invokeinterface to non interface?"); - ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; - // the number of implementors for decl_interface is less or - // equal to the number of implementors for target->holder() so - // if number of implementors of target->holder() == 1 then - // number of implementors for decl_interface is 0 or 1. If - // it's 0 then no class implements decl_interface and there's - // no point in inlining. - if (!holder->is_loaded() || decl_interface->nof_implementors() != 1 || decl_interface->has_nonstatic_concrete_methods()) { - singleton = NULL; - } - } - if (singleton) { - cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton); + ciInstanceKlass* declared_interface = callee_holder; + if (declared_interface->nof_implementors() == 1 && + (!target->is_default_method() || target->is_overpass()) /* CHA doesn't support default methods yet. */) { + singleton = declared_interface->implementor(); + assert(singleton != NULL && singleton != declared_interface, ""); + cha_monomorphic_target = target->find_monomorphic_target(calling_klass, declared_interface, singleton); if (cha_monomorphic_target != NULL) { - // If CHA is able to bind this invoke then update the class - // to match that class, otherwise klass will refer to the - // interface. - klass = cha_monomorphic_target->holder(); - actual_recv = target->holder(); - - // insert a check it's really the expected class. - CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); - c->set_incompatible_class_change_check(); - c->set_direct_compare(klass->is_final()); - // pass the result of the checkcast so that the compiler has - // more accurate type info in the inlinee - better_receiver = append_split(c); + if (cha_monomorphic_target->holder() != compilation()->env()->Object_klass()) { + // If CHA is able to bind this invoke then update the class + // to match that class, otherwise klass will refer to the + // interface. + klass = cha_monomorphic_target->holder(); + actual_recv = declared_interface; + + // insert a check it's really the expected class. + CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); + c->set_incompatible_class_change_check(); + c->set_direct_compare(klass->is_final()); + // pass the result of the checkcast so that the compiler has + // more accurate type info in the inlinee + better_receiver = append_split(c); + } else { + cha_monomorphic_target = NULL; // subtype check against Object is useless + } } } } } if (cha_monomorphic_target != NULL) { - if (cha_monomorphic_target->is_abstract()) { - // Do not optimize for abstract methods - cha_monomorphic_target = NULL; - } - } - - if (cha_monomorphic_target != NULL) { + assert(!cha_monomorphic_target->is_abstract(), ""); if (!(target->is_final_method())) { // If we inlined because CHA revealed only a single target method, // then we are dependent on that target method not getting overridden diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/c1/c1_Runtime1.cpp --- a/src/hotspot/share/c1/c1_Runtime1.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/c1/c1_Runtime1.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * 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,6 +57,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/sharedRuntime.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/ci/ciEnv.cpp --- a/src/hotspot/share/ci/ciEnv.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/ci/ciEnv.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -55,6 +55,7 @@ #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/reflection.hpp" #include "runtime/jniHandles.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/ci/ciInstanceKlass.hpp --- a/src/hotspot/share/ci/ciInstanceKlass.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/ci/ciInstanceKlass.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -72,7 +72,7 @@ // The possible values of the _implementor fall into following three cases: // NULL: no implementor. // A ciInstanceKlass that's not itself: one implementor. - // Itsef: more than one implementors. + // Itself: more than one implementor. ciInstanceKlass* _implementor; void compute_injected_fields(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/ci/ciMethod.cpp --- a/src/hotspot/share/ci/ciMethod.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/ci/ciMethod.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -46,6 +46,7 @@ #include "oops/oop.inline.hpp" #include "prims/nativeLookup.hpp" #include "runtime/deoptimization.hpp" +#include "runtime/handles.inline.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/xmlstream.hpp" #ifdef COMPILER2 @@ -89,6 +90,7 @@ _is_c2_compilable = !h_m()->is_not_c2_compilable(); _can_be_parsed = true; _has_reserved_stack_access = h_m()->has_reserved_stack_access(); + _is_overpass = h_m()->is_overpass(); // Lazy fields, filled in on demand. Require allocation. _code = NULL; _exception_handlers = NULL; @@ -718,7 +720,7 @@ VM_ENTRY_MARK; // Disable CHA for default methods for now - if (root_m->get_Method()->is_default_method()) { + if (root_m->is_default_method()) { return NULL; } @@ -758,6 +760,7 @@ // with the same name but different vtable indexes. return NULL; } + assert(!target()->is_abstract(), "not allowed"); return CURRENT_THREAD_ENV->get_method(target()); } @@ -874,6 +877,14 @@ } // ------------------------------------------------------------------ +ciKlass* ciMethod::get_declared_method_holder_at_bci(int bci) { + ciBytecodeStream iter(this); + iter.reset_to_bci(bci); + iter.next(); + return iter.get_declared_method_holder(); +} + +// ------------------------------------------------------------------ // Adjust a CounterData count to be commensurate with // interpreter_invocation_count. If the MDO exists for // only 25% of the time the method exists, then the diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/ci/ciMethod.hpp --- a/src/hotspot/share/ci/ciMethod.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/ci/ciMethod.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -89,6 +89,7 @@ bool _can_be_parsed; bool _can_be_statically_bound; bool _has_reserved_stack_access; + bool _is_overpass; // Lazy fields, filled in on demand address _code; @@ -265,6 +266,8 @@ return get_method_at_bci(bci, ignored_will_link, &ignored_declared_signature); } + ciKlass* get_declared_method_holder_at_bci(int bci); + ciSignature* get_declared_signature_at_bci(int bci) { bool ignored_will_link; ciSignature* declared_signature; @@ -333,6 +336,9 @@ bool is_empty_method() const; bool is_vanilla_constructor() const; bool is_final_method() const { return is_final() || holder()->is_final(); } + bool is_default_method() const { return !is_abstract() && !is_private() && + holder()->is_interface(); } + bool is_overpass () const { check_is_loaded(); return _is_overpass; } bool has_loops () const; bool has_jsrs () const; bool is_getter () const; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/ci/ciReplay.cpp --- a/src/hotspot/share/ci/ciReplay.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/ci/ciReplay.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * 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 "oops/method.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/fieldDescriptor.inline.hpp" +#include "runtime/handles.inline.hpp" #include "utilities/copy.hpp" #include "utilities/macros.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/ci/ciStreams.cpp --- a/src/hotspot/share/ci/ciStreams.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/ci/ciStreams.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -315,18 +315,7 @@ // If this is a method invocation bytecode, get the constant pool // index of the invoked method. int ciBytecodeStream::get_method_index() { -#ifdef ASSERT - switch (cur_bc()) { - case Bytecodes::_invokeinterface: - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: - case Bytecodes::_invokestatic: - case Bytecodes::_invokedynamic: - break; - default: - ShouldNotReachHere(); - } -#endif + assert(Bytecodes::is_invoke(cur_bc()), "invalid bytecode: %s", Bytecodes::name(cur_bc())); if (has_index_u4()) return get_index_u4(); // invokedynamic return get_index_u2_cpcache(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/classLoader.cpp --- a/src/hotspot/share/classfile/classLoader.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/classLoader.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -56,7 +56,6 @@ #include "prims/jvm_misc.hpp" #include "runtime/arguments.hpp" #include "runtime/compilationPolicy.hpp" -#include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/dictionary.cpp --- a/src/hotspot/share/classfile/dictionary.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/dictionary.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,41 +198,6 @@ } } -// During class loading we may have cached a protection domain that has -// since been unreferenced, so this entry should be cleared. -void Dictionary::clean_cached_protection_domains(DictionaryEntry* probe) { - assert_locked_or_safepoint(SystemDictionary_lock); - - ProtectionDomainEntry* current = probe->pd_set(); - ProtectionDomainEntry* prev = NULL; - while (current != NULL) { - if (current->object_no_keepalive() == NULL) { - LogTarget(Debug, protectiondomain) lt; - if (lt.is_enabled()) { - ResourceMark rm; - // Print out trace information - LogStream ls(lt); - ls.print_cr("PD in set is not alive:"); - ls.print("class loader: "); loader_data()->class_loader()->print_value_on(&ls); - ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls); - ls.cr(); - } - if (probe->pd_set() == current) { - probe->set_pd_set(current->next()); - } else { - assert(prev != NULL, "should be set by alive entry"); - prev->set_next(current->next()); - } - ProtectionDomainEntry* to_delete = current; - current = current->next(); - delete to_delete; - } else { - prev = current; - current = current->next(); - } - } -} - // Just the classes from defining class loaders void Dictionary::classes_do(void f(InstanceKlass*)) { for (int index = 0; index < table_size(); index++) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/dictionary.hpp --- a/src/hotspot/share/classfile/dictionary.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/dictionary.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -51,8 +51,6 @@ DictionaryEntry* get_entry(int index, unsigned int hash, Symbol* name); - void clean_cached_protection_domains(DictionaryEntry* probe); - public: Dictionary(ClassLoaderData* loader_data, int table_size, bool resizable = false); Dictionary(ClassLoaderData* loader_data, int table_size, HashtableBucket* t, int number_of_entries, bool resizable = false); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/stringTable.cpp --- a/src/hotspot/share/classfile/stringTable.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/stringTable.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -468,7 +468,7 @@ if ((dead_factor > load_factor) || (load_factor > PREF_AVG_LIST_LEN) || (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) { - log_debug(stringtable)("Concurrent work triggered, live factor:%g dead factor:%g", + log_debug(stringtable)("Concurrent work triggered, live factor: %g dead factor: %g", load_factor, dead_factor); trigger_concurrent_work(); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/symbolTable.cpp --- a/src/hotspot/share/classfile/symbolTable.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/symbolTable.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,10 +49,6 @@ const size_t END_SIZE = 17; // If a chain gets to 100 something might be wrong const size_t REHASH_LEN = 100; -// We only get a chance to check whether we need -// to clean infrequently (on class unloading), -// so if we have even one dead entry then mark table for cleaning -const double CLEAN_DEAD_HIGH_WATER_MARK = 0.0; const size_t ON_STACK_BUFFER_LENGTH = 128; @@ -142,7 +138,7 @@ SymbolTable::SymbolTable() : _symbols_removed(0), _symbols_counted(0), _local_table(NULL), _current_size(0), _has_work(0), _needs_rehashing(false), - _items_count(0), _uncleaned_items_count(0) { + _items_count(0), _has_items_to_clean(false) { size_t start_size_log_2 = ceil_log2(SymbolTableSize); _current_size = ((size_t)1) << start_size_log_2; @@ -171,22 +167,14 @@ } } +void SymbolTable::reset_has_items_to_clean() { Atomic::store(false, &_has_items_to_clean); } +void SymbolTable::mark_has_items_to_clean() { Atomic::store(true, &_has_items_to_clean); } +bool SymbolTable::has_items_to_clean() const { return Atomic::load(&_has_items_to_clean); } + void SymbolTable::item_added() { Atomic::inc(&(SymbolTable::the_table()->_items_count)); } -void SymbolTable::set_item_clean_count(size_t ncl) { - Atomic::store(ncl, &(SymbolTable::the_table()->_uncleaned_items_count)); - log_trace(symboltable)("Set uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count); -} - -// Mark one item as needing to be cleaned, but only if no other items are marked yet -void SymbolTable::mark_item_clean_count() { - if (Atomic::cmpxchg((size_t)1, &(SymbolTable::the_table()->_uncleaned_items_count), (size_t)0) == 0) { - log_trace(symboltable)("Marked uncleaned items:" SIZE_FORMAT, SymbolTable::the_table()->_uncleaned_items_count); - } -} - void SymbolTable::item_removed() { Atomic::inc(&(SymbolTable::the_table()->_symbols_removed)); Atomic::dec(&(SymbolTable::the_table()->_items_count)); @@ -196,15 +184,11 @@ return (double)_items_count/_current_size; } -double SymbolTable::get_dead_factor() const { - return (double)_uncleaned_items_count/_current_size; -} - size_t SymbolTable::table_size() { return ((size_t)1) << _local_table->get_size_log2(Thread::current()); } -void SymbolTable::trigger_concurrent_work() { +void SymbolTable::trigger_cleanup() { MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); SymbolTable::the_table()->_has_work = true; Service_lock->notify_all(); @@ -490,12 +474,7 @@ update_needs_rehash(rehash_warning); if (clean_hint) { - // we just found out that there is a dead item, - // which we were unable to clean right now, - // but we have no way of telling whether it's - // been previously counted or not, so mark - // it only if no other items were found yet - mark_item_clean_count(); + mark_has_items_to_clean(); check_concurrent_work(); } @@ -697,7 +676,7 @@ } bdt.cont(jt); } - SymbolTable::the_table()->set_item_clean_count(0); + SymbolTable::the_table()->reset_has_items_to_clean(); bdt.done(jt); } @@ -711,17 +690,13 @@ if (_has_work) { return; } - double load_factor = SymbolTable::get_load_factor(); - double dead_factor = SymbolTable::get_dead_factor(); - // We should clean/resize if we have more dead than alive, + // We should clean/resize if we have // more items than preferred load factor or // more dead items than water mark. - if ((dead_factor > load_factor) || - (load_factor > PREF_AVG_LIST_LEN) || - (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) { - log_debug(symboltable)("Concurrent work triggered, live factor:%f dead factor:%f", - load_factor, dead_factor); - trigger_concurrent_work(); + if (has_items_to_clean() || (get_load_factor() > PREF_AVG_LIST_LEN)) { + log_debug(symboltable)("Concurrent work triggered, load factor: %f, items to clean: %s", + get_load_factor(), has_items_to_clean() ? "true" : "false"); + trigger_cleanup(); } } @@ -737,34 +712,6 @@ _has_work = false; } -class CountDead : StackObj { - size_t _count; -public: - CountDead() : _count(0) {} - bool operator()(Symbol** value) { - assert(value != NULL, "expected valid value"); - assert(*value != NULL, "value should point to a symbol"); - Symbol* sym = *value; - if (sym->refcount() == 0) { - _count++; - } - return true; - }; - size_t get_dead_count() const { - return _count; - } -}; - -void SymbolTable::do_check_concurrent_work() { - CountDead counter; - if (!SymbolTable::the_table()->_local_table->try_scan(Thread::current(), counter)) { - log_info(symboltable)("count dead unavailable at this moment"); - } else { - SymbolTable::the_table()->set_item_clean_count(counter.get_dead_count()); - SymbolTable::the_table()->check_concurrent_work(); - } -} - void SymbolTable::do_concurrent_work(JavaThread* jt) { SymbolTable::the_table()->concurrent_work(jt); } @@ -800,7 +747,7 @@ if (get_load_factor() > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { log_debug(symboltable)("Choosing growing over rehashing."); - trigger_concurrent_work(); + trigger_cleanup(); _needs_rehashing = false; return; } @@ -808,7 +755,7 @@ // Already rehashed. if (rehashed) { log_warning(symboltable)("Rehashing already done, still long lists."); - trigger_concurrent_work(); + trigger_cleanup(); _needs_rehashing = false; return; } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/symbolTable.hpp --- a/src/hotspot/share/classfile/symbolTable.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/symbolTable.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -123,18 +123,19 @@ volatile bool _needs_rehashing; volatile size_t _items_count; - volatile size_t _uncleaned_items_count; + volatile bool _has_items_to_clean; double get_load_factor() const; - double get_dead_factor() const; void check_concurrent_work(); - void trigger_concurrent_work(); static void item_added(); static void item_removed(); - static void set_item_clean_count(size_t ncl); - static void mark_item_clean_count(); + + // For cleaning + void reset_has_items_to_clean(); + void mark_has_items_to_clean(); + bool has_items_to_clean() const; SymbolTable(); @@ -190,12 +191,9 @@ initialize_symbols(symbol_alloc_arena_size); } - static void unlink() { - do_check_concurrent_work(); - } - static void do_check_concurrent_work(); static void do_concurrent_work(JavaThread* jt); static bool has_work() { return the_table()->_has_work; } + static void trigger_cleanup(); // Probing static Symbol* lookup(const char* name, int len, TRAPS); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/classfile/systemDictionary.cpp --- a/src/hotspot/share/classfile/systemDictionary.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1825,40 +1825,27 @@ if (unloading_occurred) { MutexLockerEx ml2(is_concurrent ? Module_lock : NULL); JFR_ONLY(Jfr::on_unloading_classes();) + MutexLockerEx ml1(is_concurrent ? SystemDictionary_lock : NULL); ClassLoaderDataGraph::clean_module_and_package_info(); - } - } - - // Cleanup ResolvedMethodTable even if no unloading occurred. - { - GCTraceTime(Debug, gc, phases) t("ResolvedMethodTable", gc_timer); - ResolvedMethodTable::trigger_cleanup(); - } - - if (unloading_occurred) { - { - GCTraceTime(Debug, gc, phases) t("SymbolTable", gc_timer); - // Check if there's work to do in the SymbolTable - SymbolTable::do_check_concurrent_work(); - } - - { - MutexLockerEx ml(is_concurrent ? SystemDictionary_lock : NULL); - GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer); constraints()->purge_loader_constraints(); resolution_errors()->purge_resolution_errors(); } - - { - GCTraceTime(Debug, gc, phases) t("ResolvedMethodTable", gc_timer); - // Oops referenced by the protection domain cache table may get unreachable independently - // of the class loader (eg. cached protection domain oops). So we need to - // explicitly unlink them here. - // All protection domain oops are linked to the caller class, so if nothing - // unloads, this is not needed. - _pd_cache_table->trigger_cleanup(); - } + } + + GCTraceTime(Debug, gc, phases) t("Trigger cleanups", gc_timer); + // Trigger cleaning the ResolvedMethodTable even if no unloading occurred. + ResolvedMethodTable::trigger_cleanup(); + + if (unloading_occurred) { + SymbolTable::trigger_cleanup(); + + // Oops referenced by the protection domain cache table may get unreachable independently + // of the class loader (eg. cached protection domain oops). So we need to + // explicitly unlink them here. + // All protection domain oops are linked to the caller class, so if nothing + // unloads, this is not needed. + _pd_cache_table->trigger_cleanup(); } return unloading_occurred; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/compiler/compileBroker.cpp --- a/src/hotspot/share/compiler/compileBroker.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/compiler/compileBroker.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -48,6 +48,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/compilationPolicy.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/compiler/compilerDefinitions.cpp --- a/src/hotspot/share/compiler/compilerDefinitions.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,7 @@ FLAG_SET_ERGO(uintx, CodeCacheExpansionSize, 32*K); } if (FLAG_IS_DEFAULT(MetaspaceSize)) { - FLAG_SET_ERGO(size_t, MetaspaceSize, 12*M); + FLAG_SET_ERGO(size_t, MetaspaceSize, MIN2(12*M, MaxMetaspaceSize)); } if (FLAG_IS_DEFAULT(MaxRAM)) { // Do not use FLAG_SET_ERGO to update MaxRAM, as this will impact @@ -264,7 +264,7 @@ FLAG_SET_DEFAULT(InitialCodeCacheSize, MAX2(16*M, InitialCodeCacheSize)); } if (FLAG_IS_DEFAULT(MetaspaceSize)) { - FLAG_SET_DEFAULT(MetaspaceSize, MAX2(12*M, MetaspaceSize)); + FLAG_SET_DEFAULT(MetaspaceSize, MIN2(MAX2(12*M, MetaspaceSize), MaxMetaspaceSize)); } if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) { FLAG_SET_DEFAULT(NewSizeThreadIncrease, MAX2(4*K, NewSizeThreadIncrease)); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -5269,12 +5269,6 @@ // Prune dead klasses from subklass/sibling/implementor lists. Klass::clean_weak_klass_links(purged_class); } - - { - GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", _gc_timer_cm); - // Clean up unreferenced symbols in symbol table. - SymbolTable::unlink(); - } } // Restore any preserved marks as a result of mark stack or diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/cms/parNewGeneration.cpp --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -59,7 +59,6 @@ #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" -#include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/thread.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/g1/g1ConcurrentMark.cpp --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -588,7 +588,7 @@ _num_active_tasks = active_tasks; // Need to update the three data structures below according to the // number of active threads for this phase. - _terminator = TaskTerminator((int) active_tasks, _task_queues); + _terminator.terminator()->reset_for_reuse((int) active_tasks); _first_overflow_barrier_sync.set_n_workers((int) active_tasks); _second_overflow_barrier_sync.set_n_workers((int) active_tasks); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/parallel/psMarkSweep.cpp --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -566,12 +566,6 @@ Klass::clean_weak_klass_links(purged_class); } - { - GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", _gc_timer); - // Clean up unreferenced symbols in symbol table. - SymbolTable::unlink(); - } - _gc_tracer->report_object_count_after_gc(is_alive_closure()); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/parallel/psParallelCompact.cpp --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -2184,12 +2184,6 @@ Klass::clean_weak_klass_links(purged_class); } - { - GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", &_gc_timer); - // Clean up unreferenced symbols in symbol table. - SymbolTable::unlink(); - } - _gc_tracer.report_object_count_after_gc(is_alive_closure()); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/serial/genMarkSweep.cpp --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -239,12 +239,6 @@ Klass::clean_weak_klass_links(purged_class); } - { - GCTraceTime(Debug, gc, phases) t("Scrub Symbol Table", gc_timer()); - // Clean up unreferenced symbols in symbol table. - SymbolTable::unlink(); - } - gc_tracer()->report_object_count_after_gc(&is_alive); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/shared/taskqueue.cpp --- a/src/hotspot/share/gc/shared/taskqueue.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/shared/taskqueue.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -281,13 +281,3 @@ } } -// Move assignment -TaskTerminator& TaskTerminator::operator=(const TaskTerminator& o) { - if (_terminator != NULL) { - delete _terminator; - } - _terminator = o.terminator(); - const_cast(o)._terminator = NULL; - return *this; -} - diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/shared/taskqueue.hpp --- a/src/hotspot/share/gc/shared/taskqueue.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/shared/taskqueue.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -510,37 +510,21 @@ #endif }; -#ifdef _MSC_VER -#pragma warning(push) -// warning C4521: multiple copy constructors specified -#pragma warning(disable:4521) -// warning C4522: multiple assignment operators specified -#pragma warning(disable:4522) -#endif - class TaskTerminator : public StackObj { private: ParallelTaskTerminator* _terminator; - // Disable following copy constructors and assignment operator - TaskTerminator(TaskTerminator& o) { } - TaskTerminator(const TaskTerminator& o) { } - TaskTerminator& operator=(TaskTerminator& o) { return *this; } + // Noncopyable. + TaskTerminator(const TaskTerminator&); + TaskTerminator& operator=(const TaskTerminator&); public: TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set); ~TaskTerminator(); - // Move assignment - TaskTerminator& operator=(const TaskTerminator& o); - ParallelTaskTerminator* terminator() const { return _terminator; } }; -#ifdef _MSC_VER -#pragma warning(pop) -#endif - typedef GenericTaskQueue OopTaskQueue; typedef GenericTaskQueueSet OopTaskQueueSet; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -46,6 +46,7 @@ #include "memory/metaspace.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" +#include "runtime/handles.inline.hpp" template class ShenandoahInitMarkRootsClosure : public OopClosure { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -65,6 +65,8 @@ #include "gc/shenandoah/heuristics/shenandoahTraversalHeuristics.hpp" #include "memory/metaspace.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/safepointMechanism.hpp" #include "runtime/vmThread.hpp" #include "services/mallocTracker.hpp" @@ -1863,6 +1865,22 @@ return _free_set->used(); } +bool ShenandoahHeap::try_cancel_gc() { + while (true) { + jbyte prev = _cancelled_gc.cmpxchg(CANCELLED, CANCELLABLE); + if (prev == CANCELLABLE) return true; + else if (prev == CANCELLED) return false; + assert(ShenandoahSuspendibleWorkers, "should not get here when not using suspendible workers"); + assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED"); + { + // We need to provide a safepoint here, otherwise we might + // spin forever if a SP is pending. + ThreadBlockInVM sp(JavaThread::current()); + SpinPause(); + } + } +} + void ShenandoahHeap::cancel_gc(GCCause::Cause cause) { if (try_cancel_gc()) { FormatBuffer<> msg("Cancelling GC: %s", GCCause::to_string(cause)); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Red Hat, Inc. All rights reserved. + * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as @@ -380,7 +380,7 @@ }; ShenandoahSharedEnumFlag _cancelled_gc; - inline bool try_cancel_gc(); + bool try_cancel_gc(); public: static address cancelled_gc_addr(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Red Hat, Inc. All rights reserved. + * Copyright (c) 2015, 2019, Red Hat, Inc. All rights reserved. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as @@ -31,7 +31,6 @@ #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahBrooksPointer.inline.hpp" -#include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" #include "gc/shenandoah/shenandoahWorkGroup.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" @@ -42,8 +41,6 @@ #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" -#include "runtime/interfaceSupport.inline.hpp" -#include "runtime/prefetch.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/thread.hpp" #include "utilities/copy.hpp" @@ -216,22 +213,6 @@ } } -inline bool ShenandoahHeap::try_cancel_gc() { - while (true) { - jbyte prev = _cancelled_gc.cmpxchg(CANCELLED, CANCELLABLE); - if (prev == CANCELLABLE) return true; - else if (prev == CANCELLED) return false; - assert(ShenandoahSuspendibleWorkers, "should not get here when not using suspendible workers"); - assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED"); - { - // We need to provide a safepoint here, otherwise we might - // spin forever if a SP is pending. - ThreadBlockInVM sp(JavaThread::current()); - SpinPause(); - } - } -} - inline void ShenandoahHeap::clear_cancelled_gc() { _cancelled_gc.set(CANCELLABLE); _oom_evac_handler.clear(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/gc/z/zFuture.inline.hpp --- a/src/hotspot/share/gc/z/zFuture.inline.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/gc/z/zFuture.inline.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ #define SHARE_GC_Z_ZFUTURE_INLINE_HPP #include "gc/z/zFuture.hpp" -#include "runtime/interfaceSupport.inline.hpp" #include "runtime/semaphore.inline.hpp" #include "runtime/thread.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp --- a/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ #include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/recorder/repository/jfrChunkRotation.hpp" #include "jfr/recorder/repository/jfrChunkWriter.hpp" +#include "runtime/handles.inline.hpp" static jobject chunk_monitor = NULL; static intptr_t threshold = 0; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * 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,7 +31,7 @@ #include "jfr/utilities/jfrTypes.hpp" #include "memory/resourceArea.hpp" #include "runtime/atomic.hpp" -#include "runtime/handles.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/globals.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp --- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ #include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp" #include "runtime/fieldDescriptor.inline.hpp" -#include "runtime/handles.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/thread.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jvmci/compilerRuntime.cpp --- a/src/hotspot/share/jvmci/compilerRuntime.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jvmci/compilerRuntime.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "aot/aotLoader.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" #include "interpreter/linkResolver.hpp" @@ -29,12 +30,12 @@ #include "oops/cpCache.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/compilationPolicy.hpp" +#include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/deoptimization.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/vframe.inline.hpp" #include "utilities/sizes.hpp" -#include "aot/aotLoader.hpp" // Resolve and allocate String JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_string_by_symbol(JavaThread *thread, void* string_result, const char* name)) diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jvmci/jvmciCodeInstaller.cpp --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ #include "oops/oop.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jvmci/jvmciCompilerToVM.cpp --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/timerTrace.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/jvmci/jvmciRuntime.cpp --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * 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,6 +42,7 @@ #include "oops/objArrayOop.inline.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/reflection.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/memory/metaspace.cpp --- a/src/hotspot/share/memory/metaspace.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/memory/metaspace.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -132,7 +132,15 @@ return value; } -bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC) { +// Try to increase the _capacity_until_GC limit counter by v bytes. +// Returns true if it succeeded. It may fail if either another thread +// concurrently increased the limit or the new limit would be larger +// than MaxMetaspaceSize. +// On success, optionally returns new and old metaspace capacity in +// new_cap_until_GC and old_cap_until_GC respectively. +// On error, optionally sets can_retry to indicate whether if there is +// actually enough space remaining to satisfy the request. +bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC, bool* can_retry) { assert_is_aligned(v, Metaspace::commit_alignment()); size_t old_capacity_until_GC = _capacity_until_GC; @@ -143,6 +151,16 @@ new_value = align_down(max_uintx, Metaspace::commit_alignment()); } + if (new_value > MaxMetaspaceSize) { + if (can_retry != NULL) { + *can_retry = false; + } + return false; + } + + if (can_retry != NULL) { + *can_retry = true; + } size_t prev_value = Atomic::cmpxchg(new_value, &_capacity_until_GC, old_capacity_until_GC); if (old_capacity_until_GC != prev_value) { @@ -236,7 +254,7 @@ const double min_tmp = used_after_gc / maximum_used_percentage; size_t minimum_desired_capacity = - (size_t)MIN2(min_tmp, double(max_uintx)); + (size_t)MIN2(min_tmp, double(MaxMetaspaceSize)); // Don't shrink less than the initial generation size minimum_desired_capacity = MAX2(minimum_desired_capacity, MetaspaceSize); @@ -283,7 +301,7 @@ const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0; const double minimum_used_percentage = 1.0 - maximum_free_percentage; const double max_tmp = used_after_gc / minimum_used_percentage; - size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); + size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(MaxMetaspaceSize)); maximum_desired_capacity = MAX2(maximum_desired_capacity, MetaspaceSize); log_trace(gc, metaspace)(" maximum_free_percentage: %6.2f minimum_used_percentage: %6.2f", @@ -586,15 +604,15 @@ if (Metaspace::using_class_space()) { out->print(" Non-Class: "); } - print_human_readable_size(out, Metaspace::chunk_manager_metadata()->free_chunks_total_words(), scale); + print_human_readable_size(out, Metaspace::chunk_manager_metadata()->free_chunks_total_bytes(), scale); out->cr(); if (Metaspace::using_class_space()) { out->print(" Class: "); - print_human_readable_size(out, Metaspace::chunk_manager_class()->free_chunks_total_words(), scale); + print_human_readable_size(out, Metaspace::chunk_manager_class()->free_chunks_total_bytes(), scale); out->cr(); out->print(" Both: "); - print_human_readable_size(out, Metaspace::chunk_manager_class()->free_chunks_total_words() + - Metaspace::chunk_manager_metadata()->free_chunks_total_words(), scale); + print_human_readable_size(out, Metaspace::chunk_manager_class()->free_chunks_total_bytes() + + Metaspace::chunk_manager_metadata()->free_chunks_total_bytes(), scale); out->cr(); } out->cr(); @@ -1470,6 +1488,7 @@ size_t before = 0; size_t after = 0; + bool can_retry = true; MetaWord* res; bool incremented; @@ -1477,9 +1496,9 @@ // the HWM, an allocation is still attempted. This is because another thread must then // have incremented the HWM and therefore the allocation might still succeed. do { - incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before); + incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before, &can_retry); res = allocate(word_size, mdtype); - } while (!incremented && res == NULL); + } while (!incremented && res == NULL && can_retry); if (incremented) { Metaspace::tracer()->report_gc_threshold(before, after, diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/memory/metaspace.hpp --- a/src/hotspot/share/memory/metaspace.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/memory/metaspace.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -457,7 +457,8 @@ static size_t capacity_until_GC(); static bool inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC = NULL, - size_t* old_cap_until_GC = NULL); + size_t* old_cap_until_GC = NULL, + bool* can_retry = NULL); static size_t dec_capacity_until_GC(size_t v); static bool should_concurrent_collect() { return _should_concurrent_collect; } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/oops/constMethod.cpp --- a/src/hotspot/share/oops/constMethod.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/oops/constMethod.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -426,7 +426,6 @@ void ConstMethod::print_on(outputStream* st) const { ResourceMark rm; - assert(is_constMethod(), "must be constMethod"); st->print_cr("%s", internal_name()); Method* m = method(); st->print(" - method: " INTPTR_FORMAT " ", p2i((address)m)); @@ -444,7 +443,6 @@ // Short version of printing ConstMethod* - just print the name of the // method it belongs to. void ConstMethod::print_value_on(outputStream* st) const { - assert(is_constMethod(), "must be constMethod"); st->print(" const part of method " ); Method* m = method(); if (m != NULL) { @@ -487,8 +485,6 @@ // Verification void ConstMethod::verify_on(outputStream* st) { - guarantee(is_constMethod(), "object must be constMethod"); - // Verification can occur during oop construction before the method or // other fields have been initialized. guarantee(method() != NULL && method()->is_method(), "should be method"); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/oops/constMethod.hpp --- a/src/hotspot/share/oops/constMethod.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/oops/constMethod.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -241,8 +241,6 @@ MethodType mt, TRAPS); - bool is_constMethod() const { return true; } - // Inlined tables void set_inlined_tables_length(InlineTableSizes* sizes); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/oops/constantPool.cpp --- a/src/hotspot/share/oops/constantPool.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/oops/constantPool.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -52,6 +52,7 @@ #include "runtime/init.hpp" #include "runtime/javaCalls.hpp" #include "runtime/signature.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.inline.hpp" #include "utilities/copy.hpp" @@ -2523,11 +2524,6 @@ guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count"); } } - if (cache() != NULL) { - // Note: cache() can be NULL before a class is completely setup or - // in temporary constant pools used during constant pool merging - guarantee(cache()->is_constantPoolCache(), "should be constant pool cache"); - } if (pool_holder() != NULL) { // Note: pool_holder() can be NULL in temporary constant pools // used during constant pool merging diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/oops/cpCache.cpp --- a/src/hotspot/share/oops/cpCache.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/oops/cpCache.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -851,14 +851,12 @@ // Printing void ConstantPoolCache::print_on(outputStream* st) const { - assert(is_constantPoolCache(), "obj must be constant pool cache"); st->print_cr("%s", internal_name()); // print constant pool cache entries for (int i = 0; i < length(); i++) entry_at(i)->print(st, i); } void ConstantPoolCache::print_value_on(outputStream* st) const { - assert(is_constantPoolCache(), "obj must be constant pool cache"); st->print("cache [%d]", length()); print_address_on(st); st->print(" for "); @@ -869,7 +867,6 @@ // Verification void ConstantPoolCache::verify_on(outputStream* st) { - guarantee(is_constantPoolCache(), "obj must be constant pool cache"); // print constant pool cache entries for (int i = 0; i < length(); i++) entry_at(i)->verify(st); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/oops/cpCache.hpp --- a/src/hotspot/share/oops/cpCache.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/oops/cpCache.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -444,7 +444,6 @@ const intStack& cp_cache_map, const intStack& invokedynamic_cp_cache_map, const intStack& invokedynamic_references_map, TRAPS); - bool is_constantPoolCache() const { return true; } int length() const { return _length; } void metaspace_pointers_do(MetaspaceClosure* it); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/oops/method.cpp --- a/src/hotspot/share/oops/method.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/oops/method.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -2403,7 +2403,6 @@ void Method::verify_on(outputStream* st) { guarantee(is_method(), "object must be method"); guarantee(constants()->is_constantPool(), "should be constant pool"); - guarantee(constMethod()->is_constMethod(), "should be ConstMethod*"); MethodData* md = method_data(); guarantee(md == NULL || md->is_methodData(), "should be method data"); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/c2_globals.hpp --- a/src/hotspot/share/opto/c2_globals.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/c2_globals.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -516,7 +516,7 @@ "Sets max value cached by the java.lang.Integer autobox cache") \ range(0, max_jint) \ \ - experimental(bool, AggressiveUnboxing, false, \ + experimental(bool, AggressiveUnboxing, true, \ "Control optimizations for aggressive boxing elimination") \ \ develop(bool, TracePostallocExpand, false, "Trace expanding nodes after" \ diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/c2compiler.cpp --- a/src/hotspot/share/opto/c2compiler.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/c2compiler.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ */ #include "precompiled.hpp" +#include "runtime/handles.inline.hpp" #include "jfr/support/jfrIntrinsics.hpp" #include "opto/c2compiler.hpp" #include "opto/compile.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/callGenerator.cpp --- a/src/hotspot/share/opto/callGenerator.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/callGenerator.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -459,7 +459,7 @@ C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops()); C->env()->notice_inlined_method(_inline_cg->method()); C->set_inlining_progress(true); - + C->set_do_cleanup(kit.stopped()); // path is dead; needs cleanup kit.replace_call(call, result, true); } @@ -652,11 +652,13 @@ CallGenerator* _if_missed; CallGenerator* _if_hit; float _hit_prob; + bool _exact_check; public: PredictedCallGenerator(ciKlass* predicted_receiver, CallGenerator* if_missed, - CallGenerator* if_hit, float hit_prob) + CallGenerator* if_hit, bool exact_check, + float hit_prob) : CallGenerator(if_missed->method()) { // The call profile data may predict the hit_prob as extreme as 0 or 1. @@ -668,6 +670,7 @@ _if_missed = if_missed; _if_hit = if_hit; _hit_prob = hit_prob; + _exact_check = exact_check; } virtual bool is_virtual() const { return true; } @@ -682,9 +685,16 @@ CallGenerator* if_missed, CallGenerator* if_hit, float hit_prob) { - return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob); + return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, + /*exact_check=*/true, hit_prob); } +CallGenerator* CallGenerator::for_guarded_call(ciKlass* guarded_receiver, + CallGenerator* if_missed, + CallGenerator* if_hit) { + return new PredictedCallGenerator(guarded_receiver, if_missed, if_hit, + /*exact_check=*/false, PROB_ALWAYS); +} JVMState* PredictedCallGenerator::generate(JVMState* jvms) { GraphKit kit(jvms); @@ -695,8 +705,8 @@ Node* receiver = kit.argument(0); CompileLog* log = kit.C->log(); if (log != NULL) { - log->elem("predicted_call bci='%d' klass='%d'", - jvms->bci(), log->identify(_predicted_receiver)); + log->elem("predicted_call bci='%d' exact='%d' klass='%d'", + jvms->bci(), (_exact_check ? 1 : 0), log->identify(_predicted_receiver)); } receiver = kit.null_check_receiver_before_call(method()); @@ -708,10 +718,15 @@ ReplacedNodes replaced_nodes = kit.map()->replaced_nodes(); replaced_nodes.clone(); - Node* exact_receiver = receiver; // will get updated in place... - Node* slow_ctl = kit.type_check_receiver(receiver, - _predicted_receiver, _hit_prob, - &exact_receiver); + Node* casted_receiver = receiver; // will get updated in place... + Node* slow_ctl = NULL; + if (_exact_check) { + slow_ctl = kit.type_check_receiver(receiver, _predicted_receiver, _hit_prob, + &casted_receiver); + } else { + slow_ctl = kit.subtype_check_receiver(receiver, _predicted_receiver, + &casted_receiver); + } SafePointNode* slow_map = NULL; JVMState* slow_jvms = NULL; @@ -736,7 +751,7 @@ } // fall through if the instance exactly matches the desired type - kit.replace_in_map(receiver, exact_receiver); + kit.replace_in_map(receiver, casted_receiver); // Make the hot call: JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/callGenerator.hpp --- a/src/hotspot/share/opto/callGenerator.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/callGenerator.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -144,6 +144,10 @@ CallGenerator* if_hit, float hit_prob); + static CallGenerator* for_guarded_call(ciKlass* predicted_receiver, + CallGenerator* if_missed, + CallGenerator* if_hit); + // How to make a call that optimistically assumes a MethodHandle target: static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, CallGenerator* if_missed, diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/castnode.cpp --- a/src/hotspot/share/opto/castnode.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/castnode.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -410,11 +410,11 @@ Node* dispX, bool negate = false) { if (negate) { - dispX = new SubXNode(phase->MakeConX(0), phase->transform(dispX)); + dispX = phase->transform(new SubXNode(phase->MakeConX(0), dispX)); } return new AddPNode(phase->C->top(), phase->transform(new CastX2PNode(base)), - phase->transform(dispX)); + dispX); } Node *CastX2PNode::Ideal(PhaseGVN *phase, bool can_reshape) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/cfgnode.hpp --- a/src/hotspot/share/opto/cfgnode.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/cfgnode.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -119,11 +119,13 @@ // can turn PhiNodes into copys in-place by NULL'ing out their RegionNode // input in slot 0. class PhiNode : public TypeNode { + friend class PhaseRenumberLive; + const TypePtr* const _adr_type; // non-null only for Type::MEMORY nodes. // The following fields are only used for data PhiNodes to indicate // that the PhiNode represents the value of a known instance field. int _inst_mem_id; // Instance memory id (node index of the memory Phi) - const int _inst_id; // Instance id of the memory slice. + int _inst_id; // Instance id of the memory slice. const int _inst_index; // Alias index of the instance memory slice. // Array elements references have the same alias_idx but different offset. const int _inst_offset; // Offset of the instance memory slice. diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/compile.cpp --- a/src/hotspot/share/opto/compile.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/compile.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -648,6 +648,7 @@ _orig_pc_slot_offset_in_bytes(0), _inlining_progress(false), _inlining_incrementally(false), + _do_cleanup(false), _has_reserved_stack_access(target->has_reserved_stack_access()), #ifndef PRODUCT _trace_opto_output(directive->TraceOptoOutputOption), @@ -2051,52 +2052,49 @@ } _boxing_late_inlines.trunc_to(0); - { - ResourceMark rm; - PhaseRemoveUseless pru(gvn, for_igvn()); - } - - igvn = PhaseIterGVN(gvn); - igvn.optimize(); - - set_inlining_progress(false); + inline_incrementally_cleanup(igvn); + set_inlining_incrementally(false); } } -void Compile::inline_incrementally_one(PhaseIterGVN& igvn) { +bool Compile::inline_incrementally_one() { assert(IncrementalInline, "incremental inlining should be on"); - PhaseGVN* gvn = initial_gvn(); + + TracePhase tp("incrementalInline_inline", &timers[_t_incrInline_inline]); + set_inlining_progress(false); + set_do_cleanup(false); + int i = 0; + for (; i <_late_inlines.length() && !inlining_progress(); i++) { + CallGenerator* cg = _late_inlines.at(i); + _late_inlines_pos = i+1; + cg->do_late_inline(); + if (failing()) return false; + } + int j = 0; + for (; i < _late_inlines.length(); i++, j++) { + _late_inlines.at_put(j, _late_inlines.at(i)); + } + _late_inlines.trunc_to(j); + assert(inlining_progress() || _late_inlines.length() == 0, ""); + + bool needs_cleanup = do_cleanup() || over_inlining_cutoff(); set_inlining_progress(false); - for_igvn()->clear(); - gvn->replace_with(&igvn); - - { - TracePhase tp("incrementalInline_inline", &timers[_t_incrInline_inline]); - int i = 0; - for (; i <_late_inlines.length() && !inlining_progress(); i++) { - CallGenerator* cg = _late_inlines.at(i); - _late_inlines_pos = i+1; - cg->do_late_inline(); - if (failing()) return; - } - int j = 0; - for (; i < _late_inlines.length(); i++, j++) { - _late_inlines.at_put(j, _late_inlines.at(i)); - } - _late_inlines.trunc_to(j); - } - + set_do_cleanup(false); + return (_late_inlines.length() > 0) && !needs_cleanup; +} + +void Compile::inline_incrementally_cleanup(PhaseIterGVN& igvn) { { TracePhase tp("incrementalInline_pru", &timers[_t_incrInline_pru]); ResourceMark rm; - PhaseRemoveUseless pru(gvn, for_igvn()); + PhaseRemoveUseless pru(initial_gvn(), for_igvn()); } - { TracePhase tp("incrementalInline_igvn", &timers[_t_incrInline_igvn]); - igvn = PhaseIterGVN(gvn); + igvn = PhaseIterGVN(initial_gvn()); + igvn.optimize(); } } @@ -2104,14 +2102,10 @@ void Compile::inline_incrementally(PhaseIterGVN& igvn) { TracePhase tp("incrementalInline", &timers[_t_incrInline]); - PhaseGVN* gvn = initial_gvn(); - set_inlining_incrementally(true); - set_inlining_progress(true); uint low_live_nodes = 0; - while(inlining_progress() && _late_inlines.length() > 0) { - + while (_late_inlines.length() > 0) { if (live_nodes() > (uint)LiveNodeCountInliningCutoff) { if (low_live_nodes < (uint)LiveNodeCountInliningCutoff * 8 / 10) { TracePhase tp("incrementalInline_ideal", &timers[_t_incrInline_ideal]); @@ -2125,22 +2119,23 @@ } if (live_nodes() > (uint)LiveNodeCountInliningCutoff) { - break; + break; // finish } } - inline_incrementally_one(igvn); - - if (failing()) return; - - { - TracePhase tp("incrementalInline_igvn", &timers[_t_incrInline_igvn]); - igvn.optimize(); + for_igvn()->clear(); + initial_gvn()->replace_with(&igvn); + + while (inline_incrementally_one()) { + assert(!failing(), "inconsistent"); } if (failing()) return; + + inline_incrementally_cleanup(igvn); + + if (failing()) return; } - assert( igvn._worklist.size() == 0, "should be done with igvn" ); if (_string_late_inlines.length() > 0) { @@ -2152,17 +2147,7 @@ if (failing()) return; - { - TracePhase tp("incrementalInline_pru", &timers[_t_incrInline_pru]); - ResourceMark rm; - PhaseRemoveUseless pru(initial_gvn(), for_igvn()); - } - - { - TracePhase tp("incrementalInline_igvn", &timers[_t_incrInline_igvn]); - igvn = PhaseIterGVN(gvn); - igvn.optimize(); - } + inline_incrementally_cleanup(igvn); } set_inlining_incrementally(false); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/compile.hpp --- a/src/hotspot/share/opto/compile.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/compile.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -383,6 +383,7 @@ int _major_progress; // Count of something big happening bool _inlining_progress; // progress doing incremental inlining? bool _inlining_incrementally;// Are we doing incremental inlining (post parse) + bool _do_cleanup; // Cleanup is needed before proceeding with incremental inlining bool _has_loops; // True if the method _may_ have some loops bool _has_split_ifs; // True if the method _may_ have some split-if bool _has_unsafe_access; // True if the method _may_ produce faults in unsafe loads or stores. @@ -653,6 +654,8 @@ int inlining_progress() const { return _inlining_progress; } void set_inlining_incrementally(bool z) { _inlining_incrementally = z; } int inlining_incrementally() const { return _inlining_incrementally; } + void set_do_cleanup(bool z) { _do_cleanup = z; } + int do_cleanup() const { return _do_cleanup; } void set_major_progress() { _major_progress++; } void clear_major_progress() { _major_progress = 0; } int max_inline_size() const { return _max_inline_size; } @@ -1022,6 +1025,11 @@ ciMethodData* logmd = NULL); // Report if there were too many recompiles at a method and bci. bool too_many_recompiles(ciMethod* method, int bci, Deoptimization::DeoptReason reason); + // Report if there were too many traps or recompiles at a method and bci. + bool too_many_traps_or_recompiles(ciMethod* method, int bci, Deoptimization::DeoptReason reason) { + return too_many_traps(method, bci, reason) || + too_many_recompiles(method, bci, reason); + } // Return a bitset with the reasons where deoptimization is allowed, // i.e., where there were not too many uncommon traps. int _allowed_reasons; @@ -1075,7 +1083,11 @@ if (!inlining_incrementally()) { return unique() > (uint)NodeCountInliningCutoff; } else { - return live_nodes() > (uint)LiveNodeCountInliningCutoff; + // Give some room for incremental inlining algorithm to "breathe" + // and avoid thrashing when live node count is close to the limit. + // Keep in mind that live_nodes() isn't accurate during inlining until + // dead node elimination step happens (see Compile::inline_incrementally). + return live_nodes() > (uint)LiveNodeCountInliningCutoff * 11 / 10; } } @@ -1083,7 +1095,8 @@ void dec_number_of_mh_late_inlines() { assert(_number_of_mh_late_inlines > 0, "_number_of_mh_late_inlines < 0 !"); _number_of_mh_late_inlines--; } bool has_mh_late_inlines() const { return _number_of_mh_late_inlines > 0; } - void inline_incrementally_one(PhaseIterGVN& igvn); + bool inline_incrementally_one(); + void inline_incrementally_cleanup(PhaseIterGVN& igvn); void inline_incrementally(PhaseIterGVN& igvn); void inline_string_calls(bool parse_time); void inline_boxing_calls(PhaseIterGVN& igvn); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/doCall.cpp --- a/src/hotspot/share/opto/doCall.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/doCall.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -209,7 +209,7 @@ int morphism = profile.morphism(); if (speculative_receiver_type != NULL) { - if (!too_many_traps(caller, bci, Deoptimization::Reason_speculate_class_check)) { + if (!too_many_traps_or_recompiles(caller, bci, Deoptimization::Reason_speculate_class_check)) { // We have a speculative type, we should be able to resolve // the call. We do that before looking at the profiling at // this invoke because it may lead to bimorphic inlining which @@ -262,7 +262,7 @@ ? Deoptimization::Reason_bimorphic : Deoptimization::reason_class_check(speculative_receiver_type != NULL)); if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) && - !too_many_traps(caller, bci, reason) + !too_many_traps_or_recompiles(caller, bci, reason) ) { // Generate uncommon trap for class check failure path // in case of monomorphic or bimorphic virtual call site. @@ -292,6 +292,51 @@ } } } + + // If there is only one implementor of this interface then we + // may be able to bind this invoke directly to the implementing + // klass but we need both a dependence on the single interface + // and on the method we bind to. Additionally since all we know + // about the receiver type is that it's supposed to implement the + // interface we have to insert a check that it's the class we + // expect. Interface types are not checked by the verifier so + // they are roughly equivalent to Object. + // The number of implementors for declared_interface is less or + // equal to the number of implementors for target->holder() so + // if number of implementors of target->holder() == 1 then + // number of implementors for decl_interface is 0 or 1. If + // it's 0 then no class implements decl_interface and there's + // no point in inlining. + if (call_does_dispatch && bytecode == Bytecodes::_invokeinterface) { + ciInstanceKlass* declared_interface = + caller->get_declared_method_holder_at_bci(bci)->as_instance_klass(); + + if (declared_interface->nof_implementors() == 1 && + (!callee->is_default_method() || callee->is_overpass()) /* CHA doesn't support default methods yet */) { + ciInstanceKlass* singleton = declared_interface->implementor(); + ciMethod* cha_monomorphic_target = + callee->find_monomorphic_target(caller->holder(), declared_interface, singleton); + + if (cha_monomorphic_target != NULL && + cha_monomorphic_target->holder() != env()->Object_klass()) { // subtype check against Object is useless + ciKlass* holder = cha_monomorphic_target->holder(); + + // Try to inline the method found by CHA. Inlined method is guarded by the type check. + CallGenerator* hit_cg = call_generator(cha_monomorphic_target, + vtable_index, !call_does_dispatch, jvms, allow_inline, prof_factor); + + // Deoptimize on type check fail. The interpreter will throw ICCE for us. + CallGenerator* miss_cg = CallGenerator::for_uncommon_trap(callee, + Deoptimization::Reason_class_check, Deoptimization::Action_none); + + CallGenerator* cg = CallGenerator::for_guarded_call(holder, miss_cg, hit_cg); + if (hit_cg != NULL && cg != NULL) { + dependencies()->assert_unique_concrete_method(declared_interface, cha_monomorphic_target); + return cg; + } + } + } + } } // Nothing claimed the intrinsic, we go with straight-forward inlining diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/graphKit.cpp --- a/src/hotspot/share/opto/graphKit.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/graphKit.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -2794,6 +2794,22 @@ return fail; } +//------------------------------subtype_check_receiver------------------------- +Node* GraphKit::subtype_check_receiver(Node* receiver, ciKlass* klass, + Node** casted_receiver) { + const TypeKlassPtr* tklass = TypeKlassPtr::make(klass); + Node* recv_klass = load_object_klass(receiver); + Node* want_klass = makecon(tklass); + + Node* slow_ctl = gen_subtype_check(recv_klass, want_klass); + + // Cast receiver after successful check + const TypeOopPtr* recv_type = tklass->cast_to_exactness(false)->is_klassptr()->as_instance_type(); + Node* cast = new CheckCastPPNode(control(), receiver, recv_type); + (*casted_receiver) = _gvn.transform(cast); + + return slow_ctl; +} //------------------------------seems_never_null------------------------------- // Use null_seen information if it is available from the profile. @@ -2836,7 +2852,7 @@ Deoptimization::DeoptReason reason = Deoptimization::reason_class_check(spec_klass != NULL); // Make sure we haven't already deoptimized from this tactic. - if (too_many_traps(reason) || too_many_recompiles(reason)) + if (too_many_traps_or_recompiles(reason)) return NULL; // (No, this isn't a call, but it's enough like a virtual call @@ -2891,9 +2907,8 @@ Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; Deoptimization::DeoptReason null_reason = Deoptimization::Reason_speculate_null_check; - if (!too_many_traps(null_reason) && !too_many_recompiles(null_reason) && - !too_many_traps(class_reason) && - !too_many_recompiles(class_reason)) { + if (!too_many_traps_or_recompiles(null_reason) && + !too_many_traps_or_recompiles(class_reason)) { Node* not_null_obj = NULL; // not_null is true if we know the object is not null and // there's no need for a null check @@ -2918,8 +2933,7 @@ obj = exact_obj; } } else { - if (!too_many_traps(Deoptimization::Reason_null_assert) && - !too_many_recompiles(Deoptimization::Reason_null_assert)) { + if (!too_many_traps_or_recompiles(Deoptimization::Reason_null_assert)) { Node* exact_obj = null_assert(obj); replace_in_map(obj, exact_obj); obj = exact_obj; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/graphKit.hpp --- a/src/hotspot/share/opto/graphKit.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/graphKit.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -751,6 +751,10 @@ return C->too_many_recompiles(method(), bci(), reason); } + bool too_many_traps_or_recompiles(Deoptimization::DeoptReason reason) { + return C->too_many_traps_or_recompiles(method(), bci(), reason); + } + // Returns the object (if any) which was created the moment before. Node* just_allocated_object(Node* current_control); @@ -830,6 +834,10 @@ Node* type_check_receiver(Node* receiver, ciKlass* klass, float prob, Node* *casted_receiver); + // Inexact type check used for predicted calls. + Node* subtype_check_receiver(Node* receiver, ciKlass* klass, + Node** casted_receiver); + // implementation of object creation Node* set_output_for_allocation(AllocateNode* alloc, const TypeOopPtr* oop_type, diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/phaseX.cpp --- a/src/hotspot/share/opto/phaseX.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/phaseX.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -461,55 +461,115 @@ PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, Unique_Node_List* worklist, Unique_Node_List* new_worklist, PhaseNumber phase_num) : - PhaseRemoveUseless(gvn, worklist, Remove_Useless_And_Renumber_Live) { - + PhaseRemoveUseless(gvn, worklist, Remove_Useless_And_Renumber_Live), + _new_type_array(C->comp_arena()), + _old2new_map(C->unique(), C->unique(), -1), + _delayed(Thread::current()->resource_area()), + _is_pass_finished(false), + _live_node_count(C->live_nodes()) +{ assert(RenumberLiveNodes, "RenumberLiveNodes must be set to true for node renumbering to take place"); assert(C->live_nodes() == _useful.size(), "the number of live nodes must match the number of useful nodes"); assert(gvn->nodes_size() == 0, "GVN must not contain any nodes at this point"); + assert(_delayed.size() == 0, "should be empty"); - uint old_unique_count = C->unique(); - uint live_node_count = C->live_nodes(); uint worklist_size = worklist->size(); - // Storage for the updated type information. - Type_Array new_type_array(C->comp_arena()); - // Iterate over the set of live nodes. - uint current_idx = 0; // The current new node ID. Incremented after every assignment. - for (uint i = 0; i < _useful.size(); i++) { - Node* n = _useful.at(i); - // Sanity check that fails if we ever decide to execute this phase after EA - assert(!n->is_Phi() || n->as_Phi()->inst_mem_id() == -1, "should not be linked to data Phi"); - const Type* type = gvn->type_or_null(n); - new_type_array.map(current_idx, type); + for (uint current_idx = 0; current_idx < _useful.size(); current_idx++) { + Node* n = _useful.at(current_idx); bool in_worklist = false; if (worklist->member(n)) { in_worklist = true; } + const Type* type = gvn->type_or_null(n); + _new_type_array.map(current_idx, type); + + assert(_old2new_map.at(n->_idx) == -1, "already seen"); + _old2new_map.at_put(n->_idx, current_idx); + n->set_idx(current_idx); // Update node ID. if (in_worklist) { new_worklist->push(n); } - current_idx++; + if (update_embedded_ids(n) < 0) { + _delayed.push(n); // has embedded IDs; handle later + } } assert(worklist_size == new_worklist->size(), "the new worklist must have the same size as the original worklist"); - assert(live_node_count == current_idx, "all live nodes must be processed"); + assert(_live_node_count == _useful.size(), "all live nodes must be processed"); + + _is_pass_finished = true; // pass finished; safe to process delayed updates + + while (_delayed.size() > 0) { + Node* n = _delayed.pop(); + int no_of_updates = update_embedded_ids(n); + assert(no_of_updates > 0, "should be updated"); + } // Replace the compiler's type information with the updated type information. - gvn->replace_types(new_type_array); + gvn->replace_types(_new_type_array); // Update the unique node count of the compilation to the number of currently live nodes. - C->set_unique(live_node_count); + C->set_unique(_live_node_count); // Set the dead node count to 0 and reset dead node list. C->reset_dead_node_list(); } +int PhaseRenumberLive::new_index(int old_idx) { + assert(_is_pass_finished, "not finished"); + if (_old2new_map.at(old_idx) == -1) { // absent + // Allocate a placeholder to preserve uniqueness + _old2new_map.at_put(old_idx, _live_node_count); + _live_node_count++; + } + return _old2new_map.at(old_idx); +} + +int PhaseRenumberLive::update_embedded_ids(Node* n) { + int no_of_updates = 0; + if (n->is_Phi()) { + PhiNode* phi = n->as_Phi(); + if (phi->_inst_id != -1) { + if (!_is_pass_finished) { + return -1; // delay + } + int new_idx = new_index(phi->_inst_id); + assert(new_idx != -1, ""); + phi->_inst_id = new_idx; + no_of_updates++; + } + if (phi->_inst_mem_id != -1) { + if (!_is_pass_finished) { + return -1; // delay + } + int new_idx = new_index(phi->_inst_mem_id); + assert(new_idx != -1, ""); + phi->_inst_mem_id = new_idx; + no_of_updates++; + } + } + + const Type* type = _new_type_array.fast_lookup(n->_idx); + if (type != NULL && type->isa_oopptr() && type->is_oopptr()->is_known_instance()) { + if (!_is_pass_finished) { + return -1; // delay + } + int old_idx = type->is_oopptr()->instance_id(); + int new_idx = new_index(old_idx); + const Type* new_type = type->is_oopptr()->with_instance_id(new_idx); + _new_type_array.map(n->_idx, new_type); + no_of_updates++; + } + + return no_of_updates; +} //============================================================================= //------------------------------PhaseTransform--------------------------------- diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/phaseX.hpp --- a/src/hotspot/share/opto/phaseX.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/phaseX.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -157,6 +157,16 @@ // Phase that first performs a PhaseRemoveUseless, then it renumbers compiler // structures accordingly. class PhaseRenumberLive : public PhaseRemoveUseless { +protected: + Type_Array _new_type_array; // Storage for the updated type information. + GrowableArray _old2new_map; + Node_List _delayed; + bool _is_pass_finished; + uint _live_node_count; + + int update_embedded_ids(Node* n); + int new_index(int old_idx); + public: PhaseRenumberLive(PhaseGVN* gvn, Unique_Node_List* worklist, Unique_Node_List* new_worklist, diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/type.cpp --- a/src/hotspot/share/opto/type.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/type.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -3436,6 +3436,12 @@ return make(_ptr, _offset, _instance_id, _speculative, depth); } +//------------------------------with_instance_id-------------------------------- +const TypePtr* TypeOopPtr::with_instance_id(int instance_id) const { + assert(_instance_id != -1, "should be known"); + return make(_ptr, _offset, instance_id, _speculative, _inline_depth); +} + //------------------------------meet_instance_id-------------------------------- int TypeOopPtr::meet_instance_id( int instance_id ) const { // Either is 'TOP' instance? Return the other instance! @@ -4044,6 +4050,11 @@ return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, depth); } +const TypePtr *TypeInstPtr::with_instance_id(int instance_id) const { + assert(is_known_instance(), "should be known"); + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, instance_id, _speculative, _inline_depth); +} + //============================================================================= // Convenience common pre-built types. const TypeAryPtr *TypeAryPtr::RANGE; @@ -4530,6 +4541,11 @@ return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, _speculative, depth); } +const TypePtr *TypeAryPtr::with_instance_id(int instance_id) const { + assert(is_known_instance(), "should be known"); + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); +} + //============================================================================= //------------------------------hash------------------------------------------- diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/opto/type.hpp --- a/src/hotspot/share/opto/type.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/opto/type.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -1045,6 +1045,8 @@ virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; virtual const TypePtr* with_inline_depth(int depth) const; + virtual const TypePtr* with_instance_id(int instance_id) const; + virtual const Type *xdual() const; // Compute dual right now. // the core of the computation of the meet for TypeOopPtr and for its subclasses virtual const Type *xmeet_helper(const Type *t) const; @@ -1123,6 +1125,7 @@ // Speculative type helper methods. virtual const Type* remove_speculative() const; virtual const TypePtr* with_inline_depth(int depth) const; + virtual const TypePtr* with_instance_id(int instance_id) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1212,6 +1215,7 @@ // Speculative type helper methods. virtual const Type* remove_speculative() const; virtual const TypePtr* with_inline_depth(int depth) const; + virtual const TypePtr* with_instance_id(int instance_id) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/jvm.cpp --- a/src/hotspot/share/prims/jvm.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/jvm.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -870,10 +870,6 @@ Handle h_prot (THREAD, protection_domain); jclass result = find_class_from_class_loader(env, h_name, init, h_loader, h_prot, true, thread); - if (result != NULL) { - oop mirror = JNIHandles::resolve_non_null(result); - Klass* to_class = java_lang_Class::as_Klass(mirror); - } if (log_is_enabled(Debug, class, resolve) && result != NULL) { // this function is generally only used for class loading during verification. diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp --- a/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ #include "oops/oop.inline.hpp" #include "prims/jvmtiCodeBlobEvents.hpp" #include "prims/jvmtiExport.hpp" -#include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" #include "runtime/vmThread.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/jvmtiEnv.cpp --- a/src/hotspot/share/prims/jvmtiEnv.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/jvmtiEnv.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * 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,6 +56,7 @@ #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/fieldDescriptor.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jfieldIDWorkaround.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/jvmtiEnvBase.cpp --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * 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,6 +41,7 @@ #include "runtime/biasedLocking.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jfieldIDWorkaround.hpp" #include "runtime/jniHandles.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/jvmtiExport.cpp --- a/src/hotspot/share/prims/jvmtiExport.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/jvmtiExport.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -49,7 +49,7 @@ #include "prims/jvmtiThreadState.inline.hpp" #include "runtime/arguments.hpp" #include "runtime/fieldDescriptor.inline.hpp" -#include "runtime/handles.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/jvmtiManageCapabilities.cpp --- a/src/hotspot/share/prims/jvmtiManageCapabilities.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/jvmtiManageCapabilities.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -107,6 +107,14 @@ #ifndef ZERO jc.can_pop_frame = 1; jc.can_force_early_return = 1; + // Workaround for 8195635: + // disable pop_frame and force_early_return capabilities with Graal +#if INCLUDE_JVMCI + if (UseJVMCICompiler) { + jc.can_pop_frame = 0; + jc.can_force_early_return = 0; + } +#endif // INCLUDE_JVMCI #endif // !ZERO jc.can_get_source_debug_extension = 1; jc.can_access_local_variables = 1; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/methodHandles.cpp --- a/src/hotspot/share/prims/methodHandles.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/methodHandles.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -40,6 +40,7 @@ #include "prims/methodHandles.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/fieldDescriptor.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/nativeLookup.cpp --- a/src/hotspot/share/prims/nativeLookup.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/nativeLookup.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/os.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "utilities/macros.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/stackwalk.cpp --- a/src/hotspot/share/prims/stackwalk.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/stackwalk.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -35,6 +35,7 @@ #include "runtime/globals.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.inline.hpp" #include "utilities/globalDefinitions.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/unsafe.cpp --- a/src/hotspot/share/prims/unsafe.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/unsafe.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ #include "prims/unsafe.hpp" #include "runtime/atomic.hpp" #include "runtime/globals.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/orderAccess.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/prims/whitebox.cpp --- a/src/hotspot/share/prims/whitebox.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/prims/whitebox.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -59,6 +59,7 @@ #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/handshake.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/arguments.cpp --- a/src/hotspot/share/runtime/arguments.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/arguments.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -579,7 +579,7 @@ { "TraceClassUnloading", LogLevel::Info, true, LOG_TAGS(class, unload) }, { "TraceExceptions", LogLevel::Info, true, LOG_TAGS(exceptions) }, { "TraceLoaderConstraints", LogLevel::Info, true, LOG_TAGS(class, loader, constraints) }, - { "TraceMonitorInflation", LogLevel::Debug, true, LOG_TAGS(monitorinflation) }, + { "TraceMonitorInflation", LogLevel::Trace, true, LOG_TAGS(monitorinflation) }, { "TraceSafepointCleanupTime", LogLevel::Info, true, LOG_TAGS(safepoint, cleanup) }, { "TraceJVMTIObjectTagging", LogLevel::Debug, true, LOG_TAGS(jvmti, objecttagging) }, { "TraceRedefineClasses", LogLevel::Info, false, LOG_TAGS(redefine, class) }, diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/deoptimization.cpp --- a/src/hotspot/share/runtime/deoptimization.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/deoptimization.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -47,6 +47,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/sharedRuntime.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/handles.hpp --- a/src/hotspot/share/runtime/handles.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/handles.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -31,6 +31,7 @@ class InstanceKlass; class Klass; +class Thread; //------------------------------------------------------------------------------------------------------------------------ // In order to preserve oops during garbage collection, they should be diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/handles.inline.hpp --- a/src/hotspot/share/runtime/handles.inline.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/handles.inline.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -26,7 +26,9 @@ #define SHARE_RUNTIME_HANDLES_INLINE_HPP #include "runtime/handles.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" +#include "oops/metadata.hpp" +#include "oops/oop.hpp" // these inline functions are in a separate file to break an include cycle // between Thread and Handle diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/init.cpp --- a/src/hotspot/share/runtime/init.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/init.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -166,6 +166,13 @@ static bool destructorsCalled = false; if (!destructorsCalled) { destructorsCalled = true; + if (log_is_enabled(Info, monitorinflation)) { + // The ObjectMonitor subsystem uses perf counters so + // do this before perfMemory_exit(). + // ObjectSynchronizer::finish_deflate_idle_monitors()'s call + // to audit_and_print_stats() is done at the Debug level. + ObjectSynchronizer::audit_and_print_stats(true /* on_exit */); + } perfMemory_exit(); if (log_is_enabled(Debug, safepoint, stats)) { // Print the collected safepoint statistics. diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/java.cpp --- a/src/hotspot/share/runtime/java.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/java.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -58,6 +58,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/deoptimization.hpp" #include "runtime/flags/flagSetting.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/os.cpp --- a/src/hotspot/share/runtime/os.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/os.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -47,6 +47,7 @@ #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -908,6 +909,11 @@ st->cr(); } +void os::print_instructions(outputStream* st, address pc, int unitsize) { + st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc)); + print_hex_dump(st, pc - 256, pc + 256, unitsize); +} + void os::print_environment_variables(outputStream* st, const char** env_list) { if (env_list) { st->print_cr("Environment Variables:"); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/os.hpp --- a/src/hotspot/share/runtime/os.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/os.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -640,6 +640,7 @@ static void print_siginfo(outputStream* st, const void* siginfo); static void print_signal_handlers(outputStream* st, char* buf, size_t buflen); static void print_date_and_time(outputStream* st, char* buf, size_t buflen); + static void print_instructions(outputStream* st, address pc, int unitsize); static void print_location(outputStream* st, intptr_t x, bool verbose = false); static size_t lasterror(char *buf, size_t len); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/reflection.cpp --- a/src/hotspot/share/runtime/reflection.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/reflection.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -49,6 +49,7 @@ #include "runtime/reflection.hpp" #include "runtime/reflectionUtils.hpp" #include "runtime/signature.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.inline.hpp" static void trace_class_resolution(const Klass* to_class) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/safepoint.cpp --- a/src/hotspot/share/runtime/safepoint.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/safepoint.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/orderAccess.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/semaphore.inline.hpp --- a/src/hotspot/share/runtime/semaphore.inline.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/semaphore.inline.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -27,7 +27,7 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/semaphore.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" inline void Semaphore::wait_with_safepoint_check(JavaThread* thread) { // Prepare to block and allow safepoints while blocked diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/serviceThread.cpp --- a/src/hotspot/share/runtime/serviceThread.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/serviceThread.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/synchronizer.cpp --- a/src/hotspot/share/runtime/synchronizer.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/synchronizer.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "jfr/jfrEvents.hpp" #include "memory/allocation.inline.hpp" #include "memory/metaspaceShared.hpp" @@ -1354,6 +1355,8 @@ // before or after the CAS(INFLATING) operation. // See the comments in omAlloc(). + LogStreamHandle(Trace, monitorinflation) lsh; + if (mark->has_locker()) { ObjectMonitor * m = omAlloc(Self); // Optimistically prepare the objectmonitor - anticipate successful CAS @@ -1423,14 +1426,11 @@ // Hopefully the performance counters are allocated on distinct cache lines // to avoid false sharing on MP systems ... OM_PERFDATA_OP(Inflations, inc()); - if (log_is_enabled(Debug, monitorinflation)) { - if (object->is_instance()) { - ResourceMark rm(Self); - log_debug(monitorinflation)("inflate(has_locker): " - "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'", - p2i(object), p2i(object->mark()), - object->klass()->external_name()); - } + if (log_is_enabled(Trace, monitorinflation)) { + ResourceMark rm(Self); + lsh.print_cr("inflate(has_locker): object=" INTPTR_FORMAT ", mark=" + INTPTR_FORMAT ", type='%s'", p2i(object), + p2i(object->mark()), object->klass()->external_name()); } if (event.should_commit()) { post_monitor_inflate_event(&event, object, cause); @@ -1474,14 +1474,11 @@ // Hopefully the performance counters are allocated on distinct // cache lines to avoid false sharing on MP systems ... OM_PERFDATA_OP(Inflations, inc()); - if (log_is_enabled(Debug, monitorinflation)) { - if (object->is_instance()) { - ResourceMark rm(Self); - log_debug(monitorinflation)("inflate(neutral): " - "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'", - p2i(object), p2i(object->mark()), - object->klass()->external_name()); - } + if (log_is_enabled(Trace, monitorinflation)) { + ResourceMark rm(Self); + lsh.print_cr("inflate(neutral): object=" INTPTR_FORMAT ", mark=" + INTPTR_FORMAT ", type='%s'", p2i(object), + p2i(object->mark()), object->klass()->external_name()); } if (event.should_commit()) { post_monitor_inflate_event(&event, object, cause); @@ -1529,14 +1526,12 @@ // Deflate the monitor if it is no longer being used // It's idle - scavenge and return to the global free list // plain old deflation ... - if (log_is_enabled(Debug, monitorinflation)) { - if (obj->is_instance()) { - ResourceMark rm; - log_debug(monitorinflation)("deflate_monitor: " - "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'", - p2i(obj), p2i(obj->mark()), - obj->klass()->external_name()); - } + if (log_is_enabled(Trace, monitorinflation)) { + ResourceMark rm; + log_trace(monitorinflation)("deflate_monitor: " + "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'", + p2i(obj), p2i(obj->mark()), + obj->klass()->external_name()); } // Restore the header back to obj @@ -1602,10 +1597,11 @@ } void ObjectSynchronizer::prepare_deflate_idle_monitors(DeflateMonitorCounters* counters) { - counters->nInuse = 0; // currently associated with objects - counters->nInCirculation = 0; // extant - counters->nScavenged = 0; // reclaimed (global and per-thread) - counters->perThreadTimes = 0.0; // per-thread scavenge times + counters->nInuse = 0; // currently associated with objects + counters->nInCirculation = 0; // extant + counters->nScavenged = 0; // reclaimed (global and per-thread) + counters->perThreadScavenged = 0; // per-thread scavenge total + counters->perThreadTimes = 0.0; // per-thread scavenge times } void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) { @@ -1614,6 +1610,11 @@ ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors ObjectMonitor * freeTailp = NULL; + elapsedTimer timer; + + if (log_is_enabled(Info, monitorinflation)) { + timer.start(); + } // Prevent omFlush from changing mids in Thread dtor's during deflation // And in case the vm thread is acquiring a lock during a safepoint @@ -1624,9 +1625,10 @@ // a separate pass. See deflate_thread_local_monitors(). // For moribund threads, scan gOmInUseList + int deflated_count = 0; if (gOmInUseList) { counters->nInCirculation += gOmInUseCount; - int deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp); + deflated_count = deflate_monitor_list((ObjectMonitor **)&gOmInUseList, &freeHeadp, &freeTailp); gOmInUseCount -= deflated_count; counters->nScavenged += deflated_count; counters->nInuse += gOmInUseCount; @@ -1641,29 +1643,53 @@ gFreeList = freeHeadp; } Thread::muxRelease(&gListLock); + timer.stop(); + LogStreamHandle(Debug, monitorinflation) lsh_debug; + LogStreamHandle(Info, monitorinflation) lsh_info; + LogStream * ls = NULL; + if (log_is_enabled(Debug, monitorinflation)) { + ls = &lsh_debug; + } else if (deflated_count != 0 && log_is_enabled(Info, monitorinflation)) { + ls = &lsh_info; + } + if (ls != NULL) { + ls->print_cr("deflating global idle monitors, %3.7f secs, %d monitors", timer.seconds(), deflated_count); + } } void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* counters) { - if (log_is_enabled(Info, safepoint, cleanup)) { - // Report the cumulative time for deflating each thread's idle - // monitors. Note: if the work is split among more than one - // worker thread, then the reported time will likely be more - // than a beginning to end measurement of the phase. - log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs", counters->perThreadTimes); + // Report the cumulative time for deflating each thread's idle + // monitors. Note: if the work is split among more than one + // worker thread, then the reported time will likely be more + // than a beginning to end measurement of the phase. + log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->perThreadTimes, counters->perThreadScavenged); + + LogStreamHandle(Debug, monitorinflation) lsh_debug; + LogStreamHandle(Info, monitorinflation) lsh_info; + LogStream * ls = NULL; + if (log_is_enabled(Debug, monitorinflation)) { + ls = &lsh_debug; + } else if (counters->perThreadScavenged != 0 && log_is_enabled(Info, monitorinflation)) { + ls = &lsh_info; + } + if (ls != NULL) { + ls->print_cr("deflating per-thread idle monitors, %3.7f secs, %d monitors", counters->perThreadTimes, counters->perThreadScavenged); } gMonitorFreeCount += counters->nScavenged; - // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree. + if (log_is_enabled(Debug, monitorinflation)) { + // exit_globals()'s call to audit_and_print_stats() is done + // at the Info level. + ObjectSynchronizer::audit_and_print_stats(false /* on_exit */); + } ForceMonitorScavenge = 0; // Reset OM_PERFDATA_OP(Deflations, inc(counters->nScavenged)); OM_PERFDATA_OP(MonExtant, set_value(counters->nInCirculation)); - // TODO: Add objectMonitor leak detection. - // Audit/inventory the objectMonitors -- make sure they're all accounted for. GVars.stwRandom = os::random(); GVars.stwCycle++; } @@ -1675,7 +1701,8 @@ ObjectMonitor * freeTailp = NULL; elapsedTimer timer; - if (log_is_enabled(Info, safepoint, cleanup)) { + if (log_is_enabled(Info, safepoint, cleanup) || + log_is_enabled(Info, monitorinflation)) { timer.start(); } @@ -1690,6 +1717,7 @@ thread->omInUseCount -= deflated_count; counters->nScavenged += deflated_count; counters->nInuse += thread->omInUseCount; + counters->perThreadScavenged += deflated_count; // For now, we only care about cumulative per-thread deflation time. counters->perThreadTimes += timer.seconds(); @@ -1782,6 +1810,338 @@ return (u_char*)&GVars.stwRandom; } +void ObjectSynchronizer::audit_and_print_stats(bool on_exit) { + assert(on_exit || SafepointSynchronize::is_at_safepoint(), "invariant"); + + LogStreamHandle(Debug, monitorinflation) lsh_debug; + LogStreamHandle(Info, monitorinflation) lsh_info; + LogStreamHandle(Trace, monitorinflation) lsh_trace; + LogStream * ls = NULL; + if (log_is_enabled(Trace, monitorinflation)) { + ls = &lsh_trace; + } else if (log_is_enabled(Debug, monitorinflation)) { + ls = &lsh_debug; + } else if (log_is_enabled(Info, monitorinflation)) { + ls = &lsh_info; + } + assert(ls != NULL, "sanity check"); + + if (!on_exit) { + // Not at VM exit so grab the global list lock. + Thread::muxAcquire(&gListLock, "audit_and_print_stats"); + } + + // Log counts for the global and per-thread monitor lists: + int chkMonitorPopulation = log_monitor_list_counts(ls); + int error_cnt = 0; + + ls->print_cr("Checking global lists:"); + + // Check gMonitorPopulation: + if (gMonitorPopulation == chkMonitorPopulation) { + ls->print_cr("gMonitorPopulation=%d equals chkMonitorPopulation=%d", + gMonitorPopulation, chkMonitorPopulation); + } else { + ls->print_cr("ERROR: gMonitorPopulation=%d is not equal to " + "chkMonitorPopulation=%d", gMonitorPopulation, + chkMonitorPopulation); + error_cnt++; + } + + // Check gOmInUseList and gOmInUseCount: + chk_global_in_use_list_and_count(ls, &error_cnt); + + // Check gFreeList and gMonitorFreeCount: + chk_global_free_list_and_count(ls, &error_cnt); + + if (!on_exit) { + Thread::muxRelease(&gListLock); + } + + ls->print_cr("Checking per-thread lists:"); + + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { + // Check omInUseList and omInUseCount: + chk_per_thread_in_use_list_and_count(jt, ls, &error_cnt); + + // Check omFreeList and omFreeCount: + chk_per_thread_free_list_and_count(jt, ls, &error_cnt); + } + + if (error_cnt == 0) { + ls->print_cr("No errors found in monitor list checks."); + } else { + log_error(monitorinflation)("found monitor list errors: error_cnt=%d", error_cnt); + } + + if ((on_exit && log_is_enabled(Info, monitorinflation)) || + (!on_exit && log_is_enabled(Trace, monitorinflation))) { + // When exiting this log output is at the Info level. When called + // at a safepoint, this log output is at the Trace level since + // there can be a lot of it. + log_in_use_monitor_details(ls, on_exit); + } + + ls->flush(); + + guarantee(error_cnt == 0, "ERROR: found monitor list errors: error_cnt=%d", error_cnt); +} + +// Check a free monitor entry; log any errors. +void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n, + outputStream * out, int *error_cnt_p) { + if (n->is_busy()) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": free per-thread monitor must not be busy.", p2i(jt), + p2i(n)); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor " + "must not be busy.", p2i(n)); + } + *error_cnt_p = *error_cnt_p + 1; + } + if (n->header() != NULL) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": free per-thread monitor must have NULL _header " + "field: _header=" INTPTR_FORMAT, p2i(jt), p2i(n), + p2i(n->header())); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor " + "must have NULL _header field: _header=" INTPTR_FORMAT, + p2i(n), p2i(n->header())); + } + *error_cnt_p = *error_cnt_p + 1; + } + if (n->object() != NULL) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": free per-thread monitor must have NULL _object " + "field: _object=" INTPTR_FORMAT, p2i(jt), p2i(n), + p2i(n->object())); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor " + "must have NULL _object field: _object=" INTPTR_FORMAT, + p2i(n), p2i(n->object())); + } + *error_cnt_p = *error_cnt_p + 1; + } +} + +// Check the global free list and count; log the results of the checks. +void ObjectSynchronizer::chk_global_free_list_and_count(outputStream * out, + int *error_cnt_p) { + int chkMonitorFreeCount = 0; + for (ObjectMonitor * n = gFreeList; n != NULL; n = n->FreeNext) { + chk_free_entry(NULL /* jt */, n, out, error_cnt_p); + chkMonitorFreeCount++; + } + if (gMonitorFreeCount == chkMonitorFreeCount) { + out->print_cr("gMonitorFreeCount=%d equals chkMonitorFreeCount=%d", + gMonitorFreeCount, chkMonitorFreeCount); + } else { + out->print_cr("ERROR: gMonitorFreeCount=%d is not equal to " + "chkMonitorFreeCount=%d", gMonitorFreeCount, + chkMonitorFreeCount); + *error_cnt_p = *error_cnt_p + 1; + } +} + +// Check the global in-use list and count; log the results of the checks. +void ObjectSynchronizer::chk_global_in_use_list_and_count(outputStream * out, + int *error_cnt_p) { + int chkOmInUseCount = 0; + for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) { + chk_in_use_entry(NULL /* jt */, n, out, error_cnt_p); + chkOmInUseCount++; + } + if (gOmInUseCount == chkOmInUseCount) { + out->print_cr("gOmInUseCount=%d equals chkOmInUseCount=%d", gOmInUseCount, + chkOmInUseCount); + } else { + out->print_cr("ERROR: gOmInUseCount=%d is not equal to chkOmInUseCount=%d", + gOmInUseCount, chkOmInUseCount); + *error_cnt_p = *error_cnt_p + 1; + } +} + +// Check an in-use monitor entry; log any errors. +void ObjectSynchronizer::chk_in_use_entry(JavaThread * jt, ObjectMonitor * n, + outputStream * out, int *error_cnt_p) { + if (n->header() == NULL) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": in-use per-thread monitor must have non-NULL _header " + "field.", p2i(jt), p2i(n)); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global monitor " + "must have non-NULL _header field.", p2i(n)); + } + *error_cnt_p = *error_cnt_p + 1; + } + if (n->object() == NULL) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": in-use per-thread monitor must have non-NULL _object " + "field.", p2i(jt), p2i(n)); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global monitor " + "must have non-NULL _object field.", p2i(n)); + } + *error_cnt_p = *error_cnt_p + 1; + } + const oop obj = (oop)n->object(); + const markOop mark = obj->mark(); + if (!mark->has_monitor()) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": in-use per-thread monitor's object does not think " + "it has a monitor: obj=" INTPTR_FORMAT ", mark=" + INTPTR_FORMAT, p2i(jt), p2i(n), p2i((address)obj), + p2i((address)mark)); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global " + "monitor's object does not think it has a monitor: obj=" + INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n), + p2i((address)obj), p2i((address)mark)); + } + *error_cnt_p = *error_cnt_p + 1; + } + ObjectMonitor * const obj_mon = mark->monitor(); + if (n != obj_mon) { + if (jt != NULL) { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT + ": in-use per-thread monitor's object does not refer " + "to the same monitor: obj=" INTPTR_FORMAT ", mark=" + INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt), + p2i(n), p2i((address)obj), p2i((address)mark), + p2i((address)obj_mon)); + } else { + out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global " + "monitor's object does not refer to the same monitor: obj=" + INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon=" + INTPTR_FORMAT, p2i(n), p2i((address)obj), + p2i((address)mark), p2i((address)obj_mon)); + } + *error_cnt_p = *error_cnt_p + 1; + } +} + +// Check the thread's free list and count; log the results of the checks. +void ObjectSynchronizer::chk_per_thread_free_list_and_count(JavaThread *jt, + outputStream * out, + int *error_cnt_p) { + int chkOmFreeCount = 0; + for (ObjectMonitor * n = jt->omFreeList; n != NULL; n = n->FreeNext) { + chk_free_entry(jt, n, out, error_cnt_p); + chkOmFreeCount++; + } + if (jt->omFreeCount == chkOmFreeCount) { + out->print_cr("jt=" INTPTR_FORMAT ": omFreeCount=%d equals " + "chkOmFreeCount=%d", p2i(jt), jt->omFreeCount, chkOmFreeCount); + } else { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ": omFreeCount=%d is not " + "equal to chkOmFreeCount=%d", p2i(jt), jt->omFreeCount, + chkOmFreeCount); + *error_cnt_p = *error_cnt_p + 1; + } +} + +// Check the thread's in-use list and count; log the results of the checks. +void ObjectSynchronizer::chk_per_thread_in_use_list_and_count(JavaThread *jt, + outputStream * out, + int *error_cnt_p) { + int chkOmInUseCount = 0; + for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) { + chk_in_use_entry(jt, n, out, error_cnt_p); + chkOmInUseCount++; + } + if (jt->omInUseCount == chkOmInUseCount) { + out->print_cr("jt=" INTPTR_FORMAT ": omInUseCount=%d equals " + "chkOmInUseCount=%d", p2i(jt), jt->omInUseCount, + chkOmInUseCount); + } else { + out->print_cr("ERROR: jt=" INTPTR_FORMAT ": omInUseCount=%d is not " + "equal to chkOmInUseCount=%d", p2i(jt), jt->omInUseCount, + chkOmInUseCount); + *error_cnt_p = *error_cnt_p + 1; + } +} + +// Log details about ObjectMonitors on the in-use lists. The 'BHL' +// flags indicate why the entry is in-use, 'object' and 'object type' +// indicate the associated object and its type. +void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out, + bool on_exit) { + if (!on_exit) { + // Not at VM exit so grab the global list lock. + Thread::muxAcquire(&gListLock, "log_in_use_monitor_details"); + } + + if (gOmInUseCount > 0) { + out->print_cr("In-use global monitor info:"); + out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)"); + out->print_cr("%18s %s %18s %18s", + "monitor", "BHL", "object", "object type"); + out->print_cr("================== === ================== =================="); + for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) { + const oop obj = (oop) n->object(); + const markOop mark = n->header(); + ResourceMark rm; + out->print_cr(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(n), + n->is_busy() != 0, mark->hash() != 0, n->owner() != NULL, + p2i(obj), obj->klass()->external_name()); + } + } + + if (!on_exit) { + Thread::muxRelease(&gListLock); + } + + out->print_cr("In-use per-thread monitor info:"); + out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)"); + out->print_cr("%18s %18s %s %18s %18s", + "jt", "monitor", "BHL", "object", "object type"); + out->print_cr("================== ================== === ================== =================="); + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { + for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) { + const oop obj = (oop) n->object(); + const markOop mark = n->header(); + ResourceMark rm; + out->print_cr(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT + " %s", p2i(jt), p2i(n), n->is_busy() != 0, + mark->hash() != 0, n->owner() != NULL, p2i(obj), + obj->klass()->external_name()); + } + } + + out->flush(); +} + +// Log counts for the global and per-thread monitor lists and return +// the population count. +int ObjectSynchronizer::log_monitor_list_counts(outputStream * out) { + int popCount = 0; + out->print_cr("%18s %10s %10s %10s", + "Global Lists:", "InUse", "Free", "Total"); + out->print_cr("================== ========== ========== =========="); + out->print_cr("%18s %10d %10d %10d", "", + gOmInUseCount, gMonitorFreeCount, gMonitorPopulation); + popCount += gOmInUseCount + gMonitorFreeCount; + + out->print_cr("%18s %10s %10s %10s", + "Per-Thread Lists:", "InUse", "Free", "Provision"); + out->print_cr("================== ========== ========== =========="); + + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { + out->print_cr(INTPTR_FORMAT " %10d %10d %10d", p2i(jt), + jt->omInUseCount, jt->omFreeCount, jt->omFreeProvision); + popCount += jt->omInUseCount + jt->omFreeCount; + } + return popCount; +} + #ifndef PRODUCT // Check if monitor belongs to the monitor cache diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/synchronizer.hpp --- a/src/hotspot/share/runtime/synchronizer.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/synchronizer.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -35,10 +35,11 @@ class ThreadsList; struct DeflateMonitorCounters { - int nInuse; // currently associated with objects - int nInCirculation; // extant - int nScavenged; // reclaimed (global and per-thread) - double perThreadTimes; // per-thread scavenge times + int nInuse; // currently associated with objects + int nInCirculation; // extant + int nScavenged; // reclaimed (global and per-thread) + int perThreadScavenged; // per-thread scavenge total + double perThreadTimes; // per-thread scavenge times }; class ObjectSynchronizer : AllStatic { @@ -153,6 +154,23 @@ static void thread_local_used_oops_do(Thread* thread, OopClosure* f); // debugging + static void audit_and_print_stats(bool on_exit); + static void chk_free_entry(JavaThread * jt, ObjectMonitor * n, + outputStream * out, int *error_cnt_p); + static void chk_global_free_list_and_count(outputStream * out, + int *error_cnt_p); + static void chk_global_in_use_list_and_count(outputStream * out, + int *error_cnt_p); + static void chk_in_use_entry(JavaThread * jt, ObjectMonitor * n, + outputStream * out, int *error_cnt_p); + static void chk_per_thread_in_use_list_and_count(JavaThread *jt, + outputStream * out, + int *error_cnt_p); + static void chk_per_thread_free_list_and_count(JavaThread *jt, + outputStream * out, + int *error_cnt_p); + static void log_in_use_monitor_details(outputStream * out, bool on_exit); + static int log_monitor_list_counts(outputStream * out); static int verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0; private: diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/thread.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -69,6 +69,7 @@ #include "runtime/flags/jvmFlagWriteableList.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/handshake.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.inline.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/thread.hpp --- a/src/hotspot/share/runtime/thread.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/thread.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -1280,15 +1280,8 @@ address last_Java_pc(void) { return _anchor.last_Java_pc(); } // Safepoint support -#if !(defined(PPC64) || defined(AARCH64)) - JavaThreadState thread_state() const { return _thread_state; } - void set_thread_state(JavaThreadState s) { _thread_state = s; } -#else - // Use membars when accessing volatile _thread_state. See - // Threads::create_vm() for size checks. inline JavaThreadState thread_state() const; inline void set_thread_state(JavaThreadState s); -#endif inline ThreadSafepointState* safepoint_state() const; inline void set_safepoint_state(ThreadSafepointState* state); inline bool is_at_poll_safepoint(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/thread.inline.hpp --- a/src/hotspot/share/runtime/thread.inline.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/thread.inline.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -121,15 +121,25 @@ set_has_async_exception(); } +inline JavaThreadState JavaThread::thread_state() const { #if defined(PPC64) || defined (AARCH64) -inline JavaThreadState JavaThread::thread_state() const { + // Use membars when accessing volatile _thread_state. See + // Threads::create_vm() for size checks. return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state); +#else + return _thread_state; +#endif } inline void JavaThread::set_thread_state(JavaThreadState s) { +#if defined(PPC64) || defined (AARCH64) + // Use membars when accessing volatile _thread_state. See + // Threads::create_vm() for size checks. OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s); +#else + _thread_state = s; +#endif } -#endif ThreadSafepointState* JavaThread::safepoint_state() const { return _safepoint_state; diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/tieredThresholdPolicy.cpp --- a/src/hotspot/share/runtime/tieredThresholdPolicy.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -28,6 +28,7 @@ #include "memory/resourceArea.hpp" #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/safepoint.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/tieredThresholdPolicy.hpp" #include "code/scopeDesc.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/vframe.cpp --- a/src/hotspot/share/runtime/vframe.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/vframe.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * 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,6 +43,7 @@ #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.inline.hpp" #include "runtime/vframeArray.hpp" #include "runtime/vframe_hp.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/runtime/vmThread.cpp --- a/src/hotspot/share/runtime/vmThread.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/runtime/vmThread.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "oops/method.hpp" #include "oops/oop.inline.hpp" #include "oops/verifyOopClosure.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/services/lowMemoryDetector.cpp --- a/src/hotspot/share/services/lowMemoryDetector.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/services/lowMemoryDetector.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ #include "classfile/vmSymbols.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/utilities/debug.cpp --- a/src/hotspot/share/utilities/debug.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/utilities/debug.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -92,6 +92,21 @@ # endif #endif // PRODUCT +#ifdef ASSERT +// This is to test that error reporting works if we assert during dynamic +// initialization of the hotspot. See JDK-8214975. +struct Crasher { + Crasher() { + // Using getenv - no other mechanism would work yet. + const char* s = ::getenv("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION"); + if (s != NULL && ::strcmp(s, "1") == 0) { + fatal("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION"); + } + } +}; +static Crasher g_crasher; +#endif // ASSERT + ATTRIBUTE_PRINTF(1, 2) void warning(const char* format, ...) { if (PrintWarnings) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/utilities/vmError.cpp --- a/src/hotspot/share/utilities/vmError.cpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/utilities/vmError.cpp Mon Feb 04 15:00:29 2019 -0500 @@ -1189,16 +1189,6 @@ volatile intptr_t VMError::first_error_tid = -1; -// An error could happen before tty is initialized or after it has been -// destroyed. -// Please note: to prevent large stack allocations, the log- and -// output-stream use a global scratch buffer for format printing. -// (see VmError::report_and_die(). Access to those streams is synchronized -// in VmError::report_and_die() - there is only one reporting thread at -// any given time. -fdStream VMError::out(defaultStream::output_fd()); -fdStream VMError::log; // error log used by VMError::report_and_die() - /** Expand a pattern into a buffer starting at pos and open a file using constructed path */ static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) { int fd = -1; @@ -1303,9 +1293,25 @@ Thread* thread, address pc, void* siginfo, void* context, const char* filename, int lineno, size_t size) { - // Don't allocate large buffer on stack + // A single scratch buffer to be used from here on. + // Do not rely on it being preserved across function calls. static char buffer[O_BUFLEN]; + + // File descriptor to tty to print an error summary to. + // Hard wired to stdout; see JDK-8215004 (compatibility concerns). + static const int fd_out = 1; // stdout + + // File descriptor to the error log file. + static int fd_log = -1; + + // Use local fdStream objects only. Do not use global instances whose initialization + // relies on dynamic initialization (see JDK-8214975). Do not rely on these instances + // to carry over into recursions or invocations from other threads. + fdStream out(fd_out); out.set_scratch_buffer(buffer, sizeof(buffer)); + + // Depending on the re-entrance depth at this point, fd_log may be -1 or point to an open hs-err file. + fdStream log(fd_log); log.set_scratch_buffer(buffer, sizeof(buffer)); // How many errors occurred in error handler when reporting first_error. @@ -1451,15 +1457,15 @@ // see if log file is already open if (!log.is_open()) { // open log file - int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); - if (fd != -1) { + fd_log = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); + if (fd_log != -1) { out.print_raw("# An error report file with more information is saved as:\n# "); out.print_raw_cr(buffer); - log.set_fd(fd); + log.set_fd(fd_log); } else { out.print_raw_cr("# Can not save log file, dump to screen.."); - log.set_fd(defaultStream::output_fd()); + log.set_fd(fd_out); } } @@ -1468,8 +1474,9 @@ _current_step = 0; _current_step_info = ""; - if (log.fd() != defaultStream::output_fd()) { - close(log.fd()); + if (fd_log != -1) { + close(fd_log); + fd_log = -1; } log.set_fd(-1); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/hotspot/share/utilities/vmError.hpp --- a/src/hotspot/share/utilities/vmError.hpp Sun Feb 03 08:16:08 2019 -0500 +++ b/src/hotspot/share/utilities/vmError.hpp Mon Feb 04 15:00:29 2019 -0500 @@ -122,9 +122,6 @@ void* context, const char* detail_fmt, ...) ATTRIBUTE_PRINTF(6, 7); static void report_and_die(const char* message, const char* detail_fmt, ...) ATTRIBUTE_PRINTF(2, 3); - static fdStream out; - static fdStream log; // error log used by VMError::report_and_die() - // Timeout handling. // Hook functions for platform dependend functionality: static void reporting_started(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.base/share/classes/java/lang/Character.java --- a/src/java.base/share/classes/java/lang/Character.java Sun Feb 03 08:16:08 2019 -0500 +++ b/src/java.base/share/classes/java/lang/Character.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * 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,35 +35,29 @@ /** * The {@code Character} class wraps a value of the primitive - * type {@code char} in an object. An object of type + * type {@code char} in an object. An object of class * {@code Character} contains a single field whose type is * {@code char}. *

- * In addition, this class provides several methods for determining - * a character's category (lowercase letter, digit, etc.) and for converting - * characters from uppercase to lowercase and vice versa. - *

- * Character information is based on the Unicode Standard, version 11.0.0. - *

- * The methods and data of class {@code Character} are defined by - * the information in the UnicodeData file that is part of the - * Unicode Character Database maintained by the Unicode - * Consortium. This file specifies various properties including name - * and general category for every defined Unicode code point or - * character range. + * In addition, this class provides a large number of static methods for + * determining a character's category (lowercase letter, digit, etc.) + * and for converting characters from uppercase to lowercase and vice + * versa. + * + *

Unicode Conformance

*

- * The file and its description are available from the Unicode Consortium at: - *

+ * The fields and methods of class {@code Character} are defined in terms + * of character information from the Unicode Standard, specifically the + * UnicodeData file that is part of the Unicode Character Database. + * This file specifies properties including name and category for every + * assigned Unicode code point or character range. The file is available + * from the Unicode Consortium at + * http://www.unicode.org. *

- * The code point, U+32FF, is reserved by the Unicode Consortium - * to represent the Japanese square character for the new era that begins - * May 2019. Relevant methods in the Character class return the same - * properties as for the existing Japanese era characters (e.g., U+337E for - * "Meizi"). For the details of the code point, refer to - * - * http://blog.unicode.org/2018/09/new-japanese-era.html. + * The Java SE 13 Platform uses character information from version 11.0 + * of the Unicode Standard, plus the Japanese Era code point, + * {@code U+32FF}, from the first version of the Unicode Standard + * after 11.0 that assigns the code point. * *

Unicode Character Representations

* @@ -9495,7 +9489,7 @@ * character in a Java identifier. *

* A character may start a Java identifier if and only if - * one of the following is true: + * one of the following conditions is true: *

    *
  • {@link #isLetter(char) isLetter(ch)} returns {@code true} *
  • {@link #getType(char) getType(ch)} returns {@code LETTER_NUMBER} @@ -9524,8 +9518,8 @@ * Determines if the specified character may be part of a Java * identifier as other than the first character. *

    - * A character may be part of a Java identifier if and only if any - * of the following are true: + * A character may be part of a Java identifier if and only if one + * of the following conditions is true: *

      *
    • it is a letter *
    • it is a currency symbol (such as {@code '$'}) @@ -9667,7 +9661,7 @@ * identifier as other than the first character. *

      * A character may be part of a Java identifier if any of the following - * are true: + * conditions are true: *

        *
      • it is a letter *
      • it is a currency symbol (such as {@code '$'}) @@ -9704,7 +9698,7 @@ * identifier as other than the first character. *

        * A character may be part of a Java identifier if any of the following - * are true: + * conditions are true: *

          *
        • it is a letter *
        • it is a currency symbol (such as {@code '$'}) @@ -9715,7 +9709,7 @@ *
        • it is a non-spacing mark *
        • {@link #isIdentifierIgnorable(int) * isIdentifierIgnorable(codePoint)} returns {@code true} for - * the character + * the code point *
        * * @param codePoint the character (Unicode code point) to be tested. diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.base/share/classes/java/time/chrono/JapaneseEra.java --- a/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Sun Feb 03 08:16:08 2019 -0500 +++ b/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Mon Feb 04 15:00:29 2019 -0500 @@ -88,15 +88,33 @@ /** * An era in the Japanese Imperial calendar system. *

        - * This class defines the valid eras for the Japanese chronology. - * Japan introduced the Gregorian calendar starting with Meiji 6. - * Only Meiji and later eras are supported; - * dates before Meiji 6, January 1 are not supported. - * The number of the valid eras may increase, as new eras may be - * defined by the Japanese government. Once an era is defined, - * future versions of the platform may add a singleton instance - * for it. The defined era is expected to have a consecutive integer - * associated with it. + * The Japanese government defines the official name and start date of + * each era. Eras are consecutive and their date ranges do not overlap, + * so the end date of one era is always the day before the start date + * of the next era. + *

        + * The Java SE Platform supports all eras defined by the Japanese government, + * beginning with the Meiji era. Each era is identified in the Platform by an + * integer value and a name. The {@link #of(int)} and {@link #valueOf(String)} + * methods may be used to obtain a singleton instance of {@code JapaneseEra} + * for each era. The {@link #values()} method returns the singleton instances + * of all supported eras. + *

        + * For convenience, this class declares a number of public static final fields + * that refer to singleton instances returned by the {@link #values()} method. + * + * @apiNote + * The fields declared in this class may evolve over time, in line with the + * results of the {@link #values()} method. However, there is not necessarily + * a 1:1 correspondence between the fields and the singleton instances. + * + * @apiNote + * The Japanese government may announce a new era and define its start + * date but not its official name. In this scenario, the singleton instance + * that represents the new era may return a name that is not stable until + * the official name is defined. Developers should exercise caution when + * relying on the name returned by any singleton instance that does not + * correspond to a public static final field. * * @implSpec * This class is immutable and thread-safe. @@ -199,14 +217,18 @@ //----------------------------------------------------------------------- /** * Obtains an instance of {@code JapaneseEra} from an {@code int} value. + *

          + *
        • The value {@code 1} is associated with the 'Showa' era, because + * it contains 1970-01-01 (ISO calendar system).
        • + *
        • The values {@code -1} and {@code 0} are associated with two earlier + * eras, Meiji and Taisho, respectively.
        • + *
        • A value greater than {@code 1} is associated with a later era, + * beginning with Heisei ({@code 2}).
        • + *
        *

        - * The {@link #SHOWA} era that contains 1970-01-01 (ISO calendar system) has the value 1. - * Later era is numbered 2 ({@link #HEISEI}). Earlier eras are numbered 0 ({@link #TAISHO}), - * -1 ({@link #MEIJI}), only Meiji and later eras are supported. - *

        - * In addition to the known era singletons, values for additional - * eras may be defined. Those values are the {@link Era#getValue()} - * of corresponding eras from the {@link #values()} method. + * Every instance of {@code JapaneseEra} that is returned from the {@link #values()} + * method has an int value (available via {@link Era#getValue()} which is + * accepted by this method. * * @param japaneseEra the era to represent * @return the {@code JapaneseEra} singleton, not null diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.base/share/classes/java/util/jar/Attributes.java --- a/src/java.base/share/classes/java/util/jar/Attributes.java Sun Feb 03 08:16:08 2019 -0500 +++ b/src/java.base/share/classes/java/util/jar/Attributes.java Mon Feb 04 15:00:29 2019 -0500 @@ -265,9 +265,10 @@ } /** - * Compares the specified Attributes object with this Map for equality. - * Returns true if the given object is also an instance of Attributes - * and the two Attributes objects represent the same mappings. + * Compares the specified object to the underlying + * {@linkplain Attributes#map map} for equality. + * Returns true if the given object is also a Map + * and the two maps represent the same mappings. * * @param o the Object to be compared * @return true if the specified Object is equal to this Map diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.desktop/share/legal/mesa3d.md --- a/src/java.desktop/share/legal/mesa3d.md Sun Feb 03 08:16:08 2019 -0500 +++ b/src/java.desktop/share/legal/mesa3d.md Mon Feb 04 15:00:29 2019 -0500 @@ -1,10 +1,10 @@ -## Mesa 3-D Graphics Library v4.1 +## Mesa 3-D Graphics Library v5.0 ### Mesa License

         
         Mesa 3-D graphics library
        -Version:  4.1
        +Version:  5.0
         
         Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
         
        diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.xml/share/classes/com/sun/org/apache/xpath/internal/SourceTreeManager.java
        --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/SourceTreeManager.java	Sun Feb 03 08:16:08 2019 -0500
        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
        @@ -1,391 +0,0 @@
        -/*
        - * Copyright (c) 2017, 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
        - * this work for additional information regarding copyright ownership.
        - * The ASF licenses this file to You under the Apache License, Version 2.0
        - * (the "License"); you may not use this file except in compliance with
        - * the License.  You may obtain a copy of the License at
        - *
        - *      http://www.apache.org/licenses/LICENSE-2.0
        - *
        - * Unless required by applicable law or agreed to in writing, software
        - * distributed under the License is distributed on an "AS IS" BASIS,
        - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        - * See the License for the specific language governing permissions and
        - * limitations under the License.
        - */
        -
        -package com.sun.org.apache.xpath.internal;
        -
        -import com.sun.org.apache.xml.internal.dtm.DTM;
        -import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
        -import java.io.IOException;
        -import java.util.ArrayList;
        -import java.util.List;
        -import javax.xml.transform.Source;
        -import javax.xml.transform.SourceLocator;
        -import javax.xml.transform.TransformerException;
        -import javax.xml.transform.URIResolver;
        -import javax.xml.transform.sax.SAXSource;
        -import javax.xml.transform.stream.StreamSource;
        -import org.xml.sax.XMLReader;
        -import org.xml.sax.helpers.XMLReaderFactory;
        -
        -/**
        - * This class bottlenecks all management of source trees.  The methods
        - * in this class should allow easy garbage collection of source
        - * trees (not yet!), and should centralize parsing for those source trees.
        - *
        - * @LastModified: Oct 2017
        - */
        -@SuppressWarnings("deprecation")
        -public class SourceTreeManager
        -{
        -
        -  /** List of SourceTree objects that this manager manages. */
        -  private List m_sourceTree = new ArrayList<>();
        -
        -  /**
        -   * Reset the list of SourceTree objects that this manager manages.
        -   *
        -   */
        -  public void reset()
        -  {
        -    m_sourceTree = new ArrayList<>();
        -  }
        -
        -  /** The TrAX URI resolver used to obtain source trees. */
        -  URIResolver m_uriResolver;
        -
        -  /**
        -   * Set an object that will be used to resolve URIs used in
        -   * document(), etc.
        -   * @param resolver An object that implements the URIResolver interface,
        -   * or null.
        -   */
        -  public void setURIResolver(URIResolver resolver)
        -  {
        -    m_uriResolver = resolver;
        -  }
        -
        -  /**
        -   * Get the object that will be used to resolve URIs used in
        -   * document(), etc.
        -   * @return An object that implements the URIResolver interface,
        -   * or null.
        -   */
        -  public URIResolver getURIResolver()
        -  {
        -    return m_uriResolver;
        -  }
        -
        -  /**
        -   * Given a document, find the URL associated with that document.
        -   * @param owner Document that was previously processed by this liaison.
        -   *
        -   * @return The base URI of the owner argument.
        -   */
        -  public String findURIFromDoc(int owner)
        -  {
        -    int n = m_sourceTree.size();
        -
        -    for (int i = 0; i < n; i++)
        -    {
        -      SourceTree sTree = m_sourceTree.get(i);
        -
        -      if (owner == sTree.m_root)
        -        return sTree.m_url;
        -    }
        -
        -    return null;
        -  }
        -
        -  /**
        -   * This will be called by the processor when it encounters
        -   * an xsl:include, xsl:import, or document() function.
        -   *
        -   * @param base The base URI that should be used.
        -   * @param urlString Value from an xsl:import or xsl:include's href attribute,
        -   * or a URI specified in the document() function.
        -   *
        -   * @return a Source that can be used to process the resource.
        -   *
        -   * @throws IOException
        -   * @throws TransformerException
        -   */
        -  public Source resolveURI(
        -          String base, String urlString, SourceLocator locator)
        -            throws TransformerException, IOException
        -  {
        -
        -    Source source = null;
        -
        -    if (null != m_uriResolver)
        -    {
        -      source = m_uriResolver.resolve(urlString, base);
        -    }
        -
        -    if (null == source)
        -    {
        -      String uri = SystemIDResolver.getAbsoluteURI(urlString, base);
        -
        -      source = new StreamSource(uri);
        -    }
        -
        -    return source;
        -  }
        -
        -  /** JJK: Support   kluge in ElemForEach.
        -   * TODO: This function is highly dangerous. Cache management must be improved.
        -   *
        -   * @param n The node to remove.
        -   */
        -  public void removeDocumentFromCache(int n)
        -  {
        -    if(DTM.NULL ==n)
        -      return;
        -    for(int i=m_sourceTree.size()-1;i>=0;--i)
        -    {
        -      SourceTree st= m_sourceTree.get(i);
        -      if(st!=null && st.m_root==n)
        -      {
        -        m_sourceTree.remove(i);
        -        return;
        -      }
        -    }
        -  }
        -
        -
        -
        -  /**
        -   * Put the source tree root node in the document cache.
        -   * TODO: This function needs to be a LOT more sophisticated.
        -   *
        -   * @param n The node to cache.
        -   * @param source The Source object to cache.
        -   */
        -  public void putDocumentInCache(int n, Source source)
        -  {
        -
        -    int cachedNode = getNode(source);
        -
        -    if (DTM.NULL != cachedNode)
        -    {
        -      if (!(cachedNode == n))
        -        throw new RuntimeException(
        -          "Programmer's Error!  "
        -          + "putDocumentInCache found reparse of doc: "
        -          + source.getSystemId());
        -      return;
        -    }
        -    if (null != source.getSystemId())
        -    {
        -      m_sourceTree.add(new SourceTree(n, source.getSystemId()));
        -    }
        -  }
        -
        -  /**
        -   * Given a Source object, find the node associated with it.
        -   *
        -   * @param source The Source object to act as the key.
        -   *
        -   * @return The node that is associated with the Source, or null if not found.
        -   */
        -  public int getNode(Source source)
        -  {
        -
        -//    if (source instanceof DOMSource)
        -//      return ((DOMSource) source).getNode();
        -
        -    // TODO: Not sure if the BaseID is really the same thing as the ID.
        -    String url = source.getSystemId();
        -
        -    if (null == url)
        -      return DTM.NULL;
        -
        -    int n = m_sourceTree.size();
        -
        -    // System.out.println("getNode: "+n);
        -    for (int i = 0; i < n; i++)
        -    {
        -      SourceTree sTree = m_sourceTree.get(i);
        -
        -      // System.out.println("getNode -         url: "+url);
        -      // System.out.println("getNode - sTree.m_url: "+sTree.m_url);
        -      if (url.equals(sTree.m_url))
        -        return sTree.m_root;
        -    }
        -
        -    // System.out.println("getNode - returning: "+node);
        -    return DTM.NULL;
        -  }
        -
        -  /**
        -   * Get the source tree from the a base URL and a URL string.
        -   *
        -   * @param base The base URI to use if the urlString is relative.
        -   * @param urlString An absolute or relative URL string.
        -   * @param locator The location of the caller, for diagnostic purposes.
        -   *
        -   * @return should be a non-null reference to the node identified by the
        -   * base and urlString.
        -   *
        -   * @throws TransformerException If the URL can not resolve to a node.
        -   */
        -  public int getSourceTree(
        -          String base, String urlString, SourceLocator locator, XPathContext xctxt)
        -            throws TransformerException
        -  {
        -
        -    // System.out.println("getSourceTree");
        -    try
        -    {
        -      Source source = this.resolveURI(base, urlString, locator);
        -
        -      // System.out.println("getSourceTree - base: "+base+", urlString: "+urlString+", source: "+source.getSystemId());
        -      return getSourceTree(source, locator, xctxt);
        -    }
        -    catch (IOException ioe)
        -    {
        -      throw new TransformerException(ioe.getMessage(), locator, ioe);
        -    }
        -
        -    /* catch (TransformerException te)
        -     {
        -       throw new TransformerException(te.getMessage(), locator, te);
        -     }*/
        -  }
        -
        -  /**
        -   * Get the source tree from the input source.
        -   *
        -   * @param source The Source object that should identify the desired node.
        -   * @param locator The location of the caller, for diagnostic purposes.
        -   *
        -   * @return non-null reference to a node.
        -   *
        -   * @throws TransformerException if the Source argument can't be resolved to
        -   *         a node.
        -   */
        -  public int getSourceTree(Source source, SourceLocator locator, XPathContext xctxt)
        -          throws TransformerException
        -  {
        -
        -    int n = getNode(source);
        -
        -    if (DTM.NULL != n)
        -      return n;
        -
        -    n = parseToNode(source, locator, xctxt);
        -
        -    if (DTM.NULL != n)
        -      putDocumentInCache(n, source);
        -
        -    return n;
        -  }
        -
        -  /**
        -   * Try to create a DOM source tree from the input source.
        -   *
        -   * @param source The Source object that identifies the source node.
        -   * @param locator The location of the caller, for diagnostic purposes.
        -   *
        -   * @return non-null reference to node identified by the source argument.
        -   *
        -   * @throws TransformerException if the source argument can not be resolved
        -   *         to a source node.
        -   */
        -  public int parseToNode(Source source, SourceLocator locator, XPathContext xctxt)
        -          throws TransformerException
        -  {
        -
        -    try
        -    {
        -      Object xowner = xctxt.getOwnerObject();
        -      DTM dtm;
        -      if(null != xowner && xowner instanceof com.sun.org.apache.xml.internal.dtm.DTMWSFilter)
        -      {
        -        dtm = xctxt.getDTM(source, false,
        -                          (com.sun.org.apache.xml.internal.dtm.DTMWSFilter)xowner, false, true);
        -      }
        -      else
        -      {
        -        dtm = xctxt.getDTM(source, false, null, false, true);
        -      }
        -      return dtm.getDocument();
        -    }
        -    catch (Exception e)
        -    {
        -      //e.printStackTrace();
        -      throw new TransformerException(e.getMessage(), locator, e);
        -    }
        -
        -  }
        -
        -  /**
        -   * This method returns the SAX2 parser to use with the InputSource
        -   * obtained from this URI.
        -   * It may return null if any SAX2-conformant XML parser can be used,
        -   * or if getInputSource() will also return null. The parser must
        -   * be free for use (i.e.
        -   * not currently in use for another parse().
        -   *
        -   * @param inputSource The value returned from the URIResolver.
        -   * @return a SAX2 XMLReader to use to resolve the inputSource argument.
        -   * @param locator The location of the original caller, for diagnostic purposes.
        -   *
        -   * @throws TransformerException if the reader can not be created.
        -   */
        -  public static XMLReader getXMLReader(Source inputSource, SourceLocator locator)
        -          throws TransformerException
        -  {
        -
        -    try
        -    {
        -      XMLReader reader = (inputSource instanceof SAXSource)
        -                         ? ((SAXSource) inputSource).getXMLReader() : null;
        -
        -      if (null == reader)
        -      {
        -        try {
        -          javax.xml.parsers.SAXParserFactory factory=
        -              javax.xml.parsers.SAXParserFactory.newInstance();
        -          factory.setNamespaceAware( true );
        -          javax.xml.parsers.SAXParser jaxpParser=
        -              factory.newSAXParser();
        -          reader=jaxpParser.getXMLReader();
        -
        -        } catch( javax.xml.parsers.ParserConfigurationException ex ) {
        -          throw new org.xml.sax.SAXException( ex );
        -        } catch( javax.xml.parsers.FactoryConfigurationError ex1 ) {
        -            throw new org.xml.sax.SAXException( ex1.toString() );
        -        } catch( NoSuchMethodError ex2 ) {
        -        }
        -        catch (AbstractMethodError ame){}
        -        if(null == reader)
        -          reader = XMLReaderFactory.createXMLReader();
        -      }
        -
        -      try
        -      {
        -        reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
        -                          true);
        -      }
        -      catch (org.xml.sax.SAXException se)
        -      {
        -
        -        // What can we do?
        -        // TODO: User diagnostics.
        -      }
        -
        -      return reader;
        -    }
        -    catch (org.xml.sax.SAXException se)
        -    {
        -      throw new TransformerException(se.getMessage(), locator, se);
        -    }
        -  }
        -}
        diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPathContext.java
        --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPathContext.java	Sun Feb 03 08:16:08 2019 -0500
        +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/XPathContext.java	Mon Feb 04 15:00:29 2019 -0500
        @@ -1,5 +1,5 @@
         /*
        - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
        + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
          */
         /*
          * Licensed to the Apache Software Foundation (ASF) under one or more
        @@ -49,7 +49,6 @@
         import javax.xml.transform.ErrorListener;
         import javax.xml.transform.SourceLocator;
         import javax.xml.transform.URIResolver;
        -import jdk.xml.internal.JdkXmlUtils;
         import org.xml.sax.XMLReader;
         
         /**
        @@ -57,7 +56,7 @@
          *
          * 

        This class extends DTMManager but does not directly implement it.

        * @xsl.usage advanced - * @LastModified: Oct 2017 + * @LastModified: Jan 2019 */ public class XPathContext extends DTMManager // implements ExpressionContext { @@ -483,33 +482,6 @@ m_variableStacks = varStack; } - // ================ SourceTreeManager =================== - - /** The source tree manager, which associates Source objects to source - * tree nodes. */ - private SourceTreeManager m_sourceTreeManager = new SourceTreeManager(); - - /** - * Get the SourceTreeManager associated with this execution context. - * - * @return the SourceTreeManager associated with this execution context. - */ - public final SourceTreeManager getSourceTreeManager() - { - return m_sourceTreeManager; - } - - /** - * Set the SourceTreeManager associated with this execution context. - * - * @param mgr the SourceTreeManager to be associated with this - * execution context. - */ - public void setSourceTreeManager(SourceTreeManager mgr) - { - m_sourceTreeManager = mgr; - } - // ================================================= /** The ErrorListener where errors and warnings are to be reported. */ diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncDoclocation.java --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncDoclocation.java Sun Feb 03 08:16:08 2019 -0500 +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncDoclocation.java Mon Feb 04 15:00:29 2019 -0500 @@ -62,8 +62,6 @@ if (DTM.NULL != whereNode) { fileLocation = dtm.getDocumentBaseURI(); -// int owner = dtm.getDocument(); -// fileLocation = xctxt.getSourceTreeManager().findURIFromDoc(owner); } } diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/jdk.javadoc/share/legal/jquery.md --- a/src/jdk.javadoc/share/legal/jquery.md Sun Feb 03 08:16:08 2019 -0500 +++ b/src/jdk.javadoc/share/legal/jquery.md Mon Feb 04 15:00:29 2019 -0500 @@ -3,8 +3,7 @@ ### jQuery License ``` jQuery v 3.3.1 -Copyright 2005, 2018 jQuery Foundation, Inc. and other contributors -http://jquery.com/ +Copyright JS Foundation and other contributors, https://js.foundation/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff -r 3dcb33ce7ced -r e7ba8c89abe7 src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c --- a/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c Sun Feb 03 08:16:08 2019 -0500 +++ b/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -752,6 +752,7 @@ holdEvents = JNI_FALSE; debugMonitorNotifyAll(commandQueueLock); debugMonitorExit(commandQueueLock); + unblockCommandLoop(); } /* diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/ProblemList-Xcomp.txt --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. # 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,4 +27,4 @@ # ############################################################################# -vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java 8208235 solaris-all +vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java 8058176 solaris-all diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/ProblemList-graal.txt --- a/test/hotspot/jtreg/ProblemList-graal.txt Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/ProblemList-graal.txt Mon Feb 04 15:00:29 2019 -0500 @@ -60,6 +60,8 @@ gc/g1/plab/TestPLABPromotion.java 8191048 generic-all gc/g1/plab/TestPLABResize.java 8191048 generic-all +gc/stress/TestStressG1Humongous.java 8218176 generic-all + compiler/compilercontrol/directives/LogTest.java 8181753 generic-all gc/parallel/TestPrintGCDetailsVerbose.java 8196611 macosx-all @@ -109,8 +111,6 @@ vmTestbase/vm/mlvm/anonloader/stress/oome/metaspace/Test.java 8186299 generic-all # jvmti tests -vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretbase/TestDescription.java 8195635 generic-all - vmTestbase/nsk/jvmti/PopFrame/popframe009/TestDescription.java 8195639 generic-all vmTestbase/nsk/jvmti/ForceEarlyReturn/ForceEarlyReturn001/TestDescription.java 8195674 generic-all @@ -127,6 +127,61 @@ serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java 8202482 generic-all +# tests require pop_frame and force_early_return capabilities +vmTestbase/nsk/jdb/pop/pop001/pop001.java 8195635 generic-all +vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java 8195635 generic-all +vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc01x002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc02x002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc04x002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc06x001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc08x001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/BScenarios/hotswap/tc10x002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/MethodExitEvent/returnValue/returnValue003/returnValue003.java 8195635 generic-all +vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.jav 8195635 generic-all +vmTestbase/nsk/jdi/Scenarios/invokeMethod/popframes001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/stress/serial/forceEarlyReturn002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdi/stress/serial/mixed002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java 8195635 generic-all +vmTestbase/nsk/jvmti/ForceEarlyReturn/ForceEarlyReturn001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/ForceEarlyReturn/ForceEarlyReturn002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/PopFrame/popframe001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/PopFrame/popframe003/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/PopFrame/popframe005/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/capability/CM01/cm01t007/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t001/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS202/hs202t002/hs202t002.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t001/hs203t001.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t003/hs203t003.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t004/hs203t004.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t001/hs204t001.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t003/hs204t003.java 8195635 generic-all +vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t004/hs204t004.java 8195635 generic-all +vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretbase/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretfp/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretint/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretlong/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretobj/TestDescription.java 8195635 generic-all +vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretstr/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_a/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_b/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2same_a/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2same_b/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_none2indy_a/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_none2indy_b/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/redefineClassInTarget/TestDescription.java 8195635 generic-all +vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/INDIFY_Test.java 8195635 generic-all + compiler/stable/TestStableBoolean.java 8204347 generic-all compiler/stable/TestStableByte.java 8204347 generic-all compiler/stable/TestStableChar.java 8204347 generic-all diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/ProblemList.txt --- a/test/hotspot/jtreg/ProblemList.txt Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/ProblemList.txt Mon Feb 04 15:00:29 2019 -0500 @@ -57,9 +57,9 @@ compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x -applications/ctw/modules/java_desktop.java 8217851 windows-all -applications/ctw/modules/java_desktop_2.java 8217851 windows-all -applications/ctw/modules/jdk_jconsole.java 8217851 windows-all +applications/ctw/modules/java_desktop.java 8189604 windows-all +applications/ctw/modules/java_desktop_2.java 8189604 windows-all +applications/ctw/modules/jdk_jconsole.java 8189604 windows-all ############################################################################# @@ -67,12 +67,12 @@ gc/epsilon/TestMemoryMXBeans.java 8206434 generic-all gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all -gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all +gc/survivorAlignment/TestPromotionToSurvivor.java 8218049 generic-all +gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8218049 generic-all gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8177765 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8193639 solaris-all @@ -171,7 +171,7 @@ vmTestbase/metaspace/gc/firstGC_default/TestDescription.java 8208250 generic-all vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java 6606767 generic-all -vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java 7013634,6606767 generic-all +vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java 6606767 generic-all vmTestbase/nsk/jvmti/scenarios/extension/EX03/ex03t001/TestDescription.java 8173658 generic-all vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java 8202971 generic-all @@ -181,14 +181,14 @@ vmTestbase/jit/escape/LockCoarsening/LockCoarsening002/TestDescription.java 8208259 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/redefineClassInBootstrap/TestDescription.java 8013267 generic-all -vmTestbase/vm/mlvm/meth/func/java/throwException/Test.java 8208255 generic-all -vmTestbase/vm/mlvm/meth/func/jdi/breakpointOtherStratum/Test.java 8208257,8208255 generic-all -vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java 8208255 generic-all -vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java 8208255 generic-all -vmTestbase/vm/mlvm/meth/stress/compiler/sequences/Test.java 8208255 generic-all -vmTestbase/vm/mlvm/meth/stress/gc/callSequencesDuringGC/Test.java 8208255 generic-all -vmTestbase/vm/mlvm/meth/stress/java/sequences/Test.java 8208255 generic-all -vmTestbase/vm/mlvm/meth/stress/jdi/breakpointInCompiledCode/Test.java 8208255 generic-all +vmTestbase/vm/mlvm/meth/func/java/throwException/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/func/jdi/breakpointOtherStratum/Test.java 8208257,8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/sequences/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/gc/callSequencesDuringGC/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/java/sequences/Test.java 8058176 generic-all +vmTestbase/vm/mlvm/meth/stress/jdi/breakpointInCompiledCode/Test.java 8058176 generic-all vmTestbase/vm/mlvm/mixed/stress/java/findDeadlock/TestDescription.java 8208278 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_a/TestDescription.java 8013267 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_b/TestDescription.java 8013267 generic-all diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/compiler/aot/AotCompiler.java --- a/test/hotspot/jtreg/compiler/aot/AotCompiler.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/compiler/aot/AotCompiler.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,6 +117,8 @@ // Execute with asserts args.add("-J-ea"); args.add("-J-esa"); + // we don't want to run jaotc w/ Xcomp even if it's in extraopts + args.add("-J-Xmixed"); return launchJaotc(args, extraopts); } diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java Mon Feb 04 15:00:29 2019 -0500 @@ -0,0 +1,970 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 + * @requires !vm.graal.enabled + * @modules java.base/jdk.internal.org.objectweb.asm + * java.base/jdk.internal.misc + * java.base/jdk.internal.vm.annotation + * @library /test/lib / + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet + * -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=compileonly,*::m -XX:CompileCommand=dontinline,*::test + * -Xbatch -XX:+WhiteBoxAPI -Xmixed + * -XX:-TieredCompilation + * compiler.cha.StrengthReduceInterfaceCall + * + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet + * -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=compileonly,*::m -XX:CompileCommand=dontinline,*::test + * -Xbatch -XX:+WhiteBoxAPI -Xmixed + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * compiler.cha.StrengthReduceInterfaceCall + */ +package compiler.cha; + +import jdk.internal.misc.Unsafe; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.vm.annotation.DontInline; +import sun.hotspot.WhiteBox; + +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.concurrent.Callable; + +import static jdk.test.lib.Asserts.*; +import static jdk.internal.org.objectweb.asm.ClassWriter.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +public class StrengthReduceInterfaceCall { + public static void main(String[] args) { + run(ObjectToString.class); + run(ObjectHashCode.class); + run(TwoLevelHierarchyLinear.class); + run(ThreeLevelHierarchyLinear.class); + run(ThreeLevelHierarchyAbstractVsDefault.class); + run(ThreeLevelDefaultHierarchy.class); + run(ThreeLevelDefaultHierarchy1.class); + } + + public static class ObjectToString extends ATest { + public ObjectToString() { super(I.class, C.class); } + + interface J { String toString(); } + interface I extends J {} + + static class C implements I {} + + interface K1 extends I {} + interface K2 extends I { String toString(); } // K2.tS() ABSTRACT + // interface K3 extends I { default String toString() { return "K3"; } // K2.tS() DEFAULT + + static class D implements I { public String toString() { return "D"; }} + + static class DJ1 implements J {} + static class DJ2 implements J { public String toString() { return "DJ2"; }} + + @Override + public Object test(I i) { return ObjectToStringHelper.test(i); /* invokeinterface I.toString() */ } + + @TestCase + public void testMono() { + // 0. Trigger compilation of a monomorphic call site + compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.toString() + assertCompiled(); + + // Dependency: none + + call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I + assertCompiled(); + } + + @TestCase + public void testBi() { + // 0. Trigger compilation of a bimorphic call site + compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString() + assertCompiled(); + + // Dependency: none + + call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I + assertCompiled(); + } + + @TestCase + public void testMega() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.toString() + assertCompiled(); + + // Dependency: none + // compiler.cha.StrengthReduceInterfaceCall$ObjectToString::test (5 bytes) + // @ 1 compiler.cha.StrengthReduceInterfaceCall$ObjectToStringHelper::test (7 bytes) inline (hot) + // @ 1 java.lang.Object::toString (36 bytes) virtual call + + // No dependency - no invalidation + repeat(100, () -> call(new C(){})); // Cn <: C <: intf I + assertCompiled(); + + initialize(K1.class, // intf K1 <: intf I <: intf J + K2.class, // intf K2.tS ABSTRACT <: intf I <: intf J + DJ1.class, // DJ1 <: intf J + DJ2.class); // DJ2.tS <: intf J + assertCompiled(); + + initialize(D.class); // D.tS <: intf I <: intf J + assertCompiled(); + + call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I + assertCompiled(); + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface + test(j); + }); + assertCompiled(); + } + } + + public static class ObjectHashCode extends ATest { + public ObjectHashCode() { super(I.class, C.class); } + + interface J {} + interface I extends J {} + + static class C implements I {} + + interface K1 extends I {} + interface K2 extends I { int hashCode(); } // K2.hC() ABSTRACT + // interface K3 extends I { default int hashCode() { return CORRECT; } // K2.hC() DEFAULT + + static class D implements I { public int hashCode() { return super.hashCode(); }} + + static class DJ1 implements J {} + static class DJ2 implements J { public int hashCode() { return super.hashCode(); }} + + @Override + public Object test(I i) { + return ObjectHashCodeHelper.test(i); /* invokeinterface I.hashCode() */ + } + + @TestCase + public void testMono() { + // 0. Trigger compilation of a monomorphic call site + compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.hashCode() + assertCompiled(); + + // Dependency: none + + call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I + assertCompiled(); + } + + @TestCase + public void testBi() { + // 0. Trigger compilation of a bimorphic call site + compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString() + assertCompiled(); + + // Dependency: none + + call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I + assertCompiled(); + } + + @TestCase + public void testMega() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.hashCode() + assertCompiled(); + + // Dependency: none + + // No dependency - no invalidation + repeat(100, () -> call(new C(){})); // Cn <: C <: intf I + assertCompiled(); + + initialize(K1.class, // intf K1 <: intf I <: intf J + K2.class, // intf K2.hC ABSTRACT <: intf I <: intf J + DJ1.class, // DJ1 <: intf J + DJ2.class); // DJ2.hC <: intf J + assertCompiled(); + + initialize(D.class); // D.hC <: intf I <: intf J + assertCompiled(); + + call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I + assertCompiled(); + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface + test(j); + }); + assertCompiled(); + } + } + + public static class TwoLevelHierarchyLinear extends ATest { + public TwoLevelHierarchyLinear() { super(I.class, C.class); } + + interface J { default Object m() { return WRONG; } } + + interface I extends J { Object m(); } + static class C implements I { public Object m() { return CORRECT; }} + + interface K1 extends I {} + interface K2 extends I { Object m(); } + interface K3 extends I { default Object m() { return WRONG; }} + + static class D implements I { public Object m() { return WRONG; }} + + static class DJ1 implements J {} + static class DJ2 implements J { public Object m() { return WRONG; }} + + @DontInline + public Object test(I i) { + return i.m(); + } + + @TestCase + public void testMega1() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m ABSTRACT + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check is preserved + + // 1. No deoptimization/invalidation on not-yet-seen receiver + repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT + assertCompiled(); + + // 2. No dependency invalidation on class loading of unrelated classes: different context + initialize(K1.class, // intf K1 <: intf I.m ABSTRACT <: intf J.m DEFAULT + K2.class, // intf K2.m ABSTRACT <: intf I.m ABSTRACT <: intf J.m DEFAULT + DJ1.class, // DJ1 <: intf J.m DEFAULT + DJ2.class); // DJ2.m <: intf J.m DEFAULT + assertCompiled(); + + // 3. Dependency invalidation on D <: I + initialize(D.class); // D.m <: intf I.m ABSTRACT <: intf J.m DEFAULT + assertNotCompiled(); + + // 4. Recompilation: no inlining, no dependencies + compile(megamorphic()); + call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT + assertCompiled(); + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + } + + @TestCase + public void testMega2() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // 1. Dependency invalidation + initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT + assertNotCompiled(); + + // 2. Recompilation: still inlines + // FIXME: no default method support in CHA yet + compile(megamorphic()); + call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT + assertNotCompiled(); + + // 3. Recompilation: no inlining, no dependencies + compile(megamorphic()); + call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT + assertCompiled(); + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface + test(j); + }); + assertCompiled(); + } + } + + public static class ThreeLevelHierarchyLinear extends ATest { + public ThreeLevelHierarchyLinear() { super(I.class, C.class); } + + interface J { Object m(); } + interface I extends J {} + + interface K1 extends I {} + interface K2 extends I { Object m(); } + interface K3 extends I { default Object m() { return WRONG; }} + + static class C implements I { public Object m() { return CORRECT; }} + + static class DI implements I { public Object m() { return WRONG; }} + static class DJ implements J { public Object m() { return WRONG; }} + + @DontInline + public Object test(I i) { + return i.m(); // I <: J.m ABSTRACT + } + + @TestCase + public void testMega1() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // 1. No deoptimization/invalidation on not-yet-seen receiver + repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I + assertCompiled(); // No deopt on not-yet-seen receiver + + // 2. No dependency invalidation: different context + initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT + K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT + K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT + assertCompiled(); + + // 3. Dependency invalidation: DI.m <: I + initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT + assertNotCompiled(); + + // 4. Recompilation w/o a dependency + compile(megamorphic()); + call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT + assertCompiled(); // no dependency + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + } + + @TestCase + public void testMega2() { + compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // Dependency invalidation + initialize(K3.class); // intf K3.m DEFAULT <: intf I; + assertNotCompiled(); // FIXME: default methods in sub-interfaces shouldn't be taken into account by CHA + + // Recompilation with a dependency + compile(megamorphic()); + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: K3.m DEFAULT <: intf I <: intf J.m ABSTRACT + assertNotCompiled(); + + // Recompilation w/o a dependency + compile(megamorphic()); + // Dependency: none + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT + assertCompiled(); + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() { public Object m() { return WRONG; }}); // super interface + test(j); + }); + assertCompiled(); + } + } + + public static class ThreeLevelHierarchyAbstractVsDefault extends ATest { + public ThreeLevelHierarchyAbstractVsDefault() { super(I.class, C.class); } + + interface J1 { default Object m() { return WRONG; } } // intf J1.m DEFAULT + interface J2 extends J1 { Object m(); } // intf J2.m ABSTRACT <: intf J1 + interface I extends J1, J2 {} // intf I.m OVERPASS <: intf J1,J2 + + static class C implements I { public Object m() { return CORRECT; }} + + @DontInline + public Object test(I i) { + return i.m(); // intf I.m OVERPASS + } + + static class DI implements I { public Object m() { return WRONG; }} + + static class DJ11 implements J1 {} + static class DJ12 implements J1 { public Object m() { return WRONG; }} + + static class DJ2 implements J2 { public Object m() { return WRONG; }} + + interface K11 extends J1 {} + interface K12 extends J1 { Object m(); } + interface K13 extends J1 { default Object m() { return WRONG; }} + interface K21 extends J2 {} + interface K22 extends J2 { Object m(); } + interface K23 extends J2 { default Object m() { return WRONG; }} + + + public void testMega1() { + // 0. Trigger compilation of megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // 1. No deopt/invalidation on not-yet-seen receiver + repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT + assertCompiled(); + + // 2. No dependency invalidation: different context + initialize(K11.class, K12.class, K13.class, + K21.class, K22.class, K23.class); + + // 3. Dependency invalidation: Cn.m <: C <: I + call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT + assertNotCompiled(); + + // 4. Recompilation w/o a dependency + compile(megamorphic()); + call(new C() { public Object m() { return CORRECT; }}); + assertCompiled(); // no inlining + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + } + + public void testMega2() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); + assertCompiled(); + + // Dependency: type = unique_concrete_method, context = I, method = C.m + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // 1. No dependency invalidation: different context + initialize(DJ11.class, + DJ12.class, + DJ2.class); + assertCompiled(); + + // 2. Dependency invalidation: DI.m <: I + initialize(DI.class); + assertNotCompiled(); + + // 3. Recompilation w/o a dependency + compile(megamorphic()); + call(new C() { public Object m() { return CORRECT; }}); + assertCompiled(); // no inlining + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() {}); // super interface + test(j); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() { public Object m() { return WRONG; }}); // super interface + test(j); + }); + assertCompiled(); + } + } + + public static class ThreeLevelDefaultHierarchy extends ATest { + public ThreeLevelDefaultHierarchy() { super(I.class, C.class); } + + interface J { default Object m() { return WRONG; }} + interface I extends J {} + + static class C implements I { public Object m() { return CORRECT; }} + + interface K1 extends I {} + interface K2 extends I { Object m(); } + interface K3 extends I { default Object m() { return WRONG; }} + + static class DI implements I { public Object m() { return WRONG; }} + static class DJ implements J { public Object m() { return WRONG; }} + + @DontInline + public Object test(I i) { + return i.m(); // no inlining since J.m is a default method + } + + @TestCase + public void testMega() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT + assertCompiled(); + + // Dependency: none + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // 1. No deoptimization/invalidation on not-yet-seen receiver + repeat(100, () -> call(new C() {})); + assertCompiled(); + + // 2. No dependency and no inlining + initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT + DI.class, // DI.m <: intf I <: intf J.m ABSTRACT + K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT + K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT + assertCompiled(); + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface + test(j); + }); + assertCompiled(); + } + } + + public static class ThreeLevelDefaultHierarchy1 extends ATest { + public ThreeLevelDefaultHierarchy1() { super(I.class, C.class); } + + interface J1 { Object m();} + interface J2 extends J1 { default Object m() { return WRONG; } } + interface I extends J1, J2 {} + + static class C implements I { public Object m() { return CORRECT; }} + + interface K1 extends I {} + interface K2 extends I { Object m(); } + interface K3 extends I { default Object m() { return WRONG; }} + + static class DI implements I { public Object m() { return WRONG; }} + static class DJ1 implements J1 { public Object m() { return WRONG; }} + static class DJ2 implements J2 { public Object m() { return WRONG; }} + + @DontInline + public Object test(I i) { + return i.m(); // no inlining since J.m is a default method + } + + @TestCase + public void testMega() { + // 0. Trigger compilation of a megamorphic call site + compile(megamorphic()); + assertCompiled(); + + // Dependency: none + + checkInvalidReceiver(); // ensure proper type check on receiver is preserved + + // 1. No deoptimization/invalidation on not-yet-seen receiver + repeat(100, () -> call(new C() {})); + assertCompiled(); + + // 2. No dependency, no inlining + // CHA doesn't support default methods yet. + initialize(DJ1.class, + DJ2.class, + DI.class, + K1.class, + K2.class, + K3.class); + assertCompiled(); + } + + @Override + public void checkInvalidReceiver() { + shouldThrow(IncompatibleClassChangeError.class, () -> { + I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated + test(o); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() { public Object m() { return WRONG; } }); // super interface + test(j); + }); + assertCompiled(); + + shouldThrow(IncompatibleClassChangeError.class, () -> { + I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() {}); // super interface + test(j); + }); + assertCompiled(); + } + } + + /* =========================================================== */ + + interface Action { + int run(); + } + + public static final Unsafe U = Unsafe.getUnsafe(); + + interface Test { + boolean isCompiled(); + void assertNotCompiled(); + void assertCompiled(); + + void call(T o); + T receiver(int id); + + default Runnable monomophic() { + return () -> { + call(receiver(0)); // 100% + }; + } + + default Runnable bimorphic() { + return () -> { + call(receiver(0)); // 50% + call(receiver(1)); // 50% + }; + } + + default Runnable polymorphic() { + return () -> { + for (int i = 0; i < 23; i++) { + call(receiver(0)); // 92% + } + call(receiver(1)); // 4% + call(receiver(2)); // 4% + }; + } + + default Runnable megamorphic() { + return () -> { + call(receiver(0)); // 33% + call(receiver(1)); // 33% + call(receiver(2)); // 33% + }; + } + + default void compile(Runnable r) { + assertNotCompiled(); + while(!isCompiled()) { + r.run(); + } + assertCompiled(); + } + + default void initialize(Class... cs) { + for (Class c : cs) { + U.ensureClassInitialized(c); + } + } + + default void repeat(int cnt, Runnable r) { + for (int i = 0; i < cnt; i++) { + r.run(); + } + } + } + + public static abstract class ATest implements Test { + public static final WhiteBox WB = WhiteBox.getWhiteBox(); + + public static final Object CORRECT = new Object(); + public static final Object WRONG = new Object(); + + final Method TEST; + private final Class declared; + private final Class receiver; + + private final HashMap receivers = new HashMap<>(); + + public ATest(Class declared, Class receiver) { + this.declared = declared; + this.receiver = receiver; + TEST = compute(() -> this.getClass().getDeclaredMethod("test", declared)); + } + + @DontInline + public abstract Object test(T i); + + public abstract void checkInvalidReceiver(); + + public T receiver(int id) { + return receivers.computeIfAbsent(id, (i -> { + try { + MyClassLoader cl = (MyClassLoader) receiver.getClassLoader(); + Class sub = cl.subclass(receiver, i); + return (T)sub.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new Error(e); + } + })); + } + + @Override + public boolean isCompiled() { return WB.isMethodCompiled(TEST); } + + @Override + public void assertNotCompiled() { assertFalse(isCompiled()); } + + @Override + public void assertCompiled() { assertTrue(isCompiled()); } + + @Override + public void call(T i) { + assertTrue(test(i) != WRONG); + } + } + + @Retention(value = RetentionPolicy.RUNTIME) + public @interface TestCase {} + + static void run(Class test) { + try { + for (Method m : test.getDeclaredMethods()) { + if (m.isAnnotationPresent(TestCase.class)) { + System.out.println(m.toString()); + ClassLoader cl = new MyClassLoader(test); + Class c = cl.loadClass(test.getName()); + c.getMethod(m.getName()).invoke(c.getDeclaredConstructor().newInstance()); + } + } + } catch (Exception e) { + throw new Error(e); + } + } + + static class ObjectToStringHelper { + static Object test(Object o) { + throw new Error("not used"); + } + } + static class ObjectHashCodeHelper { + static int test(Object o) { + throw new Error("not used"); + } + } + + static final class MyClassLoader extends ClassLoader { + private final Class test; + + MyClassLoader(Class test) { + this.test = test; + } + + static String intl(String s) { + return s.replace('.', '/'); + } + + Class subclass(Class c, int id) { + String name = c.getName() + id; + Class sub = findLoadedClass(name); + if (sub == null) { + ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, intl(c.getName()), null); + + { // Default constructor: ()V + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, intl(c.getName()), "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + byte[] classFile = cw.toByteArray(); + return defineClass(name, classFile, 0, classFile.length); + } + return sub; + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + if (c == null) { + try { + c = getParent().loadClass(name); + if (name.endsWith("ObjectToStringHelper")) { + ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, "java/lang/Object", null); + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEINTERFACE, intl(test.getName()) + "$I", "toString", "()Ljava/lang/String;", true); + mv.visitInsn(ARETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + byte[] classFile = cw.toByteArray(); + return defineClass(name, classFile, 0, classFile.length); + } else if (name.endsWith("ObjectHashCodeHelper")) { + ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, "java/lang/Object", null); + + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEINTERFACE, intl(test.getName()) + "$I", "hashCode", "()I", true); + mv.visitInsn(IRETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + byte[] classFile = cw.toByteArray(); + return defineClass(name, classFile, 0, classFile.length); + } else if (c == test || name.startsWith(test.getName())) { + try { + String path = name.replace('.', '/') + ".class"; + byte[] classFile = getParent().getResourceAsStream(path).readAllBytes(); + return defineClass(name, classFile, 0, classFile.length); + } catch (IOException e) { + throw new Error(e); + } + } + } catch (ClassNotFoundException e) { + // ClassNotFoundException thrown if class not found + // from the non-null parent class loader + } + + if (c == null) { + // If still not found, then invoke findClass in order + // to find the class. + c = findClass(name); + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + } + + public interface RunnableWithException { + void run() throws Throwable; + } + + public static void shouldThrow(Class expectedException, RunnableWithException r) { + try { + r.run(); + throw new AssertionError("Exception not thrown: " + expectedException.getName()); + } catch(Throwable e) { + if (expectedException == e.getClass()) { + // success: proper exception is thrown + } else { + throw new Error(expectedException.getName() + " is expected", e); + } + } + } + + public static MethodHandle unsafeCastMH(Class cls) { + try { + MethodHandle mh = MethodHandles.identity(Object.class); + return MethodHandles.explicitCastArguments(mh, mh.type().changeReturnType(cls)); + } catch (Throwable e) { + throw new Error(e); + } + } + + static T compute(Callable c) { + try { + return c.call(); + } catch (Exception e) { + throw new Error(e); + } + } +} diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/compiler/codegen/aes/TestCipherBlockChainingEncrypt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/codegen/aes/TestCipherBlockChainingEncrypt.java Mon Feb 04 15:00:29 2019 -0500 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8209951 + * @summary SIGBUS in com.sun.crypto.provider.CipherBlockChaining + * @run main/othervm/timeout=300 -Xbatch + * compiler.codegen.aes.TestCipherBlockChainingEncrypt + */ + +package compiler.codegen.aes; + +import java.io.PrintStream; +import java.security.*; +import java.util.Random; +import java.lang.reflect.Method; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; + +public class TestCipherBlockChainingEncrypt { + private static String algorithm = "PBEWithHmacSHA1AndAES_256"; + private static final String PBEPASS = "Hush, it's supposed to be a secret!"; + + private static final int INPUT_LENGTH = 800; + private static final int[] OFFSETS = {0}; + private static final int NUM_PAD_BYTES = 8; + private static final int PBKDF2_ADD_PAD_BYTES = 8; + + private static SecretKey key; + private static Cipher ci; + + public static void main(String[] args) throws Exception { + for(int i=0; i<5_000; i++) { + if (!(new TestCipherBlockChainingEncrypt().test(args))) { + throw new RuntimeException("TestCipherBlockChainingEncrypt test failed"); + } + } + } + + public boolean test(String[] args) throws Exception { + boolean result = true; + + Provider p = Security.getProvider("SunJCE"); + ci = Cipher.getInstance(algorithm, p); + key = SecretKeyFactory.getInstance(algorithm, p).generateSecret( + new PBEKeySpec(PBEPASS.toCharArray())); + + // generate input data + byte[] inputText = new byte[INPUT_LENGTH + NUM_PAD_BYTES + + PBKDF2_ADD_PAD_BYTES]; + new Random().nextBytes(inputText); + + try { + // Encrypt + execute(Cipher.ENCRYPT_MODE, + inputText, + 0, + INPUT_LENGTH); + + // PBKDF2 required 16 byte padding + int padLength = NUM_PAD_BYTES + PBKDF2_ADD_PAD_BYTES; + + // Decrypt + // Note: inputText is implicitly padded by the above encrypt + // operation so decrypt operation can safely proceed + execute(Cipher.DECRYPT_MODE, + inputText, + 0, + INPUT_LENGTH + padLength); + + } catch (Exception ex) { + ex.printStackTrace(System.out); + result = false; + } + return result; + } + + private void execute(int edMode, byte[] inputText, int offset, int len) { + try { + // init Cipher + if (Cipher.ENCRYPT_MODE == edMode) { + ci.init(Cipher.ENCRYPT_MODE, this.key); + } else { + ci.init(Cipher.DECRYPT_MODE, this.key, ci.getParameters()); + } + + // First, generate the cipherText at an allocated buffer + byte[] outputText = ci.doFinal(inputText, offset, len); + + // Second, generate cipherText again at the same buffer of plainText + int myoff = offset / 2; + int off = ci.update(inputText, offset, len, inputText, myoff); + ci.doFinal(inputText, myoff + off); + + // Compare to see whether the two results are the same or not + boolean e = equalsBlock(inputText, myoff, outputText, 0, + outputText.length); + } catch (Exception ex) { + System.out.println("Got unexpected exception for " + algorithm); + ex.printStackTrace(System.out); + } + } + + private boolean equalsBlock(byte[] b1, int off1, + byte[] b2, int off2, int len) { + for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) { + if (b1[i] != b2[j]) { + return false; + } + } + return true; + } +} diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/runtime/ErrorHandling/VeryEarlyAssertTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/ErrorHandling/VeryEarlyAssertTest.java Mon Feb 04 15:00:29 2019 -0500 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8214975 + * @summary No hs-err file if fatal error is raised during dynamic initialization. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @requires (vm.debug == true) + * @requires os.family == "linux" + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.regex.Pattern; +import java.util.Map; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class VeryEarlyAssertTest { + + public static void main(String[] args) throws Exception { + + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xmx64M", + "-XX:-CreateCoredumpOnCrash", + "-version"); + Map env = pb.environment(); + env.put("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION", "1"); + + OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); + + // we should have crashed with an assert with a specific message: + output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*"); + output_detail.shouldMatch("#.*HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION.*"); + + // extract hs-err file + String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); + if (hs_err_file == null) { + throw new RuntimeException("Did not find hs-err file in output.\n"); + } + + // scan hs-err file: File should contain the same assertion message. Other than that, + // do not expect too much: file will be littered with secondary errors. The test + // should test that we get a hs-err file at all. + File f = new File(hs_err_file); + if (!f.exists()) { + throw new RuntimeException("hs-err file missing at " + + f.getAbsolutePath() + ".\n"); + } + + System.out.println("Found hs_err file. Scanning..."); + + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line = null; + + Pattern[] pattern = new Pattern[]{ + Pattern.compile(".*HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION.*") + }; + int currentPattern = 0; + + String lastLine = null; + while ((line = br.readLine()) != null) { + if (currentPattern < pattern.length) { + if (pattern[currentPattern].matcher(line).matches()) { + System.out.println("Found: " + line + "."); + currentPattern++; + } + } + lastLine = line; + } + br.close(); + + if (currentPattern < pattern.length) { + throw new RuntimeException("hs-err file incomplete (first missing pattern: " + currentPattern + ")"); + } + + if (!lastLine.equals("END.")) { + throw new RuntimeException("hs-err file incomplete (missing END marker.)"); + } else { + System.out.println("End marker found."); + } + + System.out.println("OK."); + + } + +} + + diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/runtime/logging/MonitorInflationTest.java --- a/test/hotspot/jtreg/runtime/logging/MonitorInflationTest.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/runtime/logging/MonitorInflationTest.java Mon Feb 04 15:00:29 2019 -0500 @@ -24,7 +24,7 @@ /* * @test * @bug 8133885 - * @summary monitorinflation=debug should have logging from each of the statements in the code + * @summary monitorinflation=trace should have logging from each of the statements in the code * @library /test/lib * @modules java.base/jdk.internal.misc * java.management @@ -50,7 +50,7 @@ } public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:monitorinflation=debug", + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:monitorinflation=trace", InnerClass.class.getName()); analyzeOutputOn(pb); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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.util.Map; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; /** * @test @@ -68,6 +69,8 @@ "longConstant markOopDesc::locked_value")); test.run(-1, cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbField.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; /** * @test @@ -63,6 +64,8 @@ "field nmethod _entry_bci int", "field Universe _collectedHeap CollectedHeap")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java Mon Feb 04 15:00:29 2019 -0500 @@ -27,6 +27,8 @@ import java.util.ArrayList; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; + /** * @test * @bug 8193124 @@ -91,6 +93,8 @@ test.run(theApp.getPid(), cmds, expStrMap, null); } + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java Mon Feb 04 15:00:29 2019 -0500 @@ -29,6 +29,7 @@ import jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Platform; import jdk.test.lib.Utils; +import jtreg.SkippedException; /** * @test @@ -82,6 +83,8 @@ "MaxJavaStackTraceDepth = 1024")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java Mon Feb 04 15:00:29 2019 -0500 @@ -57,13 +57,6 @@ String jstackOutput = test.run(theApp.getPid(), cmds, null, null); - if (jstackOutput == null) { - // Output could be null due to attach permission issues - // and if we are skipping this. - LingeredApp.stopApp(theApp); - throw new SkippedException("attach permission issues"); - } - Map tokensMap = new HashMap<>(); tokensMap.put("(a java.lang.Class for LingeredAppWithLock)", "instance of Oop for java/lang/Class"); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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 @@ // the 'jstack -v' command cmds = new ArrayList(); - // Output could be null if the test was skipped due to - // attach permission issues. - if (output == null) { - throw new SkippedException("attach permission issues"); - } String cmdStr = null; String[] parts = output.split("LingeredApp.main"); String[] tokens = parts[1].split(" "); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Utils; +import jtreg.SkippedException; /** * @test @@ -68,6 +69,8 @@ "ParselTongue")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java Mon Feb 04 15:00:29 2019 -0500 @@ -27,6 +27,7 @@ import jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Platform; +import jtreg.SkippedException; /** * @test @@ -64,6 +65,8 @@ "LingeredApp.main")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR (with -Xcomp=" + withXcomp + ") " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java Mon Feb 04 15:00:29 2019 -0500 @@ -33,6 +33,7 @@ import jdk.test.lib.JDKToolFinder; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.SA.SATestUtils; +import jtreg.SkippedException; /** @@ -177,22 +178,18 @@ List commands, Map> expectedStrMap, Map> unExpectedStrMap) - throws IOException, InterruptedException { + throws Exception { if (!Platform.shouldSAAttach()) { - if (Platform.isOSX()) { - if (!SATestUtils.canAddPrivileges()) { - // Skip the test if we don't have enough permissions to attach - // and cannot add privileges. - System.out.println("SA attach not expected to work - test skipped."); - return null; - } else { - needPrivileges = true; - } - } else { - System.out.println("SA attach not expected to work. Insufficient privileges."); - throw new Error("Cannot attach."); + if (Platform.isOSX() && SATestUtils.canAddPrivileges()) { + needPrivileges = true; } + else { + // Skip the test if we don't have enough permissions to attach + // and cannot add privileges. + throw new SkippedException( + "SA attach not expected to work. Insufficient privileges."); + } } attach(lingeredAppPid); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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,9 +75,6 @@ String longConstantOutput = test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap); - if (longConstantOutput == null) { - throw new SkippedException("attach permission issues"); - } checkForTruncation(longConstantOutput); } catch (SkippedException e) { throw e; diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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 jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Platform; +import jtreg.SkippedException; /** * @test @@ -57,6 +58,8 @@ "jimage", "zip", "verify")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; /** * @test @@ -68,6 +69,8 @@ unExpStrMap.put("printall", List.of( "cannot be cast to")); test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,11 +55,6 @@ String jstackOutput = test.run(theApp.getPid(), cmds, null, null); - if (jstackOutput == null) { - LingeredApp.stopApp(theApp); - throw new SkippedException("attach permission issues"); - } - String[] snippets = jstackOutput.split("LingeredApp.main"); String addressString = null; diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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 jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Platform; +import jtreg.SkippedException; /** * @test @@ -83,6 +84,8 @@ "bool JvmtiExport::_can_post_on_exceptions")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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 jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Platform; +import jtreg.SkippedException; /** * @test @@ -58,6 +59,8 @@ "Reference Handler", "Finalizer", "main")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,11 +70,6 @@ unExpStrMap.put("g1regiondetails", List.of("Unknown Region Type")); String regionDetailsOutput = test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap); - if (regionDetailsOutput == null) { - LingeredApp.stopApp(theApp); - throw new SkippedException("attach permission issues"); - } - // Test the output of 'scanoops' -- get the start and end addresses // from the StartsHumongous region. Ensure that it contains an // array of Strings. diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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,11 +58,6 @@ String universeOutput = test.run(theApp.getPid(), cmds, null, null); - if (universeOutput == null) { - LingeredApp.stopApp(theApp); - throw new SkippedException("attach permission issues"); - } - cmds = new ArrayList(); Map> expStrMap = new HashMap<>(); Map> unExpStrMap = new HashMap<>(); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.util.Map; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; /** * @test @@ -74,6 +75,8 @@ test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap); Files.delete(file); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; /** * @test @@ -76,14 +77,6 @@ expStrMap, unExpStrMap); - if (consolidatedOutput == null) { - // Output could be null due to attach permission issues. - System.out.println( - "Output is empty. Probably due to attach permission issues."); - LingeredApp.stopApp(theApp); - return; - } - // Test the thread command now. Obtain from the // output of the previous 'threads' command. The word before // the token 'Finalizer' should denote the thread id of the @@ -109,6 +102,8 @@ "Last_Java_SP")); cmds = List.of(cmd); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; /** * @test @@ -63,6 +64,8 @@ "type Universe null", "type ConstantPoolCache MetaspaceObj")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * 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 jdk.test.lib.apps.LingeredApp; import jdk.test.lib.Platform; +import jtreg.SkippedException; /** * @test @@ -63,6 +64,8 @@ "public static void main")); test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (SkippedException se) { + throw se; } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java --- a/test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ /* * @test * + * @bug 8217432 * @summary converted from VM Testbase metaspace/shrink_grow/ShrinkGrowTest. * * @requires vm.opt.final.ClassUnloading diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java Mon Feb 04 15:00:29 2019 -0500 @@ -397,7 +397,7 @@ // TODO: exclude GC time, compilation time (optionally) from measurements print("Comparing invocation time orders"); - verifyTimeOrder(results[REFLECTION_CALL], results[INVOKE_EXACT]); + verifyTimeOrder(results[INDY], results[REFLECTION_CALL]); verifyTimeOrder(results[INVOKE_EXACT], results[DIRECT_CALL]); verifyTimeOrder(results[INVOKE], results[DIRECT_CALL]); verifyTimeOrder(results[INVOKE_EXACT], results[INDY]); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/ProblemList-Xcomp.txt --- a/test/jdk/ProblemList-Xcomp.txt Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/ProblemList-Xcomp.txt Mon Feb 04 15:00:29 2019 -0500 @@ -29,3 +29,4 @@ java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all java/util/concurrent/CountDownLatch/Basic.java 8195057 generic-all +java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java 8216317 solaris-all diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/ProblemList-graal.txt --- a/test/jdk/ProblemList-graal.txt Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/ProblemList-graal.txt Mon Feb 04 15:00:29 2019 -0500 @@ -69,6 +69,29 @@ java/lang/Runtime/exec/LotsOfOutput.java 8196611 generic-all java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java 8196611 generic-all +# tests require pop_frame and force_early_return capabilities +com/sun/jdi/RedefineTTYLineNumber.java 8195635 generic-all +com/sun/jdi/RedefineG.java 8195635 generic-all +com/sun/jdi/RedefineCrossStart.java 8195635 generic-all +com/sun/jdi/PopSynchronousTest.java 8195635 generic-all +com/sun/jdi/RedefineTTYLineNumber.java 8195635 generic-all +com/sun/jdi/RedefineG.java 8195635 generic-all +com/sun/jdi/RedefineCrossStart.java 8195635 generic-all +com/sun/jdi/PopSynchronousTest.java 8195635 generic-all +com/sun/jdi/PopAsynchronousTest.java 8195635 generic-all +com/sun/jdi/PopAndStepTest.java 8195635 generic-all +com/sun/jdi/PopAsynchronousTest.java 8195635 generic-all +com/sun/jdi/PopAndStepTest.java 8195635 generic-all +com/sun/jdi/EarlyReturnTest.java 8195635 generic-all +com/sun/jdi/RedefineTTYLineNumber.java 8195635 generic-all +com/sun/jdi/RedefineG.java 8195635 generic-all +com/sun/jdi/RedefineCrossStart.java 8195635 generic-all +com/sun/jdi/PopSynchronousTest.java 8195635 generic-all +com/sun/jdi/PopAsynchronousTest.java 8195635 generic-all +com/sun/jdi/PopAndStepTest.java 8195635 generic-all +com/sun/jdi/EarlyReturnTest.java 8195635 generic-all +com/sun/jdi/EarlyReturnTest.java 8195635 generic-all + # Next JFR tests fail with Graal. Assuming 8193210. jdk/jfr/event/compiler/TestCodeSweeper.java 8193210 generic-all jdk/jfr/event/compiler/TestCompilerInlining.java 8193210 generic-all diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/java/beans/PropertyEditor/Test6397609.java --- a/test/jdk/java/beans/PropertyEditor/Test6397609.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/java/beans/PropertyEditor/Test6397609.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * 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,31 +32,38 @@ */ import java.beans.PropertyEditorManager; +import java.lang.ref.WeakReference; public class Test6397609 { public static void main(String[] args) throws Exception { - MemoryClassLoader loader = new MemoryClassLoader(); - PropertyEditorManager.registerEditor( - Object.class, - loader.compile("Editor", - "public class Editor extends java.beans.PropertyEditorSupport {}")); + Class targetClass = Object.class; + Class editorClass = new MemoryClassLoader().compile("Editor", + "public class Editor extends java.beans.PropertyEditorSupport {}"); + PropertyEditorManager.registerEditor(targetClass, editorClass); - if (!isEditorExist(Object.class)) { + // trigger a gc + Object object = new Object(); + var r = new WeakReference(object); + object = null; + while (r.get() != null) { + System.gc(); + Thread.sleep(100); + } + + if (PropertyEditorManager.findEditor(targetClass) == null) { throw new Error("the editor is lost"); } - loader = null; // clean the reference - if (isEditorExist(Object.class)) { + + // allow, and wait for, Editor class to be unloaded + var ref = new WeakReference>(editorClass); + editorClass = null; + while (ref.get() != null) { + System.gc(); + Thread.sleep(100); + } + + if (PropertyEditorManager.findEditor(targetClass) != null) { throw new Error("unexpected editor is found"); } } - - private static boolean isEditorExist(Class type) { - for (int i = 0; i < 10; i++) { - System.gc(); // clean all weak references - if (null == PropertyEditorManager.findEditor(type)) { - return false; - } - } - return true; - } } diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java --- a/test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ import java.io.PrintStream; +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.lang.reflect.Array; @@ -37,6 +38,7 @@ import java.security.Policy; import java.security.ProtectionDomain; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -156,7 +158,7 @@ .collect(Collectors.toSet()); set.stream().forEach(t -> LogStream.err.println("Found: " + t)); if (set.size() > 1) { - throw new RuntimeException("Too many bootsrap threads found"); + throw new RuntimeException("Too many bootstrap threads found"); } Optional t = set.stream().findFirst(); if (t.isPresent()) { @@ -292,46 +294,73 @@ // of the executor. SimplePolicy.allowAll.set(Boolean.TRUE); try { - Stream stream = Thread.getAllStackTraces().keySet().stream(); - stream.filter((t) -> t.getName().startsWith("BootstrapMessageLoggerTask-")) - .forEach(t -> LogStream.err.println(t)); + // Though unlikely, it is not impossible that the bootstrap logger + // executor may have released its first thread and spawned a new one. + // If that happened then the executor itself might have been GC'ed + // as well and a new one might have been created. + // The code below will lookup the executor threads again and + // join them. + // Only one may be active at a given time, but that might not + // be the one referenced by threadRef. + // We're just making sure all of them have stopped running + // before verifying that the executor is eventually GC'ed. + final WeakReference previous = threadRef; + Stream> stream = Thread.getAllStackTraces().keySet().stream() + .filter((t) -> t.getName().startsWith("BootstrapMessageLoggerTask-")) + .filter((t) -> previous == null ? true : t != previous.get()) + .map((t) -> new WeakReference<>(t, queue)); + List> threads = stream.collect(Collectors.toList()); + if (previous != null) threads.add(previous); + threads.forEach(t -> LogStream.err.println(t.get())); stream = null; - if (threadRef != null && test == TestCase.SECURE_AND_WAIT) { - Thread t = threadRef.get(); - if (t != null) { - if (!(Boolean)isAlive.invoke(null)) { - throw new RuntimeException("Executor already terminated"); + + if (test == TestCase.SECURE_AND_WAIT) { + // First wait for all executor threads to terminate + for (var ref : threads) { + Thread t = ref.get(); + if (t != null) { + if (!(Boolean)isAlive.invoke(null) && t.isAlive()) { + throw new RuntimeException("Executor already terminated"); + } else { + LogStream.err.println("Executor still alive as expected: " + t.getName()); + } + LogStream.err.println("Waiting for " + t.getName() + " to terminate (join)"); + t.join(60_000); + t = null; } else { - LogStream.err.println("Executor still alive as expected."); + LogStream.err.println("WeakReference is already cleared."); + long count = Thread.getAllStackTraces().keySet().stream() + .filter((tr) -> tr.getName().startsWith("BootstrapMessageLoggerTask-")) + .count(); + if (count != 0) { + LogStream.err.println("There are " + count + " threads still lingering."); + } } - LogStream.err.println("Waiting for " + t.getName() + " to terminate (join)"); - t.join(60_000); - t = null; } - LogStream.err.println("Calling System.gc()"); - System.gc(); - LogStream.err.println("Waiting for BootstrapMessageLoggerTask to be gc'ed"); - while (queue.remove(1000) == null) { + // Then wait until all the executor threads are GC'ed + while (!threads.isEmpty()) { LogStream.err.println("Calling System.gc()"); System.gc(); - } + LogStream.err.println("Waiting for BootstrapMessageLoggerTask to be gc'ed"); + Reference tref; + while ((tref = queue.remove(1000)) == null) { + LogStream.err.println("Calling System.gc()"); + System.gc(); + } - // Call the reference here to make sure threadRef will not be - // eagerly garbage collected before the thread it references. - // otherwise, it might not be enqueued, resulting in the - // queue.remove() call above to always return null.... - if (threadRef.get() != null) { - throw new RuntimeException("Reference should have been cleared"); + threads.remove(tref); + LogStream.err.println("BootstrapMessageLoggerTask has been gc'ed: " + + threads.size() + " remaining..."); } - - LogStream.err.println("BootstrapMessageLoggerTask has been gc'ed"); - // Wait for the executor to be gc'ed... + // Then wait for the executor to be gc'ed... + LogStream.err.println("Waiting for the executor to be gc'ed: Calling System.gc()"); + System.gc(); for (int i=0; i<10; i++) { - LogStream.err.println("Calling System.gc()"); - System.gc(); if (!(Boolean)isAlive.invoke(null)) break; // It would be unexpected that we reach here... Thread.sleep(1000); + LogStream.err.println("Calling System.gc()"); + System.gc(); } if ((Boolean)isAlive.invoke(null)) { diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java --- a/test/jdk/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java Mon Feb 04 15:00:29 2019 -0500 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4404702 + * @bug 4404702 8216528 * @summary When the RMI runtime (lazily) spawns system threads that could * outlive the application context in which they were (happened to be) * created, such threads should not inherit (thread local) data specific to @@ -106,7 +106,10 @@ * context class loader-- by giving it a chance to pass away. */ Thread.sleep(2000); - System.gc(); + while (loaderRef.get() != null) { + System.gc(); + Thread.sleep(100); + } System.err.println( "waiting to be notified of loader being weakly reachable..."); diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java --- a/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java Mon Feb 04 15:00:29 2019 -0500 @@ -117,7 +117,7 @@ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }; - // List of enabled cipher suites when the "crypto.policy" security + // List of supported cipher suites when the "crypto.policy" security // property is set to "unlimited" (the default value). private final static String[] SUPPORTED_DEFAULT = { "TLS_AES_128_GCM_SHA256", diff -r 3dcb33ce7ced -r e7ba8c89abe7 test/jdk/sun/net/www/protocol/http/ProtocolRedirect.java --- a/test/jdk/sun/net/www/protocol/http/ProtocolRedirect.java Sun Feb 03 08:16:08 2019 -0500 +++ b/test/jdk/sun/net/www/protocol/http/ProtocolRedirect.java Mon Feb 04 15:00:29 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * 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,24 +31,30 @@ public class ProtocolRedirect { public static void main(String [] args) throws Exception { - int localPort; - new Thread(new Redirect()).start(); - while ((localPort = Redirect.listenPort) == -1) { - Thread.sleep(1000); - } + try (Redirect server = new Redirect(new ServerSocket())) { + ServerSocket ss = server.ssock; + ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(server).start(); - String page = "http://localhost:"+localPort+"/"; - URL url = new URL(page); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - conn.connect(); - if (conn.getResponseCode() != 302) { - throw new RuntimeException("Test failed. Should get RespCode: 302. Got:"+conn.getResponseCode()); + URL url = new URL("http", ss.getInetAddress().getHostAddress(), ss.getLocalPort(), "/"); + String page = url.toString(); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.connect(); + if (conn.getResponseCode() != 302) { + System.err.println("Bad response code received from: " + page); + throw new RuntimeException("Test failed. Should get RespCode: 302. Got:" + conn.getResponseCode()); + } + System.out.println("Received expected response code from: " + page); } } } -class Redirect implements Runnable { - public static int listenPort = -1; // port to listen for connections on +class Redirect implements Runnable, Closeable { + final ServerSocket ssock; + volatile boolean stopped; + Redirect(ServerSocket ss) { + ssock = ss; + } // Send a header redirect to the peer telling it to go to the // https server on the host it sent the connection request to. @@ -61,18 +67,31 @@ out.write(reply.toString().getBytes()); } - Socket sock; + volatile Socket sock; public void run() { try { - ServerSocket ssock = new ServerSocket(); - ssock.bind(null); - listenPort = ssock.getLocalPort(); - sock = ssock.accept(); - sock.setTcpNoDelay(true); + Socket s = sock = ssock.accept(); + s.setTcpNoDelay(true); sendReply(); - sock.shutdownOutput(); - } catch(IOException io) { - throw new RuntimeException(io.getCause()); + s.shutdownOutput(); + } catch(Throwable t) { + if (!stopped) { + t.printStackTrace(); + throw new RuntimeException(String.valueOf(t), t); + } + } + } + + public void close() { + Socket s = sock; + boolean done = stopped; + if (done) return; + stopped = true; + try { + if (s != null) s.close(); + } catch (Throwable x) { + } finally { + try { ssock.close(); } catch (Throwable x) {} } }