# HG changeset patch # User alanb # Date 1550406071 0 # Node ID de9dd71ef18ca42e04a794c36c3f189bf143e2d9 # Parent 4964feb6d75d2d30503e8e56d2d97c76bd555883# Parent d230a040662314f69fe50620a68fae6634550b49 Merge diff -r 4964feb6d75d -r de9dd71ef18c .hgtags --- a/.hgtags Sun Feb 17 12:20:37 2019 +0000 +++ b/.hgtags Sun Feb 17 12:21:11 2019 +0000 @@ -542,3 +542,4 @@ 6c377af36a5c4203f16aed8a5e4c2ecc08fcd8bd jdk-12+30 021917019cda1c0c5853255322274f37693a2431 jdk-13+7 b5f7bb57de2f797be34f6c75d45c3245ad37ab97 jdk-12+31 +a535ba736cabc6886acdff36de3a096c46e5ddc5 jdk-13+8 diff -r 4964feb6d75d -r de9dd71ef18c make/Init.gmk --- a/make/Init.gmk Sun Feb 17 12:20:37 2019 +0000 +++ b/make/Init.gmk Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -277,7 +277,7 @@ else $(ECHO) "Re-running configure using default settings" endif - ( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \ + ( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" AUTOCONF="$(AUTOCONF)" \ CUSTOM_ROOT="$(CUSTOM_ROOT)" \ CUSTOM_CONFIG_DIR="$(CUSTOM_CONFIG_DIR)" \ $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) ) diff -r 4964feb6d75d -r de9dd71ef18c make/Main.gmk --- a/make/Main.gmk Sun Feb 17 12:20:37 2019 +0000 +++ b/make/Main.gmk Sun Feb 17 12:21:11 2019 +0000 @@ -766,6 +766,8 @@ $(foreach m, $(GENSRC_MODULES), $(eval $m-libs-compile-commands: $m-gensrc)) $(foreach m, $(filter $(JAVA_MODULES), $(LIBS_MODULES)), $(eval $m-libs-compile-commands: $m-java)) + $(COMPILE_COMMANDS_TARGETS_HOTSPOT): clean-compile-commands + $(COMPILE_COMMANDS_TARGETS_JDK): clean-compile-commands compile-commands-hotspot: $(COMPILE_COMMANDS_TARGETS_HOTSPOT) compile-commands: $(COMPILE_COMMANDS_TARGETS_HOTSPOT) $(COMPILE_COMMANDS_TARGETS_JDK) @@ -1139,6 +1141,9 @@ clean-docs: $(call CleanDocs) +clean-compile-commands: + $(call CleanMakeSupportDir,compile-commands) + $(CLEAN_DIR_TARGETS): $(call CleanDir,$(patsubst clean-%, %, $@)) @@ -1181,9 +1186,9 @@ ) $(ECHO) Cleaned everything, you will have to re-run configure. -ALL_TARGETS += clean clean-docs dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_SUPPORT_DIR_TARGETS) \ - $(CLEAN_TEST_TARGETS) $(CLEAN_PHASE_TARGETS) $(CLEAN_MODULE_TARGETS) \ - $(CLEAN_MODULE_PHASE_TARGETS) +ALL_TARGETS += clean clean-docs clean-compile-commands dist-clean $(CLEAN_DIR_TARGETS) \ + $(CLEAN_SUPPORT_DIR_TARGETS) $(CLEAN_TEST_TARGETS) $(CLEAN_PHASE_TARGETS) \ + $(CLEAN_MODULE_TARGETS) $(CLEAN_MODULE_PHASE_TARGETS) ################################################################################ # Declare *-only targets for each normal target diff -r 4964feb6d75d -r de9dd71ef18c make/MainSupport.gmk --- a/make/MainSupport.gmk Sun Feb 17 12:20:37 2019 +0000 +++ b/make/MainSupport.gmk Sun Feb 17 12:21:11 2019 +0000 @@ -54,6 +54,13 @@ @$(PRINTF) " done\n" endef +define CleanMakeSupportDir + @$(PRINTF) "Cleaning $(strip $1) make support artifacts ..." + @$(PRINTF) "\n" $(LOG_DEBUG) + $(RM) -r $(MAKESUPPORT_OUTPUTDIR)/$(strip $1) + @$(PRINTF) " done\n" +endef + define CleanTest @$(PRINTF) "Cleaning test $(strip $1) ..." @$(PRINTF) "\n" $(LOG_DEBUG) diff -r 4964feb6d75d -r de9dd71ef18c make/autoconf/basics.m4 --- a/make/autoconf/basics.m4 Sun Feb 17 12:20:37 2019 +0000 +++ b/make/autoconf/basics.m4 Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -406,6 +406,8 @@ [ # Save the original command line. This is passed to us by the wrapper configure script. AC_SUBST(CONFIGURE_COMMAND_LINE) + # AUTOCONF might be set in the environment by the user. Preserve for "make reconfigure". + AC_SUBST(AUTOCONF) # Save the path variable before it gets changed ORIGINAL_PATH="$PATH" AC_SUBST(ORIGINAL_PATH) diff -r 4964feb6d75d -r de9dd71ef18c make/autoconf/spec.gmk.in --- a/make/autoconf/spec.gmk.in Sun Feb 17 12:20:37 2019 +0000 +++ b/make/autoconf/spec.gmk.in Sun Feb 17 12:21:11 2019 +0000 @@ -36,6 +36,9 @@ # A self-referential reference to this file. SPEC:=@SPEC@ +# Path to autoconf if overriden by the user, to be used by "make reconfigure" +AUTOCONF := @AUTOCONF@ + # SPACE and COMMA are defined in MakeBase.gmk, but they are also used in # some definitions here, and are needed if MakeBase.gmk is not included before # this file. diff -r 4964feb6d75d -r de9dd71ef18c make/conf/jib-profiles.js --- a/make/conf/jib-profiles.js Sun Feb 17 12:20:37 2019 +0000 +++ b/make/conf/jib-profiles.js Sun Feb 17 12:21:11 2019 +0000 @@ -944,11 +944,17 @@ }, jcov: { - server: "jpg", - product: "jcov", - version: "3.0", - build_number: "b07", - file: "bundles/jcov-3_0.zip", + // Until an official build of JCov is available, use custom + // build to support classfile version 57. + // See CODETOOLS-7902358 for more info. + // server: "jpg", + // product: "jcov", + // version: "3.0", + // build_number: "b07", + // file: "bundles/jcov-3_0.zip", + organization: common.organization, + revision: "3.0-57-support+1.0", + ext: "zip", environment_name: "JCOV_HOME", }, diff -r 4964feb6d75d -r de9dd71ef18c make/hotspot/lib/JvmFlags.gmk --- a/make/hotspot/lib/JvmFlags.gmk Sun Feb 17 12:20:37 2019 +0000 +++ b/make/hotspot/lib/JvmFlags.gmk Sun Feb 17 12:21:11 2019 +0000 @@ -74,7 +74,7 @@ endif else ifeq ($(DEBUG_LEVEL), fastdebug) JVM_CFLAGS_DEBUGLEVEL := -DASSERT - ifeq ($call isTargetOs, windows aix), false) + ifeq ($(call isTargetOs, windows aix), false) # NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX. JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS endif diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -425,54 +425,56 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, bool acquire, bool release, bool weak, bool is_cae, Register result) { - - Register tmp = rscratch2; + Register tmp1 = rscratch1; + Register tmp2 = rscratch2; bool is_narrow = UseCompressedOops; Assembler::operand_size size = is_narrow ? Assembler::word : Assembler::xword; - assert_different_registers(addr, expected, new_val, result, tmp); + assert_different_registers(addr, expected, new_val, tmp1, tmp2); Label retry, done, fail; // CAS, using LL/SC pair. __ bind(retry); - __ load_exclusive(result, addr, size, acquire); + __ load_exclusive(tmp1, addr, size, acquire); if (is_narrow) { - __ cmpw(result, expected); + __ cmpw(tmp1, expected); } else { - __ cmp(result, expected); + __ cmp(tmp1, expected); } __ br(Assembler::NE, fail); - __ store_exclusive(tmp, new_val, addr, size, release); + __ store_exclusive(tmp2, new_val, addr, size, release); if (weak) { - __ cmpw(tmp, 0u); // If the store fails, return NE to our caller + __ cmpw(tmp2, 0u); // If the store fails, return NE to our caller } else { - __ cbnzw(tmp, retry); + __ cbnzw(tmp2, retry); } __ b(done); __ bind(fail); - // Check if rb(expected)==rb(result) + // Check if rb(expected)==rb(tmp1) // Shuffle registers so that we have memory value ready for next expected. - __ mov(tmp, expected); - __ mov(expected, result); + __ mov(tmp2, expected); + __ mov(expected, tmp1); if (is_narrow) { - __ decode_heap_oop(result, result); - __ decode_heap_oop(tmp, tmp); + __ decode_heap_oop(tmp1, tmp1); + __ decode_heap_oop(tmp2, tmp2); } - read_barrier_impl(masm, result); - read_barrier_impl(masm, tmp); - __ cmp(result, tmp); + read_barrier_impl(masm, tmp1); + read_barrier_impl(masm, tmp2); + __ cmp(tmp1, tmp2); // Retry with expected now being the value we just loaded from addr. __ br(Assembler::EQ, retry); if (is_cae && is_narrow) { // For cmp-and-exchange and narrow oops, we need to restore // the compressed old-value. We moved it to 'expected' a few lines up. - __ mov(result, expected); + __ mov(tmp1, expected); } __ bind(done); - if (!is_cae) { + if (is_cae) { + __ mov(result, tmp1); + } else { __ cset(result, Assembler::EQ); } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -2167,6 +2167,14 @@ hlt(0); } +void MacroAssembler::warn(const char* msg) { + pusha(); + mov(c_rarg0, (address)msg); + mov(lr, CAST_FROM_FN_PTR(address, warning)); + blrt(lr, 1, 0, MacroAssembler::ret_type_void); + popa(); +} + void MacroAssembler::unimplemented(const char* what) { const char* buf = NULL; { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1687,7 +1687,7 @@ // Helper for generating a dynamic type check. - // Smashes rscratch1. + // Smashes rscratch1, rscratch2. void generate_type_check(Register sub_klass, Register super_check_offset, Register super_klass, @@ -1979,6 +1979,10 @@ const Register dst_pos = c_rarg3; // destination position const Register length = c_rarg4; + + // Registers used as temps + const Register dst_klass = c_rarg5; + __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); @@ -2184,8 +2188,7 @@ arraycopy_range_checks(src, src_pos, dst, dst_pos, scratch_length, r18, L_failed); - const Register rscratch2_dst_klass = rscratch2; - __ load_klass(rscratch2_dst_klass, dst); // reload + __ load_klass(dst_klass, dst); // reload // Marshal the base address arguments now, freeing registers. __ lea(from, Address(src, src_pos, Address::lsl(LogBytesPerHeapOop))); @@ -2195,24 +2198,25 @@ __ movw(count, length); // length (reloaded) Register sco_temp = c_rarg3; // this register is free now assert_different_registers(from, to, count, sco_temp, - rscratch2_dst_klass, scratch_src_klass); + dst_klass, scratch_src_klass); // assert_clean_int(count, sco_temp); // Generate the type check. const int sco_offset = in_bytes(Klass::super_check_offset_offset()); - __ ldrw(sco_temp, Address(rscratch2_dst_klass, sco_offset)); - // assert_clean_int(sco_temp, r18); - generate_type_check(scratch_src_klass, sco_temp, rscratch2_dst_klass, L_plain_copy); + __ ldrw(sco_temp, Address(dst_klass, sco_offset)); + + // Smashes rscratch1, rscratch2 + generate_type_check(scratch_src_klass, sco_temp, dst_klass, L_plain_copy); // Fetch destination element klass from the ObjArrayKlass header. int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); - __ ldr(rscratch2_dst_klass, Address(rscratch2_dst_klass, ek_offset)); - __ ldrw(sco_temp, Address(rscratch2_dst_klass, sco_offset)); + __ ldr(dst_klass, Address(dst_klass, ek_offset)); + __ ldrw(sco_temp, Address(dst_klass, sco_offset)); // the checkcast_copy loop needs two extra arguments: assert(c_rarg3 == sco_temp, "#3 already in place"); // Set up arguments for checkcast_copy_entry. - __ mov(c_rarg4, rscratch2_dst_klass); // dst.klass.element_klass + __ mov(c_rarg4, dst_klass); // dst.klass.element_klass __ b(RuntimeAddress(checkcast_copy_entry)); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/aarch64/templateTable_aarch64.cpp --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -3230,7 +3230,6 @@ // since the parameter_size includes it. __ push(r19); __ mov(r19, index); - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); __ load_resolved_reference_at_index(index, r19); __ pop(r19); __ push(index); // push appendix (MethodType, CallSite, etc.) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/arm/templateTable_arm.cpp --- a/src/hotspot/cpu/arm/templateTable_arm.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/arm/templateTable_arm.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, 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 @@ -3645,7 +3645,6 @@ Label L_no_push; __ tbz(flags, ConstantPoolCacheEntry::has_appendix_shift, L_no_push); __ mov(temp, index); - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); __ load_resolved_reference_at_index(index, temp); __ verify_oop(index); __ push_ptr(index); // push appendix (MethodType, CallSite, etc.) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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. * Copyright (c) 2018, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,6 +29,7 @@ #include "gc/g1/g1BarrierSetAssembler.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" #include "gc/g1/g1CardTable.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/heapRegion.hpp" @@ -512,7 +513,7 @@ __ bind(restart); - // Get the index into the update buffer. DirtyCardQueue::_index is + // Get the index into the update buffer. G1DirtyCardQueue::_index is // a size_t so ld_ptr is appropriate here. __ ld(tmp2, dirty_card_q_index_byte_offset, R16_thread); @@ -539,7 +540,7 @@ __ mflr(R0); __ std(R0, _abi(lr), R1_SP); __ push_frame_reg_args(nbytes_save, R0); // dummy frame for C call - __ call_VM_leaf(CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread), R16_thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1DirtyCardQueueSet::handle_zero_index_for_thread), R16_thread); __ pop_frame(); __ ld(R0, _abi(lr), R1_SP); __ mtlr(R0); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,6 +30,7 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BarrierSetAssembler.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/heapRegion.hpp" @@ -587,7 +588,7 @@ __ bind(restart); - // Get the index into the update buffer. DirtyCardQueue::_index is + // Get the index into the update buffer. G1DirtyCardQueue::_index is // a size_t so z_ltg is appropriate here. __ z_ltg(idx, Address(Z_thread, dirty_card_q_index_byte_offset)); @@ -607,7 +608,7 @@ __ bind(refill); save_volatile_registers(sasm); __ z_lgr(idx, addr_card); // Save addr_card, tmp3 must be non-volatile. - __ call_VM_leaf(CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread), + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1DirtyCardQueueSet::handle_zero_index_for_thread), Z_thread); __ z_lgr(addr_card, idx); restore_volatile_registers(sasm); // Restore addr_card. diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp --- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -28,6 +28,7 @@ #include "gc/g1/g1BarrierSetAssembler.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" #include "gc/g1/g1CardTable.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/heapRegion.hpp" @@ -315,7 +316,7 @@ int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()); __ bind(restart); - // Load the index into the update buffer. DirtyCardQueue::_index is + // Load the index into the update buffer. G1DirtyCardQueue::_index is // a size_t so ld_ptr is appropriate here. __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); @@ -333,7 +334,7 @@ __ bind(refill); address handle_zero = CAST_FROM_FN_PTR(address, - &DirtyCardQueueSet::handle_zero_index_for_thread); + &G1DirtyCardQueueSet::handle_zero_index_for_thread); // This should be rare enough that we can afford to save all the // scratch registers that the calling context might be using. __ mov(G1_scratch, L3); @@ -673,7 +674,7 @@ __ bind(restart); - // Get the index into the update buffer. DirtyCardQueue::_index is + // Get the index into the update buffer. G1DirtyCardQueue::_index is // a size_t so ld_ptr is appropriate here. __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); @@ -694,7 +695,7 @@ __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, - DirtyCardQueueSet::handle_zero_index_for_thread), + G1DirtyCardQueueSet::handle_zero_index_for_thread), G2_thread); __ restore_live_registers(true); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/sparc/templateTable_sparc.cpp --- a/src/hotspot/cpu/sparc/templateTable_sparc.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/sparc/templateTable_sparc.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -2992,7 +2992,6 @@ // Push the appendix as a trailing parameter. // This must be done before we get the receiver, // since the parameter_size includes it. - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); __ load_resolved_reference_at_index(temp, index, /*tmp*/recv); __ verify_oop(temp); __ push_ptr(temp); // push appendix (MethodType, CallSite, etc.) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/cpu/x86/templateTable_x86.cpp --- a/src/hotspot/cpu/x86/templateTable_x86.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -3643,7 +3643,6 @@ // since the parameter_size includes it. __ push(rbx); __ mov(rbx, index); - assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); __ load_resolved_reference_at_index(index, rbx); __ pop(rbx); __ push(index); // push appendix (MethodType, CallSite, etc.) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/os/aix/porting_aix.cpp --- a/src/hotspot/os/aix/porting_aix.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/os/aix/porting_aix.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,15 @@ #include "utilities/align.hpp" #include "utilities/debug.hpp" +// distinguish old xlc and xlclang++, where +// is suggested but not found in GA release (might come with a fix) +#if defined(__clang__) +#define DISABLE_DEMANGLE +// #include +#else #include +#endif + #include #include #include @@ -237,6 +245,7 @@ p_name[i] = '\0'; // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h). +#ifndef DISABLE_DEMANGLE if (demangle) { char* rest; Name* const name = Demangle(p_name, rest); @@ -249,6 +258,7 @@ delete name; } } +#endif } else { strncpy(p_name, "", namelen-1); p_name[namelen-1] = '\0'; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/os_cpu/aix_ppc/prefetch_aix_ppc.inline.hpp --- a/src/hotspot/os_cpu/aix_ppc/prefetch_aix_ppc.inline.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/os_cpu/aix_ppc/prefetch_aix_ppc.inline.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -43,7 +43,7 @@ } inline void Prefetch::write(void *loc, intx interval) { -#if !defined(USE_XLC_PREFETCH_WRITE_BUILTIN) +#if !defined(USE_XLC_BUILTINS) __asm__ __volatile__ ( " dcbtst 0, %0 \n" : diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/c1/c1_Decorators.hpp --- a/src/hotspot/share/c1/c1_Decorators.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/c1/c1_Decorators.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -34,5 +34,7 @@ // Use the C1_MASK_BOOLEAN decorator for boolean accesses where the value // needs to be masked. const DecoratorSet C1_MASK_BOOLEAN = DECORATOR_LAST << 2; +// Use the C1_UNSAFE_ACCESS decorator to mark unsafe accesses. +const DecoratorSet C1_UNSAFE_ACCESS = DECORATOR_LAST << 3; #endif // SHARE_C1_C1_DECORATORS_HPP diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/c1/c1_LIRGenerator.cpp --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -2161,7 +2161,7 @@ off.load_item(); src.load_item(); - DecoratorSet decorators = IN_HEAP; + DecoratorSet decorators = IN_HEAP | C1_UNSAFE_ACCESS; if (x->is_volatile()) { decorators |= MO_SEQ_CST; @@ -2195,7 +2195,7 @@ set_no_result(x); - DecoratorSet decorators = IN_HEAP; + DecoratorSet decorators = IN_HEAP | C1_UNSAFE_ACCESS; if (type == T_ARRAY || type == T_OBJECT) { decorators |= ON_UNKNOWN_OOP_REF; } @@ -2211,7 +2211,7 @@ LIRItem off(x->offset(), this); LIRItem value(x->value(), this); - DecoratorSet decorators = IN_HEAP | MO_SEQ_CST; + DecoratorSet decorators = IN_HEAP | C1_UNSAFE_ACCESS | MO_SEQ_CST; if (type == T_ARRAY || type == T_OBJECT) { decorators |= ON_UNKNOWN_OOP_REF; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/ci/ciInstanceKlass.cpp --- a/src/hotspot/share/ci/ciInstanceKlass.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/ci/ciInstanceKlass.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -669,11 +669,21 @@ _out->print_cr(INT64_FORMAT, *(int64_t*)&d); break; } - case T_ARRAY: { + case T_ARRAY: // fall-through + case T_OBJECT: { oop value = mirror->obj_field_acquire(fd->offset()); if (value == NULL) { _out->print_cr("null"); - } else { + } else if (value->is_instance()) { + assert(fd->field_type() == T_OBJECT, ""); + if (value->is_a(SystemDictionary::String_klass())) { + const char* ascii_value = java_lang_String::as_quoted_ascii(value); + _out->print("\"%s\"", (ascii_value != NULL) ? ascii_value : ""); + } else { + const char* klass_name = value->klass()->name()->as_quoted_ascii(); + _out->print_cr("%s", klass_name); + } + } else if (value->is_array()) { typeArrayOop ta = (typeArrayOop)value; _out->print("%d", ta->length()); if (value->is_objArray()) { @@ -682,21 +692,6 @@ _out->print(" %s", klass_name); } _out->cr(); - } - break; - } - case T_OBJECT: { - oop value = mirror->obj_field_acquire(fd->offset()); - if (value == NULL) { - _out->print_cr("null"); - } else if (value->is_instance()) { - if (value->is_a(SystemDictionary::String_klass())) { - const char* ascii_value = java_lang_String::as_quoted_ascii(value); - _out->print("\"%s\"", (ascii_value != NULL) ? ascii_value : ""); - } else { - const char* klass_name = value->klass()->name()->as_quoted_ascii(); - _out->print_cr("%s", klass_name); - } } else { ShouldNotReachHere(); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/ci/ciStreams.cpp --- a/src/hotspot/share/ci/ciStreams.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/ci/ciStreams.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -334,15 +334,91 @@ ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); will_link = m->is_loaded(); - // Use the MethodType stored in the CP cache to create a signature + // Use the signature stored in the CP cache to create a signature // with correct types (in respect to class loaders). - if (has_method_type()) { - ciSymbol* sig_sym = env->get_symbol(cpool->symbol_at(get_method_signature_index(cpool))); - ciKlass* pool_holder = env->get_klass(cpool->pool_holder()); - ciMethodType* method_type = get_method_type(); - ciSignature* declared_signature = new (env->arena()) ciSignature(pool_holder, sig_sym, method_type); - (*declared_signature_result) = declared_signature; + // + // In classic Java (before Java 7) there is never the slightest + // difference between the signature at the call site and that of the + // method. Such a difference would have been a type error in the + // JVM. + // + // Now there are a few circumstances where the signature of a call + // site (which controls the outgoing stacked arguments) can differ + // from the signature of the method (which controls the receipt of + // those arguments at the method entry point). + // + // A. The signatures can differ if the callee is a static method and + // the caller thinks it is calling a non-static method (VH.get). + // This requires the method signature to have an explicit leading + // argument for the implicit 'this', not present at the call site. + // + // B. The call site can have less specific parameter types than the + // method, allowing loosely-typed code to handle strongly-typed + // methods. This happens with linkToStatic and related linker + // commands. Obviously the loosely-typed code has to ensure that + // the strongly typed method's invariants are respected, and this is + // done by issuing dynamic casts. + // + // C. The call site can have more specific parameter types than the + // method, allowing loosely-typed methods to handle strongly-typed + // requests. + // + // D. There are corresponding effects with return values, such as + // boolean method returning an int to an int-receiving call site, + // even though the method thought it returned just a boolean. + // + // E. The calling sequence at a particular call site may add an + // "appendix" argument not mentioned in the call site signature. It + // is expected by the method signature, though, and this adds to the + // method's arity, even after 'this' parameter effects (A) are + // discounted. Appendixes are used by invokehandle and + // invokedynamic instructions. + // + // F. A linker method (linkToStatic, etc.) can also take an extra + // argument, a MemberName which routes the call to a concrete + // strongly-typed method. In this case the linker method may also + // differ in any of the ways A-D. The eventual method will ignore + // the presence of the extra argument. + // + // None of these changes to calling sequences requires an argument + // to be moved or reformatted in any way. This works because all + // references look alike to the JVM, as do all primitives (except + // float/long/double). Another required property of the JVM is + // that, if a trailing argument is added or dropped, the placement + // of other arguments does not change. This allows cases E and F to + // work smoothly, against without any moving or reformatting, + // despite the arity change. + // + if (has_local_signature()) { + Symbol* local_signature = cpool->symbol_at(get_method_signature_index(cpool)); + ciSymbol* sig_sym = env->get_symbol(local_signature); + ciKlass* pool_holder = env->get_klass(cpool->pool_holder()); + ciSignature* call_site_sig = new (env->arena()) ciSignature(pool_holder, cpool, sig_sym); + // Examples of how the call site signature can differ from the method's own signature: + // + // meth = static jboolean java.lang.invoke.VarHandleGuards.guard_LII_Z(jobject, jobject, jint, jint, jobject) + // msig = (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;IILjava/lang/invoke/VarHandle$AccessDescriptor;)Z + // call = (Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;II)Z + // + // meth = static jobject java.lang.invoke.LambdaForm$MH/0x0000000800066840.linkToTargetMethod(jobject, jobject) + // msig = (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + // call = (Ljava/lang/String;)Ljava/util/function/Predicate; + // + (*declared_signature_result) = call_site_sig; + } else { + // We can just use the method's own signature. It may differ from the call site, but not by much. + // + // Examples of how the call site signature can differ from the method's signature: + // + // meth = static final native jint java.lang.invoke.MethodHandle.linkToStatic(jobject, jobject, jint, jint, jobject) + // msig = (Ljava/lang/Object;Ljava/lang/Object;IILjava/lang/invoke/MemberName;)I + // call = (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;IILjava/lang/invoke/MemberName;)Z + // + // meth = final native jint java.lang.invoke.MethodHandle.invokeBasic(jobject, jobject, jint, jint) + // msig = (Ljava/lang/Object;Ljava/lang/Object;II)I + // call = (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;II)Z + // (*declared_signature_result) = m->signature(); } return m; @@ -372,27 +448,14 @@ } // ------------------------------------------------------------------ -// ciBytecodeStream::has_method_type +// ciBytecodeStream::has_local_signature // -// Returns true if there is a MethodType argument stored in the -// constant pool cache at the current bci. -bool ciBytecodeStream::has_method_type() { +// Returns true if the method stored in the constant +// pool cache at the current bci has a local signature. +bool ciBytecodeStream::has_local_signature() { GUARDED_VM_ENTRY( constantPoolHandle cpool(_method->get_Method()->constants()); - return ConstantPool::has_method_type_at_if_loaded(cpool, get_method_index()); - ) -} - -// ------------------------------------------------------------------ -// ciBytecodeStream::get_method_type -// -// Return the MethodType stored in the constant pool cache at -// the current bci. -ciMethodType* ciBytecodeStream::get_method_type() { - GUARDED_VM_ENTRY( - constantPoolHandle cpool(_method->get_Method()->constants()); - oop method_type_oop = ConstantPool::method_type_at_if_loaded(cpool, get_method_index()); - return CURRENT_ENV->get_object(method_type_oop)->as_method_type(); + return ConstantPool::has_local_signature_at_if_loaded(cpool, get_method_index()); ) } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/ci/ciStreams.hpp --- a/src/hotspot/share/ci/ciStreams.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/ci/ciStreams.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -245,8 +245,7 @@ ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result); bool has_appendix(); ciObject* get_appendix(); - bool has_method_type(); - ciMethodType* get_method_type(); + bool has_local_signature(); ciKlass* get_declared_method_holder(); int get_method_holder_index(); int get_method_signature_index(const constantPoolHandle& cpool); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/classfile/classFileParser.cpp --- a/src/hotspot/share/classfile/classFileParser.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/classfile/classFileParser.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -564,7 +564,7 @@ } case JVM_CONSTANT_Dynamic: { const int name_and_type_ref_index = - cp->invoke_dynamic_name_and_type_ref_index_at(index); + cp->bootstrap_name_and_type_ref_index_at(index); check_property(valid_cp_range(name_and_type_ref_index, length) && cp->tag_at(name_and_type_ref_index).is_name_and_type(), @@ -579,7 +579,7 @@ } case JVM_CONSTANT_InvokeDynamic: { const int name_and_type_ref_index = - cp->invoke_dynamic_name_and_type_ref_index_at(index); + cp->bootstrap_name_and_type_ref_index_at(index); check_property(valid_cp_range(name_and_type_ref_index, length) && cp->tag_at(name_and_type_ref_index).is_name_and_type(), @@ -4991,42 +4991,43 @@ bool ClassFileParser::verify_unqualified_name(const char* name, unsigned int length, int type) { - for (const char* p = name; p != name + length;) { - jchar ch = *p; - if (ch < 128) { - if (ch == '.' || ch == ';' || ch == '[' ) { - return false; // do not permit '.', ';', or '[' - } - if (ch == '/') { + for (const char* p = name; p != name + length; p++) { + switch(*p) { + case '.': + case ';': + case '[': + // do not permit '.', ';', or '[' + return false; + case '/': // check for '//' or leading or trailing '/' which are not legal // unqualified name must not be empty if (type == ClassFileParser::LegalClass) { if (p == name || p+1 >= name+length || *(p+1) == '/') { - return false; + return false; } } else { return false; // do not permit '/' unless it's class name } - } - if (type == ClassFileParser::LegalMethod && (ch == '<' || ch == '>')) { - return false; // do not permit '<' or '>' in method names - } - p++; - } else { - char* tmp_p = UTF8::next(p, &ch); - p = tmp_p; + break; + case '<': + case '>': + // do not permit '<' or '>' in method names + if (type == ClassFileParser::LegalMethod) { + return false; + } } } return true; } -// Take pointer to a string. Skip over the longest part of the string that could +// Take pointer to a UTF8 byte string (not NUL-terminated). +// Skip over the longest part of the string that could // be taken as a fieldname. Allow '/' if slash_ok is true. // Return a pointer to just past the fieldname. // Return NULL if no fieldname at all was found, or in the case of slash_ok // being true, we saw consecutive slashes (meaning we were looking for a // qualified path but found something that was badly-formed). -static const char* skip_over_field_name(const char* name, +static const char* skip_over_field_name(const char* const name, bool slash_ok, unsigned int length) { const char* p; @@ -5062,29 +5063,12 @@ // Check if ch is Java identifier start or is Java identifier part // 4672820: call java.lang.Character methods directly without generating separate tables. EXCEPTION_MARK; - // return value JavaValue result(T_BOOLEAN); - // Set up the arguments to isJavaIdentifierStart and isJavaIdentifierPart + // Set up the arguments to isJavaIdentifierStart or isJavaIdentifierPart JavaCallArguments args; args.push_int(unicode_ch); - // public static boolean isJavaIdentifierStart(char ch); - JavaCalls::call_static(&result, - SystemDictionary::Character_klass(), - vmSymbols::isJavaIdentifierStart_name(), - vmSymbols::int_bool_signature(), - &args, - THREAD); - - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - return 0; - } - if (result.get_jboolean()) { - continue; - } - if (not_first_ch) { // public static boolean isJavaIdentifierPart(char ch); JavaCalls::call_static(&result, @@ -5093,15 +5077,21 @@ vmSymbols::int_bool_signature(), &args, THREAD); - - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - return 0; - } - - if (result.get_jboolean()) { - continue; - } + } else { + // public static boolean isJavaIdentifierStart(char ch); + JavaCalls::call_static(&result, + SystemDictionary::Character_klass(), + vmSymbols::isJavaIdentifierStart_name(), + vmSymbols::int_bool_signature(), + &args, + THREAD); + } + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + return NULL; + } + if(result.get_jboolean()) { + continue; } } return (not_first_ch) ? old_p : NULL; @@ -5109,7 +5099,8 @@ return (not_first_ch) ? p : NULL; } -// Take pointer to a string. Skip over the longest part of the string that could +// Take pointer to a UTF8 byte string (not NUL-terminated). +// Skip over the longest part of the string that could // be taken as a field signature. Allow "void" if void_ok. // Return a pointer to just past the signature. // Return NULL if no legal signature is found. @@ -5142,18 +5133,12 @@ } else { // Skip leading 'L' and ignore first appearance of ';' - length--; signature++; - char* c = strchr((char*) signature, ';'); + const char* c = (const char*) memchr(signature, ';', length - 1); // Format check signature if (c != NULL) { - ResourceMark rm(THREAD); int newlen = c - (char*) signature; - char* sig = NEW_RESOURCE_ARRAY(char, newlen + 1); - strncpy(sig, signature, newlen); - sig[newlen] = '\0'; - - bool legal = verify_unqualified_name(sig, newlen, LegalClass); + bool legal = verify_unqualified_name(signature, newlen, LegalClass); if (!legal) { classfile_parse_error("Class name contains illegal character " "in descriptor in class file %s", @@ -5187,8 +5172,8 @@ void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const { if (!_need_verify || _relax_verify) { return; } - char buf[fixed_buffer_size]; - char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); + assert(name->refcount() > 0, "symbol must be kept alive"); + char* bytes = (char*)name->bytes(); unsigned int length = name->utf8_length(); bool legal = false; @@ -5216,7 +5201,7 @@ Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), - "Illegal class name \"%s\" in class file %s", bytes, + "Illegal class name \"%.*s\" in class file %s", length, bytes, _class_name->as_C_string() ); return; @@ -5227,8 +5212,7 @@ void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPS) const { if (!_need_verify || _relax_verify) { return; } - char buf[fixed_buffer_size]; - char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); + char* bytes = (char*)name->bytes(); unsigned int length = name->utf8_length(); bool legal = false; @@ -5250,7 +5234,7 @@ Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), - "Illegal field name \"%s\" in class %s", bytes, + "Illegal field name \"%.*s\" in class %s", length, bytes, _class_name->as_C_string() ); return; @@ -5262,8 +5246,7 @@ if (!_need_verify || _relax_verify) { return; } assert(name != NULL, "method name is null"); - char buf[fixed_buffer_size]; - char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); + char* bytes = (char*)name->bytes(); unsigned int length = name->utf8_length(); bool legal = false; @@ -5288,7 +5271,7 @@ Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), - "Illegal method name \"%s\" in class %s", bytes, + "Illegal method name \"%.*s\" in class %s", length, bytes, _class_name->as_C_string() ); return; @@ -5302,8 +5285,7 @@ TRAPS) const { if (!_need_verify) { return; } - char buf[fixed_buffer_size]; - const char* const bytes = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); + const char* const bytes = (const char* const)signature->bytes(); const unsigned int length = signature->utf8_length(); const char* const p = skip_over_field_signature(bytes, false, length, CHECK); @@ -5332,8 +5314,7 @@ } unsigned int args_size = 0; - char buf[fixed_buffer_size]; - const char* p = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); + const char* p = (const char*)signature->bytes(); unsigned int length = signature->utf8_length(); const char* nextp; @@ -5741,9 +5722,8 @@ void ClassFileParser::update_class_name(Symbol* new_class_name) { // Decrement the refcount in the old name, since we're clobbering it. - if (_class_name != NULL) { - _class_name->decrement_refcount(); - } + _class_name->decrement_refcount(); + _class_name = new_class_name; // Increment the refcount of the new name. // Now the ClassFileParser owns this name and will decrement in @@ -5774,11 +5754,16 @@ // characters. So, do a strncpy instead of using sprintf("%s..."). strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(), class_name_len); + // Decrement old _class_name to avoid leaking. + _class_name->decrement_refcount(); + // Create a symbol and update the anonymous class name. - Symbol* new_name = SymbolTable::new_symbol(new_anon_name, + // The new class name is created with a refcount of one. When installed into the InstanceKlass, + // it'll be two and when the ClassFileParser destructor runs, it'll go back to one and get deleted + // when the class is unloaded. + _class_name = SymbolTable::new_symbol(new_anon_name, (int)host_pkg_len + 1 + class_name_len, CHECK); - update_class_name(new_name); } } @@ -5882,7 +5867,8 @@ _has_vanilla_constructor(false), _max_bootstrap_specifier_index(-1) { - update_class_name(name != NULL ? name : vmSymbols::unknown_class_name()); + _class_name = name != NULL ? name : vmSymbols::unknown_class_name(); + _class_name->increment_refcount(); assert(THREAD->is_Java_thread(), "invariant"); assert(_loader_data != NULL, "invariant"); @@ -6107,8 +6093,7 @@ Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); assert(class_name_in_cp != NULL, "class_name can't be null"); - // Update _class_name which could be null previously - // to reflect the name in the constant pool + // Update _class_name to reflect the name in the constant pool update_class_name(class_name_in_cp); // Don't need to check whether this class name is legal or not. diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/classfile/loaderConstraints.cpp --- a/src/hotspot/share/classfile/loaderConstraints.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/classfile/loaderConstraints.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -77,7 +77,10 @@ if (p->hash() == hash) { if (p->name() == name) { for (int i = p->num_loaders() - 1; i >= 0; i--) { - if (p->loader_data(i) == loader_data) { + if (p->loader_data(i) == loader_data && + // skip unloaded klasses + (p->klass() == NULL || + p->klass()->is_loader_alive())) { return pp; } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/classfile/stringTable.cpp --- a/src/hotspot/share/classfile/stringTable.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/classfile/stringTable.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -334,6 +334,10 @@ if (StringTable::_alt_hash) { hash = hash_string(name, len, true); } + found_string = StringTable::the_table()->do_lookup(name, len, hash); + if (found_string != NULL) { + return found_string; + } return StringTable::the_table()->do_intern(string_or_null_h, name, len, hash, CHECK_NULL); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/classfile/systemDictionary.cpp --- a/src/hotspot/share/classfile/systemDictionary.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -2114,7 +2114,7 @@ ss.print(" wants to load %s %s.", k->external_kind(), k->external_name()); Klass *existing_klass = constraints()->find_constrained_klass(name, class_loader); - if (existing_klass->class_loader() != class_loader()) { + if (existing_klass != NULL && existing_klass->class_loader() != class_loader()) { ss.print(" A different %s with the same name was previously loaded by %s. (%s)", existing_klass->external_kind(), existing_klass->class_loader_data()->loader_name_and_id(), @@ -2459,7 +2459,6 @@ Symbol* signature, Klass* accessing_klass, Handle *appendix_result, - Handle *method_type_result, TRAPS) { methodHandle empty; assert(THREAD->can_call_java() ,""); @@ -2492,7 +2491,6 @@ vmSymbols::linkMethod_signature(), &args, CHECK_(empty)); Handle mname(THREAD, (oop) result.get_jobject()); - (*method_type_result) = method_type; return unpack_method_and_appendix(mname, accessing_klass, appendix_box, appendix_result, THREAD); } @@ -2811,7 +2809,6 @@ Symbol* name, Symbol* type, Handle *appendix_result, - Handle *method_type_result, TRAPS) { methodHandle empty; Handle bsm, info; @@ -2853,7 +2850,6 @@ vmSymbols::linkCallSite_signature(), &args, CHECK_(empty)); Handle mname(THREAD, (oop) result.get_jobject()); - (*method_type_result) = method_type; return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/classfile/systemDictionary.hpp --- a/src/hotspot/share/classfile/systemDictionary.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/classfile/systemDictionary.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -481,7 +481,6 @@ Symbol* signature, Klass* accessing_klass, Handle *appendix_result, - Handle *method_type_result, TRAPS); // for a given signature, find the internal MethodHandle method (linkTo* or invokeBasic) // (does not ask Java, since this is a low-level intrinsic defined by the JVM) @@ -544,7 +543,6 @@ Symbol* name, Symbol* type, Handle *appendix_result, - Handle *method_type_result, TRAPS); // Record the error when the first attempt to resolve a reference from a constant diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/code/dependencyContext.hpp --- a/src/hotspot/share/code/dependencyContext.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/code/dependencyContext.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -107,7 +107,7 @@ _safepoint_counter(SafepointSynchronize::safepoint_counter()) {} ~DependencyContext() { - assert(_safepoint_counter == SafepointSynchronize::safepoint_counter(), "safepoint happened"); + assert(SafepointSynchronize::is_same_safepoint(_safepoint_counter), "must be the same safepoint"); } #else DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -636,8 +636,8 @@ } NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;) - _gc_counters = new CollectorCounters("CMS", 1); - _cgc_counters = new CollectorCounters("CMS stop-the-world phases", 2); + _gc_counters = new CollectorCounters("CMS full collection pauses", 1); + _cgc_counters = new CollectorCounters("CMS concurrent cycle pauses", 2); _completed_initialization = true; _inter_sweep_timer.start(); // start of time } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/cms/parNewGeneration.cpp --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -624,7 +624,7 @@ } ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) - : DefNewGeneration(rs, initial_byte_size, "PCopy"), + : DefNewGeneration(rs, initial_byte_size, "CMS young collection pauses"), _plab_stats("Young", YoungPLABSize, PLABWeight), _overflow_list(NULL), _is_alive_closure(this) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/dirtyCardQueue.cpp --- a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2001, 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. - * - */ - -#include "precompiled.hpp" -#include "gc/g1/dirtyCardQueue.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1FreeIdSet.hpp" -#include "gc/g1/g1RemSet.hpp" -#include "gc/g1/g1ThreadLocalData.hpp" -#include "gc/g1/heapRegionRemSet.hpp" -#include "gc/shared/suspendibleThreadSet.hpp" -#include "gc/shared/workgroup.hpp" -#include "runtime/atomic.hpp" -#include "runtime/flags/flagSetting.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/safepoint.hpp" -#include "runtime/thread.inline.hpp" -#include "runtime/threadSMR.hpp" - -// Closure used for updating remembered sets and recording references that -// point into the collection set while the mutator is running. -// Assumed to be only executed concurrently with the mutator. Yields via -// SuspendibleThreadSet after every card. -class G1RefineCardConcurrentlyClosure: public CardTableEntryClosure { -public: - bool do_card_ptr(jbyte* card_ptr, uint worker_i) { - G1CollectedHeap::heap()->g1_rem_set()->refine_card_concurrently(card_ptr, worker_i); - - if (SuspendibleThreadSet::should_yield()) { - // Caller will actually yield. - return false; - } - // Otherwise, we finished successfully; return true. - return true; - } -}; - -DirtyCardQueue::DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent) : - // Dirty card queues are always active, so we create them with their - // active field set to true. - PtrQueue(qset, permanent, true /* active */) -{ } - -DirtyCardQueue::~DirtyCardQueue() { - if (!is_permanent()) { - flush(); - } -} - -DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : - PtrQueueSet(notify_when_complete), - _shared_dirty_card_queue(this, true /* permanent */), - _free_ids(NULL), - _processed_buffers_mut(0), - _processed_buffers_rs_thread(0), - _cur_par_buffer_node(NULL) -{ - _all_active = true; -} - -DirtyCardQueueSet::~DirtyCardQueueSet() { - delete _free_ids; -} - -// Determines how many mutator threads can process the buffers in parallel. -uint DirtyCardQueueSet::num_par_ids() { - return (uint)os::initial_active_processor_count(); -} - -void DirtyCardQueueSet::initialize(Monitor* cbl_mon, - BufferNode::Allocator* allocator, - Mutex* lock, - bool init_free_ids) { - PtrQueueSet::initialize(cbl_mon, allocator); - _shared_dirty_card_queue.set_lock(lock); - if (init_free_ids) { - _free_ids = new G1FreeIdSet(0, num_par_ids()); - } -} - -void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) { - G1ThreadLocalData::dirty_card_queue(t).handle_zero_index(); -} - -bool DirtyCardQueueSet::apply_closure_to_buffer(CardTableEntryClosure* cl, - BufferNode* node, - bool consume, - uint worker_i) { - if (cl == NULL) return true; - bool result = true; - void** buf = BufferNode::make_buffer_from_node(node); - size_t i = node->index(); - size_t limit = buffer_size(); - for ( ; i < limit; ++i) { - jbyte* card_ptr = static_cast(buf[i]); - assert(card_ptr != NULL, "invariant"); - if (!cl->do_card_ptr(card_ptr, worker_i)) { - result = false; // Incomplete processing. - break; - } - } - if (consume) { - assert(i <= buffer_size(), "invariant"); - node->set_index(i); - } - return result; -} - -#ifndef ASSERT -#define assert_fully_consumed(node, buffer_size) -#else -#define assert_fully_consumed(node, buffer_size) \ - do { \ - size_t _afc_index = (node)->index(); \ - size_t _afc_size = (buffer_size); \ - assert(_afc_index == _afc_size, \ - "Buffer was not fully consumed as claimed: index: " \ - SIZE_FORMAT ", size: " SIZE_FORMAT, \ - _afc_index, _afc_size); \ - } while (0) -#endif // ASSERT - -bool DirtyCardQueueSet::mut_process_buffer(BufferNode* node) { - guarantee(_free_ids != NULL, "must be"); - - uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id - G1RefineCardConcurrentlyClosure cl; - bool result = apply_closure_to_buffer(&cl, node, true, worker_i); - _free_ids->release_par_id(worker_i); // release the id - - if (result) { - assert_fully_consumed(node, buffer_size()); - Atomic::inc(&_processed_buffers_mut); - } - return result; -} - -bool DirtyCardQueueSet::refine_completed_buffer_concurrently(uint worker_i, size_t stop_at) { - G1RefineCardConcurrentlyClosure cl; - return apply_closure_to_completed_buffer(&cl, worker_i, stop_at, false); -} - -bool DirtyCardQueueSet::apply_closure_during_gc(CardTableEntryClosure* cl, uint worker_i) { - assert_at_safepoint(); - return apply_closure_to_completed_buffer(cl, worker_i, 0, true); -} - -bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - uint worker_i, - size_t stop_at, - bool during_pause) { - assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); - BufferNode* nd = get_completed_buffer(stop_at); - if (nd == NULL) { - return false; - } else { - if (apply_closure_to_buffer(cl, nd, true, worker_i)) { - assert_fully_consumed(nd, buffer_size()); - // Done with fully processed buffer. - deallocate_buffer(nd); - Atomic::inc(&_processed_buffers_rs_thread); - } else { - // Return partially processed buffer to the queue. - guarantee(!during_pause, "Should never stop early"); - enqueue_completed_buffer(nd); - } - return true; - } -} - -void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { - BufferNode* nd = _cur_par_buffer_node; - while (nd != NULL) { - BufferNode* next = nd->next(); - BufferNode* actual = Atomic::cmpxchg(next, &_cur_par_buffer_node, nd); - if (actual == nd) { - bool b = apply_closure_to_buffer(cl, nd, false); - guarantee(b, "Should not stop early."); - nd = next; - } else { - nd = actual; - } - } -} - -void DirtyCardQueueSet::abandon_logs() { - assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); - abandon_completed_buffers(); - // Since abandon is done only at safepoints, we can safely manipulate - // these queues. - for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { - G1ThreadLocalData::dirty_card_queue(t).reset(); - } - shared_dirty_card_queue()->reset(); -} - -void DirtyCardQueueSet::concatenate_log(DirtyCardQueue& dcq) { - if (!dcq.is_empty()) { - dcq.flush(); - } -} - -void DirtyCardQueueSet::concatenate_logs() { - // Iterate over all the threads, if we find a partial log add it to - // the global list of logs. Temporarily turn off the limit on the number - // of outstanding buffers. - assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); - size_t old_limit = max_completed_buffers(); - set_max_completed_buffers(MaxCompletedBuffersUnlimited); - for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { - concatenate_log(G1ThreadLocalData::dirty_card_queue(t)); - } - concatenate_log(_shared_dirty_card_queue); - set_max_completed_buffers(old_limit); -} diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/dirtyCardQueue.hpp --- a/src/hotspot/share/gc/g1/dirtyCardQueue.hpp Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2001, 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. - * - */ - -#ifndef SHARE_GC_G1_DIRTYCARDQUEUE_HPP -#define SHARE_GC_G1_DIRTYCARDQUEUE_HPP - -#include "gc/shared/ptrQueue.hpp" -#include "memory/allocation.hpp" - -class DirtyCardQueueSet; -class G1FreeIdSet; -class JavaThread; -class Monitor; - -// A closure class for processing card table entries. Note that we don't -// require these closure objects to be stack-allocated. -class CardTableEntryClosure: public CHeapObj { -public: - // Process the card whose card table entry is "card_ptr". If returns - // "false", terminate the iteration early. - virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i) = 0; -}; - -// A ptrQueue whose elements are "oops", pointers to object heads. -class DirtyCardQueue: public PtrQueue { -public: - DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent = false); - - // Flush before destroying; queue may be used to capture pending work while - // doing something else, with auto-flush on completion. - ~DirtyCardQueue(); - - // Process queue entries and release resources. - void flush() { flush_impl(); } - - // Compiler support. - static ByteSize byte_offset_of_index() { - return PtrQueue::byte_offset_of_index(); - } - using PtrQueue::byte_width_of_index; - - static ByteSize byte_offset_of_buf() { - return PtrQueue::byte_offset_of_buf(); - } - using PtrQueue::byte_width_of_buf; - -}; - - - -class DirtyCardQueueSet: public PtrQueueSet { - DirtyCardQueue _shared_dirty_card_queue; - - // Apply the closure to the elements of "node" from it's index to - // buffer_size. If all closure applications return true, then - // returns true. Stops processing after the first closure - // application that returns false, and returns false from this - // function. If "consume" is true, the node's index is updated to - // exclude the processed elements, e.g. up to the element for which - // the closure returned false. - bool apply_closure_to_buffer(CardTableEntryClosure* cl, - BufferNode* node, - bool consume, - uint worker_i = 0); - - // If there are more than stop_at completed buffers, pop one, apply - // the specified closure to its active elements, and return true. - // Otherwise return false. - // - // A completely processed buffer is freed. However, if a closure - // invocation returns false, processing is stopped and the partially - // processed buffer (with its index updated to exclude the processed - // elements, e.g. up to the element for which the closure returned - // false) is returned to the completed buffer set. - // - // If during_pause is true, stop_at must be zero, and the closure - // must never return false. - bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - uint worker_i, - size_t stop_at, - bool during_pause); - - bool mut_process_buffer(BufferNode* node); - - G1FreeIdSet* _free_ids; - - // The number of completed buffers processed by mutator and rs thread, - // respectively. - jint _processed_buffers_mut; - jint _processed_buffers_rs_thread; - - // Current buffer node used for parallel iteration. - BufferNode* volatile _cur_par_buffer_node; - - void concatenate_log(DirtyCardQueue& dcq); - -public: - DirtyCardQueueSet(bool notify_when_complete = true); - ~DirtyCardQueueSet(); - - void initialize(Monitor* cbl_mon, - BufferNode::Allocator* allocator, - Mutex* lock, - bool init_free_ids = false); - - // The number of parallel ids that can be claimed to allow collector or - // mutator threads to do card-processing work. - static uint num_par_ids(); - - static void handle_zero_index_for_thread(JavaThread* t); - - // Apply G1RefineCardConcurrentlyClosure to completed buffers until there are stop_at - // completed buffers remaining. - bool refine_completed_buffer_concurrently(uint worker_i, size_t stop_at); - - // Apply the given closure to all completed buffers. The given closure's do_card_ptr - // must never return false. Must only be called during GC. - bool apply_closure_during_gc(CardTableEntryClosure* cl, uint worker_i); - - void reset_for_par_iteration() { _cur_par_buffer_node = completed_buffers_head(); } - // Applies the current closure to all completed buffers, non-consumptively. - // Can be used in parallel, all callers using the iteration state initialized - // by reset_for_par_iteration. - void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl); - - DirtyCardQueue* shared_dirty_card_queue() { - return &_shared_dirty_card_queue; - } - - // If a full collection is happening, reset partial logs, and ignore - // completed ones: the full collection will make them all irrelevant. - void abandon_logs(); - - // If any threads have partial logs, add them to the global list of logs. - void concatenate_logs(); - - jint processed_buffers_mut() { - return _processed_buffers_mut; - } - jint processed_buffers_rs_thread() { - return _processed_buffers_rs_thread; - } - -}; - -#endif // SHARE_GC_G1_DIRTYCARDQUEUE_HPP diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1BarrierSet.hpp --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -25,11 +25,10 @@ #ifndef SHARE_GC_G1_G1BARRIERSET_HPP #define SHARE_GC_G1_G1BARRIERSET_HPP -#include "gc/g1/dirtyCardQueue.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" #include "gc/shared/cardTableBarrierSet.hpp" -class DirtyCardQueueSet; class CardTable; class G1CardTable; @@ -42,7 +41,7 @@ BufferNode::Allocator _satb_mark_queue_buffer_allocator; BufferNode::Allocator _dirty_card_queue_buffer_allocator; G1SATBMarkQueueSet _satb_mark_queue_set; - DirtyCardQueueSet _dirty_card_queue_set; + G1DirtyCardQueueSet _dirty_card_queue_set; static G1BarrierSet* g1_barrier_set() { return barrier_set_cast(BarrierSet::barrier_set()); @@ -88,7 +87,7 @@ return g1_barrier_set()->_satb_mark_queue_set; } - static DirtyCardQueueSet& dirty_card_queue_set() { + static G1DirtyCardQueueSet& dirty_card_queue_set() { return g1_barrier_set()->_dirty_card_queue_set; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -37,6 +37,7 @@ #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1FullCollector.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" @@ -107,7 +108,7 @@ // apply to TLAB allocation, which is not part of this interface: it // is done by clients of this interface.) -class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure { +class RedirtyLoggedCardTableEntryClosure : public G1CardTableEntryClosure { private: size_t _num_dirtied; G1CollectedHeap* _g1h; @@ -124,7 +125,7 @@ } public: - RedirtyLoggedCardTableEntryClosure(G1CollectedHeap* g1h) : CardTableEntryClosure(), + RedirtyLoggedCardTableEntryClosure(G1CollectedHeap* g1h) : G1CardTableEntryClosure(), _num_dirtied(0), _g1h(g1h), _g1_ct(g1h->card_table()) { } bool do_card_ptr(jbyte* card_ptr, uint worker_i) { @@ -1811,7 +1812,7 @@ } { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); dcqs.set_process_completed_buffers_threshold(concurrent_refine()->yellow_zone()); dcqs.set_max_completed_buffers(concurrent_refine()->red_zone()); } @@ -1954,12 +1955,12 @@ return _hrm->total_free_bytes(); } -void G1CollectedHeap::iterate_hcc_closure(CardTableEntryClosure* cl, uint worker_i) { +void G1CollectedHeap::iterate_hcc_closure(G1CardTableEntryClosure* cl, uint worker_i) { _hot_card_cache->drain(cl, worker_i); } -void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, uint worker_i) { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); +void G1CollectedHeap::iterate_dirty_card_closure(G1CardTableEntryClosure* cl, uint worker_i) { + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); size_t n_completed_buffers = 0; while (dcqs.apply_closure_during_gc(cl, worker_i)) { n_completed_buffers++; @@ -2605,10 +2606,10 @@ size_t G1CollectedHeap::pending_card_num() { size_t extra_cards = 0; for (JavaThreadIteratorWithHandle jtiwh; JavaThread *curr = jtiwh.next(); ) { - DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(curr); + G1DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(curr); extra_cards += dcq.size(); } - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); size_t buffer_size = dcqs.buffer_size(); size_t buffer_num = dcqs.completed_buffers_num(); @@ -2630,7 +2631,7 @@ size_t _total_humongous; size_t _candidate_humongous; - DirtyCardQueue _dcq; + G1DirtyCardQueue _dcq; bool humongous_region_is_candidate(G1CollectedHeap* g1h, HeapRegion* region) const { assert(region->is_starts_humongous(), "Must start a humongous object"); @@ -3410,10 +3411,10 @@ class G1RedirtyLoggedCardsTask : public AbstractGangTask { private: - DirtyCardQueueSet* _queue; + G1DirtyCardQueueSet* _queue; G1CollectedHeap* _g1h; public: - G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"), + G1RedirtyLoggedCardsTask(G1DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"), _queue(queue), _g1h(g1h) { } virtual void work(uint worker_id) { @@ -3434,7 +3435,7 @@ dirty_card_queue_set().reset_for_par_iteration(); workers()->run_task(&redirty_task); - DirtyCardQueueSet& dcq = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcq = G1BarrierSet::dirty_card_queue_set(); dcq.merge_bufferlists(&dirty_card_queue_set()); assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1CollectedHeap.hpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -31,6 +31,7 @@ #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1EdenRegions.hpp" #include "gc/g1/g1EvacFailure.hpp" #include "gc/g1/g1EvacStats.hpp" @@ -758,7 +759,7 @@ // A set of cards that cover the objects for which the Rsets should be updated // concurrently after the collection. - DirtyCardQueueSet _dirty_card_queue_set; + G1DirtyCardQueueSet _dirty_card_queue_set; // After a collection pause, convert the regions in the collection set into free // regions. @@ -918,7 +919,7 @@ uint num_task_queues() const; // A set of cards where updates happened during the GC - DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } + G1DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } // Create a G1CollectedHeap with the specified policy. // Must call the initialize method afterwards. @@ -983,10 +984,10 @@ void scrub_rem_set(); // Apply the given closure on all cards in the Hot Card Cache, emptying it. - void iterate_hcc_closure(CardTableEntryClosure* cl, uint worker_i); + void iterate_hcc_closure(G1CardTableEntryClosure* cl, uint worker_i); // Apply the given closure on all cards in the Dirty Card Queue Set, emptying it. - void iterate_dirty_card_closure(CardTableEntryClosure* cl, uint worker_i); + void iterate_dirty_card_closure(G1CardTableEntryClosure* cl, uint worker_i); // The shared block offset table array. G1BlockOffsetTable* bot() const { return _bot; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp --- a/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -87,7 +87,7 @@ uint volatile _cur_claim_idx; // Calculates the maximum array size that will be used. - static uint required_array_size(uint num_regions, uint num_workers, uint chunk_size) { + static uint required_array_size(uint num_regions, uint chunk_size, uint num_workers) { uint const max_waste = num_workers * chunk_size; // The array should be aligned with respect to chunk_size. uint const aligned_num_regions = ((num_regions + chunk_size - 1) / chunk_size) * chunk_size; @@ -96,8 +96,8 @@ } public: - G1BuildCandidateArray(uint max_num_regions, uint num_workers, uint chunk_size) : - _max_size(required_array_size(max_num_regions, num_workers, chunk_size)), + G1BuildCandidateArray(uint max_num_regions, uint chunk_size, uint num_workers) : + _max_size(required_array_size(max_num_regions, chunk_size, num_workers)), _chunk_size(chunk_size), _data(NEW_C_HEAP_ARRAY(HeapRegion*, _max_size, mtGC)), _cur_claim_idx(0) { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ConcurrentMark.cpp --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -30,6 +30,7 @@ #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1Policy.hpp" @@ -372,7 +373,7 @@ // _finger set in set_non_marking_state - _worker_id_offset(DirtyCardQueueSet::num_par_ids() + G1ConcRefinementThreads), + _worker_id_offset(G1DirtyCardQueueSet::num_par_ids() + G1ConcRefinementThreads), _max_num_tasks(ParallelGCThreads), // _num_active_tasks set in set_non_marking_state() // _tasks set inside the constructor diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "runtime/java.hpp" @@ -378,7 +379,7 @@ void G1ConcurrentRefine::adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms) { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); if (G1UseAdaptiveConcRefinement) { update_zones(update_rs_time, update_rs_processed_buffers, goal_ms); @@ -386,7 +387,7 @@ // Change the barrier params if (max_num_threads() == 0) { // Disable dcqs notification when there are no threads to notify. - dcqs.set_process_completed_buffers_threshold(DirtyCardQueueSet::ProcessCompletedBuffersThresholdNever); + dcqs.set_process_completed_buffers_threshold(G1DirtyCardQueueSet::ProcessCompletedBuffersThresholdNever); } else { // Worker 0 is the primary; wakeup is via dcqs notification. STATIC_ASSERT(max_yellow_zone <= INT_MAX); @@ -417,7 +418,7 @@ } uint G1ConcurrentRefine::worker_id_offset() { - return DirtyCardQueueSet::num_par_ids(); + return G1DirtyCardQueueSet::num_par_ids(); } void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) { @@ -427,7 +428,7 @@ } bool G1ConcurrentRefine::do_refinement_step(uint worker_id) { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); size_t curr_buffer_num = dcqs.completed_buffers_num(); // If the number of the buffers falls down into the yellow zone, diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -29,7 +29,6 @@ #include "utilities/globalDefinitions.hpp" // Forward decl -class CardTableEntryClosure; class G1ConcurrentRefine; class G1ConcurrentRefineThread; class outputStream; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -65,7 +66,7 @@ } bool G1ConcurrentRefineThread::is_active() { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); return is_primary() ? dcqs.process_completed_buffers() : _active; } @@ -74,7 +75,7 @@ if (!is_primary()) { set_active(true); } else { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); dcqs.set_process_completed_buffers(true); } _monitor->notify(); @@ -85,7 +86,7 @@ if (!is_primary()) { set_active(false); } else { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); dcqs.set_process_completed_buffers(false); } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -25,11 +25,9 @@ #ifndef SHARE_GC_G1_G1CONCURRENTREFINETHREAD_HPP #define SHARE_GC_G1_G1CONCURRENTREFINETHREAD_HPP -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/shared/concurrentGCThread.hpp" // Forward Decl. -class CardTableEntryClosure; class G1ConcurrentRefine; // One or more G1 Concurrent Refinement Threads may be active if concurrent diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2001, 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. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" +#include "gc/g1/g1FreeIdSet.hpp" +#include "gc/g1/g1RemSet.hpp" +#include "gc/g1/g1ThreadLocalData.hpp" +#include "gc/g1/heapRegionRemSet.hpp" +#include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/shared/workgroup.hpp" +#include "runtime/atomic.hpp" +#include "runtime/flags/flagSetting.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/threadSMR.hpp" + +// Closure used for updating remembered sets and recording references that +// point into the collection set while the mutator is running. +// Assumed to be only executed concurrently with the mutator. Yields via +// SuspendibleThreadSet after every card. +class G1RefineCardConcurrentlyClosure: public G1CardTableEntryClosure { +public: + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { + G1CollectedHeap::heap()->g1_rem_set()->refine_card_concurrently(card_ptr, worker_i); + + if (SuspendibleThreadSet::should_yield()) { + // Caller will actually yield. + return false; + } + // Otherwise, we finished successfully; return true. + return true; + } +}; + +G1DirtyCardQueue::G1DirtyCardQueue(G1DirtyCardQueueSet* qset, bool permanent) : + // Dirty card queues are always active, so we create them with their + // active field set to true. + PtrQueue(qset, permanent, true /* active */) +{ } + +G1DirtyCardQueue::~G1DirtyCardQueue() { + if (!is_permanent()) { + flush(); + } +} + +G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) : + PtrQueueSet(notify_when_complete), + _shared_dirty_card_queue(this, true /* permanent */), + _free_ids(NULL), + _processed_buffers_mut(0), + _processed_buffers_rs_thread(0), + _cur_par_buffer_node(NULL) +{ + _all_active = true; +} + +G1DirtyCardQueueSet::~G1DirtyCardQueueSet() { + delete _free_ids; +} + +// Determines how many mutator threads can process the buffers in parallel. +uint G1DirtyCardQueueSet::num_par_ids() { + return (uint)os::initial_active_processor_count(); +} + +void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon, + BufferNode::Allocator* allocator, + Mutex* lock, + bool init_free_ids) { + PtrQueueSet::initialize(cbl_mon, allocator); + _shared_dirty_card_queue.set_lock(lock); + if (init_free_ids) { + _free_ids = new G1FreeIdSet(0, num_par_ids()); + } +} + +void G1DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) { + G1ThreadLocalData::dirty_card_queue(t).handle_zero_index(); +} + +bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl, + BufferNode* node, + bool consume, + uint worker_i) { + if (cl == NULL) return true; + bool result = true; + void** buf = BufferNode::make_buffer_from_node(node); + size_t i = node->index(); + size_t limit = buffer_size(); + for ( ; i < limit; ++i) { + jbyte* card_ptr = static_cast(buf[i]); + assert(card_ptr != NULL, "invariant"); + if (!cl->do_card_ptr(card_ptr, worker_i)) { + result = false; // Incomplete processing. + break; + } + } + if (consume) { + assert(i <= buffer_size(), "invariant"); + node->set_index(i); + } + return result; +} + +#ifndef ASSERT +#define assert_fully_consumed(node, buffer_size) +#else +#define assert_fully_consumed(node, buffer_size) \ + do { \ + size_t _afc_index = (node)->index(); \ + size_t _afc_size = (buffer_size); \ + assert(_afc_index == _afc_size, \ + "Buffer was not fully consumed as claimed: index: " \ + SIZE_FORMAT ", size: " SIZE_FORMAT, \ + _afc_index, _afc_size); \ + } while (0) +#endif // ASSERT + +bool G1DirtyCardQueueSet::mut_process_buffer(BufferNode* node) { + guarantee(_free_ids != NULL, "must be"); + + uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id + G1RefineCardConcurrentlyClosure cl; + bool result = apply_closure_to_buffer(&cl, node, true, worker_i); + _free_ids->release_par_id(worker_i); // release the id + + if (result) { + assert_fully_consumed(node, buffer_size()); + Atomic::inc(&_processed_buffers_mut); + } + return result; +} + +bool G1DirtyCardQueueSet::refine_completed_buffer_concurrently(uint worker_i, size_t stop_at) { + G1RefineCardConcurrentlyClosure cl; + return apply_closure_to_completed_buffer(&cl, worker_i, stop_at, false); +} + +bool G1DirtyCardQueueSet::apply_closure_during_gc(G1CardTableEntryClosure* cl, uint worker_i) { + assert_at_safepoint(); + return apply_closure_to_completed_buffer(cl, worker_i, 0, true); +} + +bool G1DirtyCardQueueSet::apply_closure_to_completed_buffer(G1CardTableEntryClosure* cl, + uint worker_i, + size_t stop_at, + bool during_pause) { + assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); + BufferNode* nd = get_completed_buffer(stop_at); + if (nd == NULL) { + return false; + } else { + if (apply_closure_to_buffer(cl, nd, true, worker_i)) { + assert_fully_consumed(nd, buffer_size()); + // Done with fully processed buffer. + deallocate_buffer(nd); + Atomic::inc(&_processed_buffers_rs_thread); + } else { + // Return partially processed buffer to the queue. + guarantee(!during_pause, "Should never stop early"); + enqueue_completed_buffer(nd); + } + return true; + } +} + +void G1DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl) { + BufferNode* nd = _cur_par_buffer_node; + while (nd != NULL) { + BufferNode* next = nd->next(); + BufferNode* actual = Atomic::cmpxchg(next, &_cur_par_buffer_node, nd); + if (actual == nd) { + bool b = apply_closure_to_buffer(cl, nd, false); + guarantee(b, "Should not stop early."); + nd = next; + } else { + nd = actual; + } + } +} + +void G1DirtyCardQueueSet::abandon_logs() { + assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); + abandon_completed_buffers(); + // Since abandon is done only at safepoints, we can safely manipulate + // these queues. + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + G1ThreadLocalData::dirty_card_queue(t).reset(); + } + shared_dirty_card_queue()->reset(); +} + +void G1DirtyCardQueueSet::concatenate_log(G1DirtyCardQueue& dcq) { + if (!dcq.is_empty()) { + dcq.flush(); + } +} + +void G1DirtyCardQueueSet::concatenate_logs() { + // Iterate over all the threads, if we find a partial log add it to + // the global list of logs. Temporarily turn off the limit on the number + // of outstanding buffers. + assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); + size_t old_limit = max_completed_buffers(); + set_max_completed_buffers(MaxCompletedBuffersUnlimited); + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + concatenate_log(G1ThreadLocalData::dirty_card_queue(t)); + } + concatenate_log(_shared_dirty_card_queue); + set_max_completed_buffers(old_limit); +} diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001, 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. + * + */ + +#ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP +#define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP + +#include "gc/shared/ptrQueue.hpp" +#include "memory/allocation.hpp" + +class G1DirtyCardQueueSet; +class G1FreeIdSet; +class JavaThread; +class Monitor; + +// A closure class for processing card table entries. Note that we don't +// require these closure objects to be stack-allocated. +class G1CardTableEntryClosure: public CHeapObj { +public: + // Process the card whose card table entry is "card_ptr". If returns + // "false", terminate the iteration early. + virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i) = 0; +}; + +// A ptrQueue whose elements are "oops", pointers to object heads. +class G1DirtyCardQueue: public PtrQueue { +public: + G1DirtyCardQueue(G1DirtyCardQueueSet* qset, bool permanent = false); + + // Flush before destroying; queue may be used to capture pending work while + // doing something else, with auto-flush on completion. + ~G1DirtyCardQueue(); + + // Process queue entries and release resources. + void flush() { flush_impl(); } + + // Compiler support. + static ByteSize byte_offset_of_index() { + return PtrQueue::byte_offset_of_index(); + } + using PtrQueue::byte_width_of_index; + + static ByteSize byte_offset_of_buf() { + return PtrQueue::byte_offset_of_buf(); + } + using PtrQueue::byte_width_of_buf; + +}; + + + +class G1DirtyCardQueueSet: public PtrQueueSet { + G1DirtyCardQueue _shared_dirty_card_queue; + + // Apply the closure to the elements of "node" from it's index to + // buffer_size. If all closure applications return true, then + // returns true. Stops processing after the first closure + // application that returns false, and returns false from this + // function. If "consume" is true, the node's index is updated to + // exclude the processed elements, e.g. up to the element for which + // the closure returned false. + bool apply_closure_to_buffer(G1CardTableEntryClosure* cl, + BufferNode* node, + bool consume, + uint worker_i = 0); + + // If there are more than stop_at completed buffers, pop one, apply + // the specified closure to its active elements, and return true. + // Otherwise return false. + // + // A completely processed buffer is freed. However, if a closure + // invocation returns false, processing is stopped and the partially + // processed buffer (with its index updated to exclude the processed + // elements, e.g. up to the element for which the closure returned + // false) is returned to the completed buffer set. + // + // If during_pause is true, stop_at must be zero, and the closure + // must never return false. + bool apply_closure_to_completed_buffer(G1CardTableEntryClosure* cl, + uint worker_i, + size_t stop_at, + bool during_pause); + + bool mut_process_buffer(BufferNode* node); + + G1FreeIdSet* _free_ids; + + // The number of completed buffers processed by mutator and rs thread, + // respectively. + jint _processed_buffers_mut; + jint _processed_buffers_rs_thread; + + // Current buffer node used for parallel iteration. + BufferNode* volatile _cur_par_buffer_node; + + void concatenate_log(G1DirtyCardQueue& dcq); + +public: + G1DirtyCardQueueSet(bool notify_when_complete = true); + ~G1DirtyCardQueueSet(); + + void initialize(Monitor* cbl_mon, + BufferNode::Allocator* allocator, + Mutex* lock, + bool init_free_ids = false); + + // The number of parallel ids that can be claimed to allow collector or + // mutator threads to do card-processing work. + static uint num_par_ids(); + + static void handle_zero_index_for_thread(JavaThread* t); + + // Apply G1RefineCardConcurrentlyClosure to completed buffers until there are stop_at + // completed buffers remaining. + bool refine_completed_buffer_concurrently(uint worker_i, size_t stop_at); + + // Apply the given closure to all completed buffers. The given closure's do_card_ptr + // must never return false. Must only be called during GC. + bool apply_closure_during_gc(G1CardTableEntryClosure* cl, uint worker_i); + + void reset_for_par_iteration() { _cur_par_buffer_node = completed_buffers_head(); } + // Applies the current closure to all completed buffers, non-consumptively. + // Can be used in parallel, all callers using the iteration state initialized + // by reset_for_par_iteration. + void par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl); + + G1DirtyCardQueue* shared_dirty_card_queue() { + return &_shared_dirty_card_queue; + } + + // If a full collection is happening, reset partial logs, and ignore + // completed ones: the full collection will make them all irrelevant. + void abandon_logs(); + + // If any threads have partial logs, add them to the global list of logs. + void concatenate_logs(); + + jint processed_buffers_mut() { + return _processed_buffers_mut; + } + jint processed_buffers_rs_thread() { + return _processed_buffers_rs_thread; + } + +}; + +#endif // SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1EvacFailure.cpp --- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -23,10 +23,10 @@ */ #include "precompiled.hpp" -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1EvacFailure.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" @@ -41,11 +41,11 @@ class UpdateRSetDeferred : public BasicOopIterateClosure { private: G1CollectedHeap* _g1h; - DirtyCardQueue* _dcq; + G1DirtyCardQueue* _dcq; G1CardTable* _ct; public: - UpdateRSetDeferred(DirtyCardQueue* dcq) : + UpdateRSetDeferred(G1DirtyCardQueue* dcq) : _g1h(G1CollectedHeap::heap()), _dcq(dcq), _ct(_g1h->card_table()) {} virtual void do_oop(narrowOop* p) { do_oop_work(p); } @@ -196,7 +196,7 @@ uint _worker_id; HeapRegionClaimer* _hrclaimer; - DirtyCardQueue _dcq; + G1DirtyCardQueue _dcq; UpdateRSetDeferred _update_rset_cl; public: diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1HotCardCache.cpp --- a/src/hotspot/share/gc/g1/g1HotCardCache.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1HotCardCache.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, 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 @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1HotCardCache.hpp" #include "runtime/atomic.hpp" @@ -83,7 +83,7 @@ return (previous_ptr == current_ptr) ? previous_ptr : card_ptr; } -void G1HotCardCache::drain(CardTableEntryClosure* cl, uint worker_i) { +void G1HotCardCache::drain(G1CardTableEntryClosure* cl, uint worker_i) { assert(default_use_cache(), "Drain only necessary if we use the hot card cache."); assert(_hot_cache != NULL, "Logic"); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1HotCardCache.hpp --- a/src/hotspot/share/gc/g1/g1HotCardCache.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1HotCardCache.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -32,8 +32,7 @@ #include "runtime/thread.hpp" #include "utilities/globalDefinitions.hpp" -class CardTableEntryClosure; -class DirtyCardQueue; +class G1CardTableEntryClosure; class G1CollectedHeap; class HeapRegion; @@ -112,7 +111,7 @@ // Refine the cards that have delayed as a result of // being in the cache. - void drain(CardTableEntryClosure* cl, uint worker_i); + void drain(G1CardTableEntryClosure* cl, uint worker_i); // Set up for parallel processing of the cards in the hot cache void reset_hot_cache_claimed_index() { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1MonitoringSupport.cpp --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -119,15 +119,15 @@ // name "collector.0". In a generational collector this would be the // young generation collection. _incremental_collection_counters = - new CollectorCounters("G1 incremental collections", 0); + new CollectorCounters("G1 young collection pauses", 0); // name "collector.1". In a generational collector this would be the // old generation collection. _full_collection_counters = - new CollectorCounters("G1 stop-the-world full collections", 1); + new CollectorCounters("G1 full collection pauses", 1); // name "collector.2". In a generational collector this would be the // STW phases in concurrent collection. _conc_collection_counters = - new CollectorCounters("G1 stop-the-world phases", 2); + new CollectorCounters("G1 concurrent cycle pauses", 2); // "Generation" and "Space" counters. // diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ParScanThreadState.hpp --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -25,9 +25,9 @@ #ifndef SHARE_GC_G1_G1PARSCANTHREADSTATE_HPP #define SHARE_GC_G1_G1PARSCANTHREADSTATE_HPP -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RemSet.hpp" @@ -46,7 +46,7 @@ class G1ParScanThreadState : public CHeapObj { G1CollectedHeap* _g1h; RefToScanQueue* _refs; - DirtyCardQueue _dcq; + G1DirtyCardQueue _dcq; G1CardTable* _ct; G1EvacuationRootClosures* _closures; @@ -77,7 +77,7 @@ #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t)) - DirtyCardQueue& dirty_card_queue() { return _dcq; } + G1DirtyCardQueue& dirty_card_queue() { return _dcq; } G1CardTable* ct() { return _ct; } InCSetState dest(InCSetState original) const { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1RemSet.cpp --- a/src/hotspot/share/gc/g1/g1RemSet.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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,12 +23,12 @@ */ #include "precompiled.hpp" -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BlockOffsetTable.inline.hpp" #include "gc/g1/g1CardTable.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1FromCardCache.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HotCardCache.hpp" @@ -300,7 +300,7 @@ } uint G1RemSet::num_par_rem_sets() { - return DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads); + return G1DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads() + MAX2(ConcGCThreads, ParallelGCThreads); } void G1RemSet::initialize(size_t capacity, uint max_regions) { @@ -456,7 +456,7 @@ } // Closure used for updating rem sets. Only called during an evacuation pause. -class G1RefineCardClosure: public CardTableEntryClosure { +class G1RefineCardClosure: public G1CardTableEntryClosure { G1RemSet* _g1rs; G1ScanObjsDuringUpdateRSClosure* _update_rs_cl; @@ -520,7 +520,7 @@ } void G1RemSet::prepare_for_oops_into_collection_set_do() { - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); dcqs.concatenate_logs(); _scan_state->reset(); @@ -677,7 +677,7 @@ *card_ptr = G1CardTable::dirty_card_val(); MutexLockerEx x(Shared_DirtyCardQ_lock, Mutex::_no_safepoint_check_flag); - DirtyCardQueue* sdcq = + G1DirtyCardQueue* sdcq = G1BarrierSet::dirty_card_queue_set().shared_dirty_card_queue(); sdcq->enqueue(card_ptr); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1RemSet.hpp --- a/src/hotspot/share/gc/g1/g1RemSet.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1RemSet.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -25,7 +25,6 @@ #ifndef SHARE_GC_G1_G1REMSET_HPP #define SHARE_GC_G1_G1REMSET_HPP -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1RemSetSummary.cpp --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -26,6 +26,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1RemSet.hpp" #include "gc/g1/g1RemSetSummary.hpp" #include "gc/g1/g1YoungRemSetSamplingThread.hpp" @@ -53,7 +54,7 @@ void G1RemSetSummary::update() { _num_conc_refined_cards = _rem_set->num_conc_refined_cards(); - DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); _num_processed_buf_mutator = dcqs.processed_buffers_mut(); _num_processed_buf_rs_threads = dcqs.processed_buffers_rs_thread(); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/g1ThreadLocalData.hpp --- a/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -24,8 +24,8 @@ #ifndef SHARE_GC_G1_G1THREADLOCALDATA_HPP #define SHARE_GC_G1_G1THREADLOCALDATA_HPP -#include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1BarrierSet.hpp" +#include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/shared/satbMarkQueue.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" @@ -33,8 +33,8 @@ class G1ThreadLocalData { private: - SATBMarkQueue _satb_mark_queue; - DirtyCardQueue _dirty_card_queue; + SATBMarkQueue _satb_mark_queue; + G1DirtyCardQueue _dirty_card_queue; G1ThreadLocalData() : _satb_mark_queue(&G1BarrierSet::satb_mark_queue_set()), @@ -66,7 +66,7 @@ return data(thread)->_satb_mark_queue; } - static DirtyCardQueue& dirty_card_queue(Thread* thread) { + static G1DirtyCardQueue& dirty_card_queue(Thread* thread) { return data(thread)->_dirty_card_queue; } @@ -83,11 +83,11 @@ } static ByteSize dirty_card_queue_index_offset() { - return dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index(); + return dirty_card_queue_offset() + G1DirtyCardQueue::byte_offset_of_index(); } static ByteSize dirty_card_queue_buffer_offset() { - return dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_buf(); + return dirty_card_queue_offset() + G1DirtyCardQueue::byte_offset_of_buf(); } }; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/g1/vmStructs_g1.hpp --- a/src/hotspot/share/gc/g1/vmStructs_g1.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -102,7 +102,7 @@ declare_toplevel_type(PtrQueue) \ declare_toplevel_type(HeapRegionType) \ declare_toplevel_type(SATBMarkQueue) \ - declare_toplevel_type(DirtyCardQueue) \ + declare_toplevel_type(G1DirtyCardQueue) \ \ declare_toplevel_type(G1CollectedHeap*) \ declare_toplevel_type(HeapRegion*) \ diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/parallel/psMarkSweep.cpp --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -72,7 +72,7 @@ void PSMarkSweep::initialize() { _span_based_discoverer.set_span(ParallelScavengeHeap::heap()->reserved_region()); set_ref_processor(new ReferenceProcessor(&_span_based_discoverer)); // a vanilla ref proc - _counters = new CollectorCounters("PSMarkSweep", 1); + _counters = new CollectorCounters("Serial full collection pauses", 1); MarkSweep::initialize(); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/parallel/psParallelCompact.cpp --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -883,7 +883,7 @@ new PCReferenceProcessor(&_span_based_discoverer, &_is_alive_closure); // non-header is alive closure - _counters = new CollectorCounters("PSParallelCompact", 1); + _counters = new CollectorCounters("Parallel full collection pauses", 1); // Initialize static fields in ParCompactionManager. ParCompactionManager::initialize(mark_bitmap()); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/parallel/psScavenge.cpp --- a/src/hotspot/share/gc/parallel/psScavenge.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -754,5 +754,5 @@ // Cache the cardtable _card_table = heap->card_table(); - _counters = new CollectorCounters("PSScavenge", 0); + _counters = new CollectorCounters("Parallel young collection pauses", 0); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/serial/defNewGeneration.hpp --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -192,7 +192,7 @@ public: DefNewGeneration(ReservedSpace rs, size_t initial_byte_size, - const char* policy="Copy"); + const char* policy="Serial young collection pauses"); virtual void ref_processor_init(); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/serial/tenuredGeneration.cpp --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -65,7 +65,7 @@ _gen_counters = new GenerationCounters(gen_name, 1, 1, gcp->min_old_size(), gcp->max_old_size(), &_virtual_space); - _gc_counters = new CollectorCounters("MSC", 1); + _gc_counters = new CollectorCounters("Serial full collection pauses", 1); _space_counters = new CSpaceCounters(gen_name, 0, _virtual_space.reserved_size(), diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/shared/c2/barrierSetC2.cpp --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -75,6 +75,7 @@ bool mismatched = (decorators & C2_MISMATCHED) != 0; bool unaligned = (decorators & C2_UNALIGNED) != 0; + bool unsafe = (decorators & C2_UNSAFE_ACCESS) != 0; bool requires_atomic_access = (decorators & MO_UNORDERED) == 0; bool in_native = (decorators & IN_NATIVE) != 0; @@ -93,7 +94,7 @@ } store = kit->store_to_memory(kit->control(), access.addr().node(), val.node(), access.type(), - access.addr().type(), mo, requires_atomic_access, unaligned, mismatched); + access.addr().type(), mo, requires_atomic_access, unaligned, mismatched, unsafe); access.set_raw_access(store); } else { assert(!requires_atomic_access, "not yet supported"); @@ -132,6 +133,7 @@ bool unaligned = (decorators & C2_UNALIGNED) != 0; bool control_dependent = (decorators & C2_CONTROL_DEPENDENT_LOAD) != 0; bool pinned = (decorators & C2_PINNED_LOAD) != 0; + bool unsafe = (decorators & C2_UNSAFE_ACCESS) != 0; bool in_native = (decorators & IN_NATIVE) != 0; @@ -148,7 +150,7 @@ load = kit->make_load(control, adr, val_type, access.type(), mo); } else { load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo, - dep, requires_atomic_access, unaligned, mismatched); + dep, requires_atomic_access, unaligned, mismatched, unsafe); } access.set_raw_access(load); } else { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -130,7 +130,7 @@ ZBarrierSetC2State* s = bs->state(); if (s->load_barrier_count() >= 2) { Compile::TracePhase tp("idealLoop", &C->timers[Phase::_t_idealLoop]); - PhaseIdealLoop ideal_loop(igvn, LoopOptsLastRound); + PhaseIdealLoop::optimize(igvn, LoopOptsLastRound); if (C->major_progress()) C->print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/gc/z/zServiceability.cpp --- a/src/hotspot/share/gc/z/zServiceability.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/gc/z/zServiceability.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -72,8 +72,8 @@ max_capacity /* max_capacity */, min_capacity /* init_capacity */), // gc.collector.2 - _collector_counters("stop-the-world" /* name */, - 2 /* ordinal */) {} + _collector_counters("Z concurrent cycle pauses" /* name */, + 2 /* ordinal */) {} CollectorCounters* ZServiceabilityCounters::collector_counters() { return &_collector_counters; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/interpreter/bytecodeTracer.cpp --- a/src/hotspot/share/interpreter/bytecodeTracer.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/interpreter/bytecodeTracer.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -382,7 +382,7 @@ st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string()); } else { if (tag.is_dynamic_constant() || tag.is_invoke_dynamic()) { - int bsm = constants->invoke_dynamic_bootstrap_method_ref_index_at(i); + int bsm = constants->bootstrap_method_ref_index_at(i); st->print(" bsm=%d", bsm); } st->print_cr(" %d <%s%s%s>", i, name->as_C_string(), sep, signature->as_C_string()); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/interpreter/interpreterRuntime.cpp --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -977,9 +977,6 @@ LastFrameAccessor last_frame(thread); const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; - //TO DO: consider passing BCI to Java. - // int caller_bci = last_frame.method()->bci_from(last_frame.bcp()); - // resolve method CallInfo info; constantPoolHandle pool(thread, last_frame.method()->constants()); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/interpreter/linkResolver.cpp --- a/src/hotspot/share/interpreter/linkResolver.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/interpreter/linkResolver.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -94,26 +94,21 @@ } void CallInfo::set_handle(const methodHandle& resolved_method, - Handle resolved_appendix, - Handle resolved_method_type, TRAPS) { - set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, resolved_method_type, CHECK); + Handle resolved_appendix, TRAPS) { + set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, CHECK); } void CallInfo::set_handle(Klass* resolved_klass, const methodHandle& resolved_method, - Handle resolved_appendix, - Handle resolved_method_type, TRAPS) { - if (resolved_method.is_null()) { - THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); - } + Handle resolved_appendix, TRAPS) { + guarantee(resolved_method.not_null(), "resolved method is null"); assert(resolved_method->intrinsic_id() == vmIntrinsics::_invokeBasic || resolved_method->is_compiled_lambda_form(), "linkMethod must return one of these"); int vtable_index = Method::nonvirtual_vtable_index; assert(!resolved_method->has_vtable_index(), ""); set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); - _resolved_appendix = resolved_appendix; - _resolved_method_type = resolved_method_type; + _resolved_appendix = resolved_appendix; } void CallInfo::set_common(Klass* resolved_klass, @@ -452,7 +447,6 @@ methodHandle LinkResolver::lookup_polymorphic_method( const LinkInfo& link_info, Handle *appendix_result_or_null, - Handle *method_type_result, TRAPS) { Klass* klass = link_info.resolved_klass(); Symbol* name = link_info.name(); @@ -520,7 +514,6 @@ full_signature, link_info.current_klass(), &appendix, - &method_type, CHECK_NULL); if (TraceMethodHandles) { ttyLocker ttyl; @@ -552,7 +545,6 @@ assert(appendix_result_or_null != NULL, ""); (*appendix_result_or_null) = appendix; - (*method_type_result) = method_type; } return result; } @@ -760,7 +752,7 @@ if (resolved_method.is_null()) { // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc - resolved_method = lookup_polymorphic_method(link_info, (Handle*)NULL, (Handle*)NULL, THREAD); + resolved_method = lookup_polymorphic_method(link_info, (Handle*)NULL, THREAD); if (HAS_PENDING_EXCEPTION) { nested_exception = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; @@ -1697,10 +1689,8 @@ resolved_klass == SystemDictionary::VarHandle_klass(), ""); assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); Handle resolved_appendix; - Handle resolved_method_type; - methodHandle resolved_method = lookup_polymorphic_method(link_info, - &resolved_appendix, &resolved_method_type, CHECK); - result.set_handle(resolved_klass, resolved_method, resolved_appendix, resolved_method_type, CHECK); + methodHandle resolved_method = lookup_polymorphic_method(link_info, &resolved_appendix, CHECK); + result.set_handle(resolved_klass, resolved_method, resolved_appendix, CHECK); } void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { @@ -1737,8 +1727,7 @@ if (!cpce->is_f1_null()) { methodHandle method( THREAD, cpce->f1_as_method()); Handle appendix( THREAD, cpce->appendix_if_resolved(pool)); - Handle method_type(THREAD, cpce->method_type_if_resolved(pool)); - result.set_handle(method, appendix, method_type, THREAD); + result.set_handle(method, appendix, THREAD); Exceptions::wrap_dynamic_exception(CHECK); return; } @@ -1766,8 +1755,7 @@ if (!cpce->is_f1_null()) { methodHandle method( THREAD, cpce->f1_as_method()); Handle appendix( THREAD, cpce->appendix_if_resolved(pool)); - Handle method_type(THREAD, cpce->method_type_if_resolved(pool)); - result.set_handle(method, appendix, method_type, THREAD); + result.set_handle(method, appendix, THREAD); Exceptions::wrap_dynamic_exception(CHECK); } else { assert(cpce->indy_resolution_failed(), "Resolution failure flag not set"); @@ -1788,17 +1776,15 @@ // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...) // The appendix argument is likely to be a freshly-created CallSite. Handle resolved_appendix; - Handle resolved_method_type; methodHandle resolved_method = SystemDictionary::find_dynamic_call_site_invoker(current_klass, pool_index, bootstrap_specifier, method_name, method_signature, &resolved_appendix, - &resolved_method_type, THREAD); Exceptions::wrap_dynamic_exception(CHECK); - result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD); + result.set_handle(resolved_method, resolved_appendix, THREAD); Exceptions::wrap_dynamic_exception(CHECK); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/interpreter/linkResolver.hpp --- a/src/hotspot/share/interpreter/linkResolver.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/interpreter/linkResolver.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -55,7 +55,6 @@ // others inferred), vtable, itable) int _call_index; // vtable or itable index of selected class method (if any) Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) - Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) Handle _resolved_method_name; // Object holding the ResolvedMethodName void set_static(Klass* resolved_klass, const methodHandle& resolved_method, TRAPS); @@ -68,10 +67,10 @@ const methodHandle& selected_method, int vtable_index, TRAPS); void set_handle(const methodHandle& resolved_method, - Handle resolved_appendix, Handle resolved_method_type, TRAPS); + Handle resolved_appendix, TRAPS); void set_handle(Klass* resolved_klass, const methodHandle& resolved_method, - Handle resolved_appendix, Handle resolved_method_type, TRAPS); + Handle resolved_appendix, TRAPS); void set_common(Klass* resolved_klass, Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, @@ -98,7 +97,6 @@ methodHandle resolved_method() const { return _resolved_method; } methodHandle selected_method() const { return _selected_method; } Handle resolved_appendix() const { return _resolved_appendix; } - Handle resolved_method_type() const { return _resolved_method_type; } Handle resolved_method_name() const { return _resolved_method_name; } // Materialize a java.lang.invoke.ResolvedMethodName for this resolved_method void set_resolved_method_name(TRAPS); @@ -207,8 +205,7 @@ static Method* lookup_method_in_interfaces(const LinkInfo& link_info); static methodHandle lookup_polymorphic_method(const LinkInfo& link_info, - Handle *appendix_result_or_null, - Handle *method_type_result, TRAPS); + Handle *appendix_result_or_null, TRAPS); JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod() // Not Linktime so doesn't take LinkInfo static methodHandle lookup_instance_method_in_klasses (Klass* klass, Symbol* name, Symbol* signature, diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/interpreter/rewriter.cpp --- a/src/hotspot/share/interpreter/rewriter.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/interpreter/rewriter.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -221,13 +221,13 @@ MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(), _pool->name_ref_at(cp_index))) { // we may need a resolved_refs entry for the appendix - add_invokedynamic_resolved_references_entries(cp_index, cache_index); + add_invokedynamic_resolved_references_entry(cp_index, cache_index); status = +1; } else if (_pool->klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_VarHandle() && MethodHandles::is_signature_polymorphic_name(SystemDictionary::VarHandle_klass(), _pool->name_ref_at(cp_index))) { // we may need a resolved_refs entry for the appendix - add_invokedynamic_resolved_references_entries(cp_index, cache_index); + add_invokedynamic_resolved_references_entry(cp_index, cache_index); status = +1; } else { status = -1; @@ -259,7 +259,7 @@ if (!reverse) { int cp_index = Bytes::get_Java_u2(p); int cache_index = add_invokedynamic_cp_cache_entry(cp_index); - int resolved_index = add_invokedynamic_resolved_references_entries(cp_index, cache_index); + int resolved_index = add_invokedynamic_resolved_references_entry(cp_index, cache_index); // Replace the trailing four bytes with a CPC index for the dynamic // call site. Unlike other CPC entries, there is one per bytecode, // not just one per distinct CP entry. In other words, the @@ -307,12 +307,9 @@ // invokedynamic resolved references map also points to cp cache and must // add delta to each. int resolved_index = _patch_invokedynamic_refs->at(i); - for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) { - assert(_invokedynamic_references_map.at(resolved_index + entry) == cache_index, + assert(_invokedynamic_references_map.at(resolved_index) == cache_index, "should be the same index"); - _invokedynamic_references_map.at_put(resolved_index+entry, - cache_index + delta); - } + _invokedynamic_references_map.at_put(resolved_index, cache_index + delta); } } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/interpreter/rewriter.hpp --- a/src/hotspot/share/interpreter/rewriter.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/interpreter/rewriter.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -159,19 +159,12 @@ return ref_index; } - // add a new entries to the resolved_references map (for invokedynamic and invokehandle only) - int add_invokedynamic_resolved_references_entries(int cp_index, int cache_index) { + // add a new entry to the resolved_references map (for invokedynamic and invokehandle only) + int add_invokedynamic_resolved_references_entry(int cp_index, int cache_index) { assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration"); - int ref_index = -1; - for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) { - const int index = _resolved_references_map.append(cp_index); // many-to-one - assert(index >= _resolved_reference_limit, ""); - if (entry == 0) { - ref_index = index; - } - assert((index - entry) == ref_index, "entries must be consecutive"); - _invokedynamic_references_map.at_put_grow(index, cache_index, -1); - } + int ref_index = _resolved_references_map.append(cp_index); // many-to-one + assert(ref_index >= _resolved_reference_limit, ""); + _invokedynamic_references_map.at_put_grow(ref_index, cache_index, -1); return ref_index; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -238,9 +238,8 @@ assert(_thread_group_name == NULL, "invariant"); if (tgname != NULL) { size_t len = strlen(tgname); - _thread_group_name = JfrCHeapObj::new_array(len+1); - strncpy(_thread_group_name, tgname, len); - _thread_group_name[len] = '\0'; + _thread_group_name = JfrCHeapObj::new_array(len + 1); + strncpy(_thread_group_name, tgname, len + 1); } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp --- a/src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkState.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -100,8 +100,7 @@ assert(path != NULL, "invariant"); const size_t path_len = strlen(path); char* new_path = JfrCHeapObj::new_array(path_len + 1); - strncpy(new_path, path, path_len); - new_path[path_len] = '\0'; + strncpy(new_path, path, path_len + 1); return new_path; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -82,10 +82,6 @@ Heap_lock->unlock(); } - if (Safepoint_lock->owned_by_self()) { - Safepoint_lock->unlock(); - } - if (VMOperationQueue_lock->owned_by_self()) { VMOperationQueue_lock->unlock(); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp --- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -209,8 +209,7 @@ if (entry_name == NULL) { return NULL; } - strncpy(entry_name, entry, entry_len); - entry_name[entry_len] = '\0'; + strncpy(entry_name, entry, entry_len + 1); const char* const fully_qualified_path_entry = fully_qualified(entry_name); if (NULL == fully_qualified_path_entry) { return NULL; @@ -332,8 +331,7 @@ if (NULL == emergency_dump_path) { return NULL; } - strncpy(emergency_dump_path, buffer, emergency_filename_length); - emergency_dump_path[emergency_filename_length] = '\0'; + strncpy(emergency_dump_path, buffer, emergency_filename_length + 1); } return emergency_dump_path; } @@ -407,8 +405,7 @@ if (_path == NULL) { return false; } - strncpy(_path, path, path_len); - _path[path_len] = '\0'; + strncpy(_path, path, path_len + 1); return true; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -383,8 +383,7 @@ } bool JfrStackTrace::record_safe(JavaThread* thread, int skip, bool leakp /* false */) { - assert(SafepointSynchronize::safepoint_safe(thread, thread->thread_state()) - || thread == Thread::current(), "Thread stack needs to be walkable"); + assert(thread == Thread::current(), "Thread stack needs to be walkable"); vframeStream vfs(thread); u4 count = 0; _reached_root = true; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/jvmci/jvmciCompilerToVM.cpp --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1241,7 +1241,6 @@ vmassert(MethodHandles::is_signature_polymorphic_method(resolved_method()),"!"); vmassert(!MethodHandles::is_signature_polymorphic_static(resolved_method->intrinsic_id()), "!"); vmassert(cp_cache_entry->appendix_if_resolved(cp) == NULL, "!"); - vmassert(cp_cache_entry->method_type_if_resolved(cp) == NULL, "!"); methodHandle m(LinkResolver::linktime_resolve_virtual_method_or_null(link_info)); vmassert(m == resolved_method, "!!"); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/memory/memRegion.hpp --- a/src/hotspot/share/memory/memRegion.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/memory/memRegion.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -34,7 +34,9 @@ // Note that MemRegions are passed by value, not by reference. // The intent is that they remain very small and contain no -// objects. These should never be allocated in heap but we do +// objects. The copy constructor and destructor must be trivial, +// to support optimization for pass-by-value. +// These should never be allocated in heap but we do // create MemRegions (in CardTableBarrierSet) in heap so operator // new and operator new [] added for this special case. @@ -59,8 +61,6 @@ assert(end >= start, "incorrect constructor arguments"); } - MemRegion(const MemRegion& mr): _start(mr._start), _word_size(mr._word_size) {} - MemRegion intersection(const MemRegion mr2) const; // regions must overlap or be adjacent MemRegion _union(const MemRegion mr2) const; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/constantPool.cpp --- a/src/hotspot/share/oops/constantPool.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/constantPool.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -594,21 +594,13 @@ } -bool ConstantPool::has_method_type_at_if_loaded(const constantPoolHandle& cpool, int which) { +bool ConstantPool::has_local_signature_at_if_loaded(const constantPoolHandle& cpool, int which) { if (cpool->cache() == NULL) return false; // nothing to load yet int cache_index = decode_cpcache_index(which, true); ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); - return e->has_method_type(); + return e->has_local_signature(); } -oop ConstantPool::method_type_at_if_loaded(const constantPoolHandle& cpool, int which) { - if (cpool->cache() == NULL) return NULL; // nothing to load yet - int cache_index = decode_cpcache_index(which, true); - ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); - return e->method_type_if_resolved(cpool); -} - - Symbol* ConstantPool::impl_name_ref_at(int which, bool uncached) { int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached)); return symbol_at(name_index); @@ -625,26 +617,22 @@ if (!uncached && cache() != NULL) { if (ConstantPool::is_invokedynamic_index(which)) { // Invokedynamic index is index into the constant pool cache - int pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index(); - pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index); + int pool_index = invokedynamic_bootstrap_ref_index_at(which); + pool_index = bootstrap_name_and_type_ref_index_at(pool_index); assert(tag_at(pool_index).is_name_and_type(), ""); return pool_index; } // change byte-ordering and go via cache i = remap_instruction_operand_from_cache(which); } else { - if (tag_at(which).is_invoke_dynamic() || - tag_at(which).is_dynamic_constant() || - tag_at(which).is_dynamic_constant_in_error()) { - int pool_index = invoke_dynamic_name_and_type_ref_index_at(which); + if (tag_at(which).has_bootstrap()) { + int pool_index = bootstrap_name_and_type_ref_index_at(which); assert(tag_at(pool_index).is_name_and_type(), ""); return pool_index; } } assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); - assert(!tag_at(i).is_invoke_dynamic() && - !tag_at(i).is_dynamic_constant() && - !tag_at(i).is_dynamic_constant_in_error(), "Must be handled above"); + assert(!tag_at(i).has_bootstrap(), "Must be handled above"); jint ref_index = *int_at_addr(i); return extract_high_short_from_int(ref_index); } @@ -654,7 +642,7 @@ if (!uncached && cache() != NULL) { if (ConstantPool::is_invokedynamic_index(which)) { // Invokedynamic index is index into resolved_references - pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index(); + pool_index = invokedynamic_bootstrap_ref_index_at(which); } else { // change byte-ordering and go via cache pool_index = remap_instruction_operand_from_cache(which); @@ -1128,14 +1116,14 @@ // JVM_CONSTANT_Dynamic is an ordered pair of [bootm, name&ftype], plus optional arguments // In both cases, the bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry. // It is accompanied by the optional arguments. - int bsm_index = this_cp->invoke_dynamic_bootstrap_method_ref_index_at(index); + int bsm_index = this_cp->bootstrap_method_ref_index_at(index); oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL); if (!java_lang_invoke_MethodHandle::is_instance(bsm_oop)) { THROW_MSG_NULL(vmSymbols::java_lang_LinkageError(), "BSM not an MethodHandle"); } // Extract the optional static arguments. - argc = this_cp->invoke_dynamic_argument_count_at(index); + argc = this_cp->bootstrap_argument_count_at(index); // if there are no static arguments, return the bsm by itself: if (argc == 0 && UseBootstrapCallInfo < 2) return bsm_oop; @@ -1177,7 +1165,7 @@ if (!use_BSCI && this_cp->tag_at(index).is_dynamic_constant()) { bool found_unresolved_condy = false; for (int i = 0; i < argc; i++) { - int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i); + int arg_index = this_cp->bootstrap_argument_index_at(index, i); if (this_cp->tag_at(arg_index).is_dynamic_constant()) { // potential recursion point condy -> condy bool found_it = false; @@ -1197,7 +1185,7 @@ bool all_resolved = true; for (int i = 0; i < argc; i++) { bool found_it = false; - int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i); + int arg_index = this_cp->bootstrap_argument_index_at(index, i); this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL); if (!found_it) { all_resolved = false; break; } } @@ -1244,7 +1232,7 @@ !(this_cp->tag_at(index).is_invoke_dynamic() || this_cp->tag_at(index).is_dynamic_constant()) || (0 > start_arg || start_arg > end_arg) || - (end_arg > (argc = this_cp->invoke_dynamic_argument_count_at(index))) || + (end_arg > (argc = this_cp->bootstrap_argument_count_at(index))) || (0 > pos || pos > limit) || (info.is_null() || limit > info->length())) { // An index or something else went wrong; throw an error. @@ -1255,7 +1243,7 @@ // now we can loop safely int info_i = pos; for (int i = start_arg; i < end_arg; i++) { - int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i); + int arg_index = this_cp->bootstrap_argument_index_at(index, i); oop arg_oop; if (must_resolve) { arg_oop = this_cp->resolve_possibly_cached_constant_at(arg_index, CHECK); @@ -1454,10 +1442,10 @@ case JVM_CONSTANT_Dynamic: { - int k1 = invoke_dynamic_name_and_type_ref_index_at(index1); - int k2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2); - int i1 = invoke_dynamic_bootstrap_specifier_index(index1); - int i2 = cp2->invoke_dynamic_bootstrap_specifier_index(index2); + int k1 = bootstrap_name_and_type_ref_index_at(index1); + int k2 = cp2->bootstrap_name_and_type_ref_index_at(index2); + int i1 = bootstrap_methods_attribute_index(index1); + int i2 = cp2->bootstrap_methods_attribute_index(index2); // separate statements and variables because CHECK_false is used bool match_entry = compare_entry_to(k1, cp2, k2, CHECK_false); bool match_operand = compare_operand_to(i1, cp2, i2, CHECK_false); @@ -1466,10 +1454,10 @@ case JVM_CONSTANT_InvokeDynamic: { - int k1 = invoke_dynamic_name_and_type_ref_index_at(index1); - int k2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2); - int i1 = invoke_dynamic_bootstrap_specifier_index(index1); - int i2 = cp2->invoke_dynamic_bootstrap_specifier_index(index2); + int k1 = bootstrap_name_and_type_ref_index_at(index1); + int k2 = cp2->bootstrap_name_and_type_ref_index_at(index2); + int i1 = bootstrap_methods_attribute_index(index1); + int i2 = cp2->bootstrap_methods_attribute_index(index2); // separate statements and variables because CHECK_false is used bool match_entry = compare_entry_to(k1, cp2, k2, CHECK_false); bool match_operand = compare_operand_to(i1, cp2, i2, CHECK_false); @@ -1793,16 +1781,16 @@ case JVM_CONSTANT_Dynamic: case JVM_CONSTANT_DynamicInError: { - int k1 = from_cp->invoke_dynamic_bootstrap_specifier_index(from_i); - int k2 = from_cp->invoke_dynamic_name_and_type_ref_index_at(from_i); + int k1 = from_cp->bootstrap_methods_attribute_index(from_i); + int k2 = from_cp->bootstrap_name_and_type_ref_index_at(from_i); k1 += operand_array_length(to_cp->operands()); // to_cp might already have operands to_cp->dynamic_constant_at_put(to_i, k1, k2); } break; case JVM_CONSTANT_InvokeDynamic: { - int k1 = from_cp->invoke_dynamic_bootstrap_specifier_index(from_i); - int k2 = from_cp->invoke_dynamic_name_and_type_ref_index_at(from_i); + int k1 = from_cp->bootstrap_methods_attribute_index(from_i); + int k2 = from_cp->bootstrap_name_and_type_ref_index_at(from_i); k1 += operand_array_length(to_cp->operands()); // to_cp might already have operands to_cp->invoke_dynamic_at_put(to_i, k1, k2); } break; @@ -2252,7 +2240,7 @@ *bytes = tag; idx1 = extract_low_short_from_int(*int_at_addr(idx)); idx2 = extract_high_short_from_int(*int_at_addr(idx)); - assert(idx2 == invoke_dynamic_name_and_type_ref_index_at(idx), "correct half of u4"); + assert(idx2 == bootstrap_name_and_type_ref_index_at(idx), "correct half of u4"); Bytes::put_Java_u2((address) (bytes+1), idx1); Bytes::put_Java_u2((address) (bytes+3), idx2); DBG(printf("JVM_CONSTANT_Dynamic: %hd %hd", idx1, idx2)); @@ -2262,7 +2250,7 @@ *bytes = tag; idx1 = extract_low_short_from_int(*int_at_addr(idx)); idx2 = extract_high_short_from_int(*int_at_addr(idx)); - assert(idx2 == invoke_dynamic_name_and_type_ref_index_at(idx), "correct half of u4"); + assert(idx2 == bootstrap_name_and_type_ref_index_at(idx), "correct half of u4"); Bytes::put_Java_u2((address) (bytes+1), idx1); Bytes::put_Java_u2((address) (bytes+3), idx2); DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd", idx1, idx2)); @@ -2443,12 +2431,12 @@ case JVM_CONSTANT_Dynamic : case JVM_CONSTANT_DynamicInError : { - st->print("bootstrap_method_index=%d", invoke_dynamic_bootstrap_method_ref_index_at(index)); - st->print(" type_index=%d", invoke_dynamic_name_and_type_ref_index_at(index)); - int argc = invoke_dynamic_argument_count_at(index); + st->print("bootstrap_method_index=%d", bootstrap_method_ref_index_at(index)); + st->print(" type_index=%d", bootstrap_name_and_type_ref_index_at(index)); + int argc = bootstrap_argument_count_at(index); if (argc > 0) { for (int arg_i = 0; arg_i < argc; arg_i++) { - int arg = invoke_dynamic_argument_index_at(index, arg_i); + int arg = bootstrap_argument_index_at(index, arg_i); st->print((arg_i == 0 ? " arguments={%d" : ", %d"), arg); } st->print("}"); @@ -2457,12 +2445,12 @@ break; case JVM_CONSTANT_InvokeDynamic : { - st->print("bootstrap_method_index=%d", invoke_dynamic_bootstrap_method_ref_index_at(index)); - st->print(" name_and_type_index=%d", invoke_dynamic_name_and_type_ref_index_at(index)); - int argc = invoke_dynamic_argument_count_at(index); + st->print("bootstrap_method_index=%d", bootstrap_method_ref_index_at(index)); + st->print(" name_and_type_index=%d", bootstrap_name_and_type_ref_index_at(index)); + int argc = bootstrap_argument_count_at(index); if (argc > 0) { for (int arg_i = 0; arg_i < argc; arg_i++) { - int arg = invoke_dynamic_argument_index_at(index, arg_i); + int arg = bootstrap_argument_index_at(index, arg_i); st->print((arg_i == 0 ? " arguments={%d" : ", %d"), arg); } st->print("}"); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/constantPool.hpp --- a/src/hotspot/share/oops/constantPool.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/constantPool.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -246,16 +246,22 @@ // The invokedynamic points at a CP cache entry. This entry points back // at the original CP entry (CONSTANT_InvokeDynamic) and also (via f2) at an entry // in the resolved_references array (which provides the appendix argument). - int invokedynamic_cp_cache_index(int index) const { - assert (is_invokedynamic_index(index), "should be a invokedynamic index"); - int cache_index = decode_invokedynamic_index(index); + int invokedynamic_cp_cache_index(int indy_index) const { + assert(is_invokedynamic_index(indy_index), "should be a invokedynamic index"); + int cache_index = decode_invokedynamic_index(indy_index); return cache_index; } - ConstantPoolCacheEntry* invokedynamic_cp_cache_entry_at(int index) const { + ConstantPoolCacheEntry* invokedynamic_cp_cache_entry_at(int indy_index) const { // decode index that invokedynamic points to. - int cp_cache_index = invokedynamic_cp_cache_index(index); + int cp_cache_index = invokedynamic_cp_cache_index(indy_index); return cache()->entry_at(cp_cache_index); } + // Given the per-instruction index of an indy instruction, report the + // main constant pool entry for its bootstrap specifier. + // From there, uncached_name/signature_ref_at will get the name/type. + int invokedynamic_bootstrap_ref_index_at(int indy_index) const { + return invokedynamic_cp_cache_entry_at(indy_index)->constant_pool_index(); + } // Assembly code support static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); } @@ -294,14 +300,14 @@ *int_at_addr(which) = ref_index; } - void dynamic_constant_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) { + void dynamic_constant_at_put(int which, int bsms_attribute_index, int name_and_type_index) { tag_at_put(which, JVM_CONSTANT_Dynamic); - *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index; + *int_at_addr(which) = ((jint) name_and_type_index<<16) | bsms_attribute_index; } - void invoke_dynamic_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) { + void invoke_dynamic_at_put(int which, int bsms_attribute_index, int name_and_type_index) { tag_at_put(which, JVM_CONSTANT_InvokeDynamic); - *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index; + *int_at_addr(which) = ((jint) name_and_type_index<<16) | bsms_attribute_index; } void unresolved_string_at_put(int which, Symbol* s) { @@ -534,26 +540,22 @@ return symbol_at(sym); } - int invoke_dynamic_name_and_type_ref_index_at(int which) { - assert(tag_at(which).is_invoke_dynamic() || - tag_at(which).is_dynamic_constant() || - tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool"); + int bootstrap_name_and_type_ref_index_at(int which) { + assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); return extract_high_short_from_int(*int_at_addr(which)); } - int invoke_dynamic_bootstrap_specifier_index(int which) { - assert(tag_at(which).is_invoke_dynamic() || - tag_at(which).is_dynamic_constant() || - tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool"); + int bootstrap_methods_attribute_index(int which) { + assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(which)); } - int invoke_dynamic_operand_base(int which) { - int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which); - return operand_offset_at(operands(), bootstrap_specifier_index); + int bootstrap_operand_base(int which) { + int bsms_attribute_index = bootstrap_methods_attribute_index(which); + return operand_offset_at(operands(), bsms_attribute_index); } // The first part of the operands array consists of an index into the second part. // Extract a 32-bit index value from the first part. - static int operand_offset_at(Array* operands, int bootstrap_specifier_index) { - int n = (bootstrap_specifier_index * 2); + static int operand_offset_at(Array* operands, int bsms_attribute_index) { + int n = (bsms_attribute_index * 2); assert(n >= 0 && n+2 <= operands->length(), "oob"); // The first 32-bit index points to the beginning of the second part // of the operands array. Make sure this index is in the first part. @@ -566,8 +568,8 @@ assert(offset == 0 || offset >= second_part && offset <= operands->length(), "oob (3)"); return offset; } - static void operand_offset_at_put(Array* operands, int bootstrap_specifier_index, int offset) { - int n = bootstrap_specifier_index * 2; + static void operand_offset_at_put(Array* operands, int bsms_attribute_index, int offset) { + int n = bsms_attribute_index * 2; assert(n >= 0 && n+2 <= operands->length(), "oob"); operands->at_put(n+0, extract_low_short_from_int(offset)); operands->at_put(n+1, extract_high_short_from_int(offset)); @@ -580,20 +582,23 @@ #ifdef ASSERT // operand tuples fit together exactly, end to end - static int operand_limit_at(Array* operands, int bootstrap_specifier_index) { - int nextidx = bootstrap_specifier_index + 1; + static int operand_limit_at(Array* operands, int bsms_attribute_index) { + int nextidx = bsms_attribute_index + 1; if (nextidx == operand_array_length(operands)) return operands->length(); else return operand_offset_at(operands, nextidx); } - int invoke_dynamic_operand_limit(int which) { - int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which); - return operand_limit_at(operands(), bootstrap_specifier_index); + int bootstrap_operand_limit(int which) { + int bsms_attribute_index = bootstrap_methods_attribute_index(which); + return operand_limit_at(operands(), bsms_attribute_index); } #endif //ASSERT - // layout of InvokeDynamic and Dynamic bootstrap method specifier (in second part of operands array): + // Layout of InvokeDynamic and Dynamic bootstrap method specifier + // data in second part of operands array. This encodes one record in + // the BootstrapMethods attribute. The whole specifier also includes + // the name and type information from the main constant pool entry. enum { _indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm _indy_argc_offset = 1, // u2 argc @@ -602,35 +607,35 @@ // These functions are used in RedefineClasses for CP merge - int operand_offset_at(int bootstrap_specifier_index) { - assert(0 <= bootstrap_specifier_index && - bootstrap_specifier_index < operand_array_length(operands()), + int operand_offset_at(int bsms_attribute_index) { + assert(0 <= bsms_attribute_index && + bsms_attribute_index < operand_array_length(operands()), "Corrupted CP operands"); - return operand_offset_at(operands(), bootstrap_specifier_index); + return operand_offset_at(operands(), bsms_attribute_index); } - int operand_bootstrap_method_ref_index_at(int bootstrap_specifier_index) { - int offset = operand_offset_at(bootstrap_specifier_index); + int operand_bootstrap_method_ref_index_at(int bsms_attribute_index) { + int offset = operand_offset_at(bsms_attribute_index); return operands()->at(offset + _indy_bsm_offset); } - int operand_argument_count_at(int bootstrap_specifier_index) { - int offset = operand_offset_at(bootstrap_specifier_index); + int operand_argument_count_at(int bsms_attribute_index) { + int offset = operand_offset_at(bsms_attribute_index); int argc = operands()->at(offset + _indy_argc_offset); return argc; } - int operand_argument_index_at(int bootstrap_specifier_index, int j) { - int offset = operand_offset_at(bootstrap_specifier_index); + int operand_argument_index_at(int bsms_attribute_index, int j) { + int offset = operand_offset_at(bsms_attribute_index); return operands()->at(offset + _indy_argv_offset + j); } - int operand_next_offset_at(int bootstrap_specifier_index) { - int offset = operand_offset_at(bootstrap_specifier_index) + _indy_argv_offset - + operand_argument_count_at(bootstrap_specifier_index); + int operand_next_offset_at(int bsms_attribute_index) { + int offset = operand_offset_at(bsms_attribute_index) + _indy_argv_offset + + operand_argument_count_at(bsms_attribute_index); return offset; } - // Compare a bootsrap specifier in the operands arrays - bool compare_operand_to(int bootstrap_specifier_index1, const constantPoolHandle& cp2, - int bootstrap_specifier_index2, TRAPS); - // Find a bootsrap specifier in the operands array - int find_matching_operand(int bootstrap_specifier_index, const constantPoolHandle& search_cp, + // Compare a bootstrap specifier data in the operands arrays + bool compare_operand_to(int bsms_attribute_index1, const constantPoolHandle& cp2, + int bsms_attribute_index2, TRAPS); + // Find a bootstrap specifier data in the operands array + int find_matching_operand(int bsms_attribute_index, const constantPoolHandle& search_cp, int operands_cur_len, TRAPS); // Resize the operands array with delta_len and delta_size void resize_operands(int delta_len, int delta_size, TRAPS); @@ -639,26 +644,22 @@ // Shrink the operands array to a smaller array with new_len length void shrink_operands(int new_len, TRAPS); - int invoke_dynamic_bootstrap_method_ref_index_at(int which) { - assert(tag_at(which).is_invoke_dynamic() || - tag_at(which).is_dynamic_constant() || - tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool"); - int op_base = invoke_dynamic_operand_base(which); + int bootstrap_method_ref_index_at(int which) { + assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); + int op_base = bootstrap_operand_base(which); return operands()->at(op_base + _indy_bsm_offset); } - int invoke_dynamic_argument_count_at(int which) { - assert(tag_at(which).is_invoke_dynamic() || - tag_at(which).is_dynamic_constant() || - tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool"); - int op_base = invoke_dynamic_operand_base(which); + int bootstrap_argument_count_at(int which) { + assert(tag_at(which).has_bootstrap(), "Corrupted constant pool"); + int op_base = bootstrap_operand_base(which); int argc = operands()->at(op_base + _indy_argc_offset); DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc; - int next_offset = invoke_dynamic_operand_limit(which)); + int next_offset = bootstrap_operand_limit(which)); assert(end_offset == next_offset, "matched ending"); return argc; } - int invoke_dynamic_argument_index_at(int which, int j) { - int op_base = invoke_dynamic_operand_base(which); + int bootstrap_argument_index_at(int which, int j) { + int op_base = bootstrap_operand_base(which); DEBUG_ONLY(int argc = operands()->at(op_base + _indy_argc_offset)); assert((uint)j < (uint)argc, "oob"); return operands()->at(op_base + _indy_argv_offset + j); @@ -796,8 +797,7 @@ static Method* method_at_if_loaded (const constantPoolHandle& this_cp, int which); static bool has_appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); static oop appendix_at_if_loaded (const constantPoolHandle& this_cp, int which); - static bool has_method_type_at_if_loaded (const constantPoolHandle& this_cp, int which); - static oop method_type_at_if_loaded (const constantPoolHandle& this_cp, int which); + static bool has_local_signature_at_if_loaded (const constantPoolHandle& this_cp, int which); static Klass* klass_at_if_loaded (const constantPoolHandle& this_cp, int which); // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/cpCache.cpp --- a/src/hotspot/share/oops/cpCache.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/cpCache.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -392,23 +392,22 @@ const methodHandle adapter = call_info.resolved_method(); const Handle appendix = call_info.resolved_appendix(); - const Handle method_type = call_info.resolved_method_type(); const bool has_appendix = appendix.not_null(); - const bool has_method_type = method_type.not_null(); // Write the flags. + // MHs and indy are always sig-poly and have a local signature. set_method_flags(as_TosState(adapter->result_type()), - ((has_appendix ? 1 : 0) << has_appendix_shift ) | - ((has_method_type ? 1 : 0) << has_method_type_shift) | - ( 1 << is_final_shift ), + ((has_appendix ? 1 : 0) << has_appendix_shift ) | + ( 1 << has_local_signature_shift ) | + ( 1 << is_final_shift ), adapter->size_of_parameters()); if (TraceInvokeDynamic) { ttyLocker ttyl; - tty->print_cr("set_method_handle bc=%d appendix=" PTR_FORMAT "%s method_type=" PTR_FORMAT "%s method=" PTR_FORMAT " ", + tty->print_cr("set_method_handle bc=%d appendix=" PTR_FORMAT "%s method=" PTR_FORMAT " (local signature) ", invoke_code, - p2i(appendix()), (has_appendix ? "" : " (unused)"), - p2i(method_type()), (has_method_type ? "" : " (unused)"), + p2i(appendix()), + (has_appendix ? "" : " (unused)"), p2i(adapter())); adapter->print(); if (has_appendix) appendix()->print(); @@ -435,20 +434,12 @@ // Store appendix, if any. if (has_appendix) { - const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset; + const int appendix_index = f2_as_index(); assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); resolved_references->obj_at_put(appendix_index, appendix()); } - // Store MethodType, if any. - if (has_method_type) { - const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset; - assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob"); - assert(resolved_references->obj_at(method_type_index) == NULL, "init just once"); - resolved_references->obj_at_put(method_type_index, method_type()); - } - release_set_f1(adapter()); // This must be the last one to set (see NOTE above)! // The interpreter assembly code does not check byte_2, @@ -459,6 +450,9 @@ ttyLocker ttyl; this->print(tty, 0); } + + assert(has_appendix == this->has_appendix(), "proper storage of appendix flag"); + assert(this->has_local_signature(), "proper storage of signature flag"); } bool ConstantPoolCacheEntry::save_and_throw_indy_exc( @@ -544,16 +538,7 @@ oop ConstantPoolCacheEntry::appendix_if_resolved(const constantPoolHandle& cpool) { if (!has_appendix()) return NULL; - const int ref_index = f2_as_index() + _indy_resolved_references_appendix_offset; - objArrayOop resolved_references = cpool->resolved_references(); - return resolved_references->obj_at(ref_index); -} - - -oop ConstantPoolCacheEntry::method_type_if_resolved(const constantPoolHandle& cpool) { - if (!has_method_type()) - return NULL; - const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset; + const int ref_index = f2_as_index(); objArrayOop resolved_references = cpool->resolved_references(); return resolved_references->obj_at(ref_index); } @@ -701,16 +686,7 @@ for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) { const int cpci = invokedynamic_references_map.at(ref); if (cpci >= 0) { -#ifdef ASSERT - // invokedynamic and invokehandle have more entries; check if they - // all point to the same constant pool cache entry. - for (int entry = 1; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) { - const int cpci_next = invokedynamic_references_map.at(ref + entry); - assert(cpci == cpci_next, "%d == %d", cpci, cpci_next); - } -#endif entry_at(cpci)->initialize_resolved_reference_index(ref); - ref += ConstantPoolCacheEntry::_indy_resolved_references_entries - 1; // skip extra entries } } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/cpCache.hpp --- a/src/hotspot/share/oops/cpCache.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/cpCache.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -51,7 +51,7 @@ // _f2 [ entry specific ] vtable or res_ref index, or vfinal method ptr // _flags [tos|0|F=1|0|0|0|f|v|0 |0000|field_index] (for field entries) // bit length [ 4 |1| 1 |1|1|1|1|1|1 |1 |-3-|----16-----] -// _flags [tos|0|F=0|M|A|I|f|0|vf|indy_rf|000|00000|psize] (for method entries) +// _flags [tos|0|F=0|S|A|I|f|0|vf|indy_rf|000|00000|psize] (for method entries) // bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|--8--|--8--] // -------------------------------- @@ -114,7 +114,7 @@ // _f2 = vtable/itable index (or final Method*) for virtual calls only, // unused by non-virtual. The is_vfinal flag indicates this is a // method pointer for a final method, not an index. -// _flags = method type info (t section), +// _flags = has local signature (MHs and indy), // virtual final bit (vfinal), // parameter size (psize section) // @@ -180,7 +180,7 @@ tos_state_shift = BitsPerInt - tos_state_bits, // see verify_tos_state_shift below // misc. option bits; can be any bit position in [16..27] is_field_entry_shift = 26, // (F) is it a field or a method? - has_method_type_shift = 25, // (M) does the call site have a MethodType? + has_local_signature_shift = 25, // (S) does the call site have a per-site signature (sig-poly methods)? has_appendix_shift = 24, // (A) does the call site have an appendix argument? is_forced_virtual_shift = 23, // (I) is the interface reference forced to virtual mode? is_final_shift = 22, // (f) is the field or method final? @@ -291,19 +291,10 @@ bool save_and_throw_indy_exc(const constantPoolHandle& cpool, int cpool_index, int index, constantTag tag, TRAPS); - // invokedynamic and invokehandle call sites have two entries in the - // resolved references array: - // appendix (at index+0) - // MethodType (at index+1) - enum { - _indy_resolved_references_appendix_offset = 0, - _indy_resolved_references_method_type_offset = 1, - _indy_resolved_references_entries - }; - + // invokedynamic and invokehandle call sites have an "appendix" item in the + // resolved references array. Method* method_if_resolved(const constantPoolHandle& cpool); oop appendix_if_resolved(const constantPoolHandle& cpool); - oop method_type_if_resolved(const constantPoolHandle& cpool); void set_parameter_size(int value); @@ -356,7 +347,7 @@ bool is_vfinal() const { return (_flags & (1 << is_vfinal_shift)) != 0; } bool indy_resolution_failed() const; bool has_appendix() const; - bool has_method_type() const; + bool has_local_signature() const; bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } bool is_long() const { return flag_state() == ltos; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/cpCache.inline.hpp --- a/src/hotspot/share/oops/cpCache.inline.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/cpCache.inline.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -71,8 +71,8 @@ return (!is_f1_null()) && (_flags & (1 << has_appendix_shift)) != 0; } -inline bool ConstantPoolCacheEntry::has_method_type() const { - return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; +inline bool ConstantPoolCacheEntry::has_local_signature() const { + return (!is_f1_null()) && (_flags & (1 << has_local_signature_shift)) != 0; } inline intx ConstantPoolCacheEntry::flags_ord() const { return (intx)OrderAccess::load_acquire(&_flags); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/instanceKlass.cpp --- a/src/hotspot/share/oops/instanceKlass.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/instanceKlass.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -75,6 +75,7 @@ #include "services/classLoadingService.hpp" #include "services/threadService.hpp" #include "utilities/dtrace.hpp" +#include "utilities/events.hpp" #include "utilities/macros.hpp" #include "utilities/stringUtils.hpp" #ifdef COMPILER1 @@ -2447,6 +2448,13 @@ // notify ClassLoadingService of class unload ClassLoadingService::notify_class_unloaded(ik); + if (log_is_enabled(Info, class, unload)) { + ResourceMark rm; + log_info(class, unload)("unloading class %s " INTPTR_FORMAT, ik->external_name(), p2i(ik)); + } + + Events::log_class_unloading(Thread::current(), ik); + #if INCLUDE_JFR assert(ik != NULL, "invariant"); EventClassUnload event; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/symbol.cpp --- a/src/hotspot/share/oops/symbol.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/symbol.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -131,19 +131,6 @@ return as_C_string(str, len + 1); } -char* Symbol::as_C_string_flexible_buffer(Thread* t, - char* buf, int size) const { - char* str; - int len = utf8_length(); - int buf_len = len + 1; - if (size < buf_len) { - str = NEW_RESOURCE_ARRAY(char, buf_len); - } else { - str = buf; - } - return as_C_string(str, buf_len); -} - void Symbol::print_utf8_on(outputStream* st) const { st->print("%s", as_C_string()); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/oops/symbol.hpp --- a/src/hotspot/share/oops/symbol.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/oops/symbol.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -104,7 +104,6 @@ class Symbol : public MetaspaceObj { friend class VMStructs; friend class SymbolTable; - friend class MoveSymbols; private: @@ -136,7 +135,6 @@ Symbol(const u1* name, int length, int refcount); void* operator new(size_t size, int len, TRAPS) throw(); void* operator new(size_t size, int len, Arena* arena, TRAPS) throw(); - void* operator new(size_t size, int len, ClassLoaderData* loader_data, TRAPS) throw(); void operator delete(void* p); @@ -207,9 +205,6 @@ // Tests if the symbol starts with the given prefix. int index_of_at(int i, const char* str, int len) const; - int index_of_at(int i, const char* str) const { - return index_of_at(i, str, (int) strlen(str)); - } // Three-way compare for sorting; returns -1/0/1 if receiver is than arg // note that the ordering is not alfabetical @@ -219,17 +214,12 @@ // allocated in resource area, or in the char buffer provided by caller. char* as_C_string() const; char* as_C_string(char* buf, int size) const; - // Use buf if needed buffer length is <= size. - char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const; // Returns an escaped form of a Java string. char* as_quoted_ascii() const; // Returns a null terminated utf8 string in a resource array char* as_utf8() const { return as_C_string(); } - char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const { - return as_C_string_flexible_buffer(t, buf, size); - } jchar* as_unicode(int& length) const; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/c2_globals.hpp --- a/src/hotspot/share/opto/c2_globals.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/c2_globals.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -509,9 +509,6 @@ product(bool, EliminateAutoBox, true, \ "Control optimizations for autobox elimination") \ \ - diagnostic(bool, UseImplicitStableValues, true, \ - "Mark well-known stable fields as such (e.g. String.value)") \ - \ product(intx, AutoBoxCacheMax, 128, \ "Sets max value cached by the java.lang.Integer autobox cache") \ range(0, max_jint) \ diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/compile.cpp --- a/src/hotspot/share/opto/compile.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/compile.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -2112,7 +2112,7 @@ // PhaseIdealLoop is expensive so we only try it once we are // out of live nodes and we only try it again if the previous // helped got the number of nodes down significantly - PhaseIdealLoop ideal_loop(igvn, LoopOptsNone); + PhaseIdealLoop::optimize(igvn, LoopOptsNone); if (failing()) return; low_live_nodes = live_nodes(); _major_progress = true; @@ -2160,7 +2160,7 @@ while(major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); assert( cnt++ < 40, "infinite cycle in loop optimization" ); - PhaseIdealLoop ideal_loop(igvn, mode); + PhaseIdealLoop::optimize(igvn, mode); _loop_opts_cnt--; if (failing()) return false; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); @@ -2282,7 +2282,7 @@ if (has_loops()) { // Cleanup graph (remove dead nodes). TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop(igvn, LoopOptsNone); + PhaseIdealLoop::optimize(igvn, LoopOptsNone); if (major_progress()) print_method(PHASE_PHASEIDEAL_BEFORE_EA, 2); if (failing()) return; } @@ -2316,7 +2316,7 @@ if((_loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) { { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop(igvn, LoopOptsDefault); + PhaseIdealLoop::optimize(igvn, LoopOptsDefault); _loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP1, 2); if (failing()) return; @@ -2324,7 +2324,7 @@ // Loop opts pass if partial peeling occurred in previous pass if(PartialPeelLoop && major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf); + PhaseIdealLoop::optimize(igvn, LoopOptsSkipSplitIf); _loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP2, 2); if (failing()) return; @@ -2332,7 +2332,7 @@ // Loop opts pass for loop-unrolling before CCP if(major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf); + PhaseIdealLoop::optimize(igvn, LoopOptsSkipSplitIf); _loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP3, 2); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/graphKit.cpp --- a/src/hotspot/share/opto/graphKit.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/graphKit.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -1489,18 +1489,19 @@ LoadNode::ControlDependency control_dependency, bool require_atomic_access, bool unaligned, - bool mismatched) { + bool mismatched, + bool unsafe) { assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched); + ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched, unsafe); } else if (require_atomic_access && bt == T_DOUBLE) { - ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched); + ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched, unsafe); } else { - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, unaligned, mismatched); + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, unaligned, mismatched, unsafe); } ld = _gvn.transform(ld); if (((bt == T_OBJECT) && C->do_escape_analysis()) || C->eliminate_boxing()) { @@ -1515,7 +1516,8 @@ MemNode::MemOrd mo, bool require_atomic_access, bool unaligned, - bool mismatched) { + bool mismatched, + bool unsafe) { assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); @@ -1534,6 +1536,9 @@ if (mismatched) { st->as_Store()->set_mismatched_access(); } + if (unsafe) { + st->as_Store()->set_unsafe_access(); + } st = _gvn.transform(st); set_memory(st, adr_idx); // Back-to-back stores can only remove intermediate store with DU info @@ -3886,10 +3891,6 @@ Node* p = basic_plus_adr(str, str, value_offset); Node* load = access_load_at(str, p, value_field_type, value_type, T_OBJECT, IN_HEAP | (set_ctrl ? C2_CONTROL_DEPENDENT_LOAD : 0) | MO_UNORDERED); - // String.value field is known to be @Stable. - if (UseImplicitStableValues) { - load = cast_array_to_stable(load, value_type); - } return load; } @@ -3901,7 +3902,6 @@ const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* coder_field_type = string_type->add_offset(coder_offset); - int coder_field_idx = C->get_alias_index(coder_field_type); Node* p = basic_plus_adr(str, str, coder_offset); Node* load = access_load_at(str, p, coder_field_type, TypeInt::BYTE, T_BYTE, @@ -4039,9 +4039,3 @@ } return NULL; } - -Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { - // Reify the property as a CastPP node in Ideal graph to comply with monotonicity - // assumption of CCP analysis. - return _gvn.transform(new CastPPNode(ary, ary_type->cast_to_stable(true))); -} diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/graphKit.hpp --- a/src/hotspot/share/opto/graphKit.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/graphKit.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -518,27 +518,27 @@ Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false) { + bool mismatched = false, bool unsafe = false) { // This version computes alias_index from bottom_type return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(), mo, control_dependency, require_atomic_access, - unaligned, mismatched); + unaligned, mismatched, unsafe); } Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false) { + bool mismatched = false, bool unsafe = false) { // This version computes alias_index from an address type assert(adr_type != NULL, "use other make_load factory"); return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type), mo, control_dependency, require_atomic_access, - unaligned, mismatched); + unaligned, mismatched, unsafe); } // This is the base version which is given an alias index. Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false); + bool mismatched = false, bool unsafe = false); // Create & transform a StoreNode and store the effect into the // parser's memory state. @@ -553,7 +553,8 @@ MemNode::MemOrd mo, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false) { + bool mismatched = false, + bool unsafe = false) { // This version computes alias_index from an address type assert(adr_type != NULL, "use other store_to_memory factory"); return store_to_memory(ctl, adr, val, bt, @@ -568,7 +569,8 @@ MemNode::MemOrd, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false); + bool mismatched = false, + bool unsafe = false); // Perform decorated accesses @@ -884,9 +886,6 @@ void add_predicate_impl(Deoptimization::DeoptReason reason, int nargs); Node* make_constant_from_field(ciField* field, Node* obj); - - // Produce new array node of stable type - Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type); }; // Helper class to support building of control flow branches. Upon diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/loopnode.cpp --- a/src/hotspot/share/opto/loopnode.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/loopnode.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -2712,8 +2712,6 @@ bool do_split_ifs = (mode == LoopOptsDefault || mode == LoopOptsLastRound); bool skip_loop_opts = (mode == LoopOptsNone); - ResourceMark rm; - int old_progress = C->major_progress(); uint orig_worklist_size = _igvn._worklist.size(); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/loopnode.hpp --- a/src/hotspot/share/opto/loopnode.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/loopnode.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -880,6 +880,42 @@ uint *_dom_depth; // Used for fast LCA test GrowableArray* _dom_stk; // For recomputation of dom depth + // Perform verification that the graph is valid. + PhaseIdealLoop( PhaseIterGVN &igvn) : + PhaseTransform(Ideal_Loop), + _igvn(igvn), + _verify_me(NULL), + _verify_only(true), + _dom_lca_tags(arena()) { // Thread::resource_area + build_and_optimize(LoopOptsVerify); + } + + // build the loop tree and perform any requested optimizations + void build_and_optimize(LoopOptsMode mode); + + // Dominators for the sea of nodes + void Dominators(); + + // Compute the Ideal Node to Loop mapping + PhaseIdealLoop(PhaseIterGVN &igvn, LoopOptsMode mode) : + PhaseTransform(Ideal_Loop), + _igvn(igvn), + _verify_me(NULL), + _verify_only(false), + _dom_lca_tags(arena()) { // Thread::resource_area + build_and_optimize(mode); + } + + // Verify that verify_me made the same decisions as a fresh run. + PhaseIdealLoop(PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) : + PhaseTransform(Ideal_Loop), + _igvn(igvn), + _verify_me(verify_me), + _verify_only(false), + _dom_lca_tags(arena()) { // Thread::resource_area + build_and_optimize(LoopOptsVerify); + } + public: Node* idom_no_update(Node* d) const { return idom_no_update(d->_idx); @@ -923,54 +959,27 @@ // Replace parallel induction variable (parallel to trip counter) void replace_parallel_iv(IdealLoopTree *loop); - // Perform verification that the graph is valid. - PhaseIdealLoop( PhaseIterGVN &igvn) : - PhaseTransform(Ideal_Loop), - _igvn(igvn), - _verify_me(NULL), - _verify_only(true), - _dom_lca_tags(arena()) { // Thread::resource_area - build_and_optimize(LoopOptsVerify); - } - - // build the loop tree and perform any requested optimizations - void build_and_optimize(LoopOptsMode mode); - - // Dominators for the sea of nodes - void Dominators(); Node *dom_lca( Node *n1, Node *n2 ) const { return find_non_split_ctrl(dom_lca_internal(n1, n2)); } Node *dom_lca_internal( Node *n1, Node *n2 ) const; - // Compute the Ideal Node to Loop mapping - PhaseIdealLoop(PhaseIterGVN &igvn, LoopOptsMode mode) : - PhaseTransform(Ideal_Loop), - _igvn(igvn), - _verify_me(NULL), - _verify_only(false), - _dom_lca_tags(arena()) { // Thread::resource_area - build_and_optimize(mode); - } - - // Verify that verify_me made the same decisions as a fresh run. - PhaseIdealLoop(PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) : - PhaseTransform(Ideal_Loop), - _igvn(igvn), - _verify_me(verify_me), - _verify_only(false), - _dom_lca_tags(arena()) { // Thread::resource_area - build_and_optimize(LoopOptsVerify); - } - // Build and verify the loop tree without modifying the graph. This // is useful to verify that all inputs properly dominate their uses. static void verify(PhaseIterGVN& igvn) { #ifdef ASSERT + ResourceMark rm; PhaseIdealLoop v(igvn); #endif } + // Recommended way to use PhaseIdealLoop. + // Run PhaseIdealLoop in some mode and allocates a local scope for memory allocations. + static void optimize(PhaseIterGVN &igvn, LoopOptsMode mode) { + ResourceMark rm; + PhaseIdealLoop v(igvn, mode); + } + // True if the method has at least 1 irreducible loop bool _has_irreducible_loops; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/memnode.cpp --- a/src/hotspot/share/opto/memnode.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/memnode.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -99,6 +99,9 @@ if (_mismatched_access) { st->print(" mismatched"); } + if (_unsafe_access) { + st->print(" unsafe"); + } } void MemNode::dump_adr_type(const Node* mem, const TypePtr* adr_type, outputStream *st) { @@ -789,7 +792,7 @@ //----------------------------LoadNode::make----------------------------------- // Polymorphic factory method: Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, - ControlDependency control_dependency, bool unaligned, bool mismatched) { + ControlDependency control_dependency, bool unaligned, bool mismatched, bool unsafe) { Compile* C = gvn.C; // sanity check the alias category against the created node type @@ -837,6 +840,9 @@ if (mismatched) { load->set_mismatched_access(); } + if (unsafe) { + load->set_unsafe_access(); + } if (load->Opcode() == Op_LoadN) { Node* ld = gvn.transform(load); return new DecodeNNode(ld, ld->bottom_type()->make_ptr()); @@ -846,7 +852,7 @@ } LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, - ControlDependency control_dependency, bool unaligned, bool mismatched) { + ControlDependency control_dependency, bool unaligned, bool mismatched, bool unsafe) { bool require_atomic = true; LoadLNode* load = new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic); if (unaligned) { @@ -855,11 +861,14 @@ if (mismatched) { load->set_mismatched_access(); } + if (unsafe) { + load->set_unsafe_access(); + } return load; } LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, - ControlDependency control_dependency, bool unaligned, bool mismatched) { + ControlDependency control_dependency, bool unaligned, bool mismatched, bool unsafe) { bool require_atomic = true; LoadDNode* load = new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic); if (unaligned) { @@ -868,6 +877,9 @@ if (mismatched) { load->set_mismatched_access(); } + if (unsafe) { + load->set_unsafe_access(); + } return load; } @@ -978,7 +990,8 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { Node* ld_adr = in(MemNode::Address); intptr_t ld_off = 0; - AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off); + Node* ld_base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ld_off); + Node* ld_alloc = AllocateNode::Ideal_allocation(ld_base, phase); const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); Compile::AliasType* atp = (tp != NULL) ? phase->C->alias_type(tp) : NULL; // This is more general than load from boxing objects. @@ -1031,16 +1044,21 @@ if (st->is_Store()) { Node* st_adr = st->in(MemNode::Address); if (!phase->eqv(st_adr, ld_adr)) { - // Try harder before giving up... Match raw and non-raw pointers. + // Try harder before giving up. Unify base pointers with casts (e.g., raw/non-raw pointers). intptr_t st_off = 0; - AllocateNode* alloc = AllocateNode::Ideal_allocation(st_adr, phase, st_off); - if (alloc == NULL) return NULL; - if (alloc != ld_alloc) return NULL; - if (ld_off != st_off) return NULL; + Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_off); + if (ld_base == NULL) return NULL; + if (st_base == NULL) return NULL; + if (ld_base->uncast() != st_base->uncast()) return NULL; + if (ld_off != st_off) return NULL; + if (ld_off == Type::OffsetBot) return NULL; + // Same base, same offset. + // Possible improvement for arrays: check index value instead of absolute offset. + // At this point we have proven something like this setup: - // A = Allocate(...) - // L = LoadQ(, AddP(CastPP(, A.Parm),, #Off)) - // S = StoreQ(, AddP(, A.Parm , #Off), V) + // B = << base >> + // L = LoadQ(AddP(Check/CastPP(B), #Off)) + // S = StoreQ(AddP( B , #Off), V) // (Actually, we haven't yet proven the Q's are the same.) // In other words, we are loading from a casted version of // the same pointer-and-offset that we stored to. diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/memnode.hpp --- a/src/hotspot/share/opto/memnode.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/memnode.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -42,6 +42,7 @@ private: bool _unaligned_access; // Unaligned access from unsafe bool _mismatched_access; // Mismatched access from unsafe: byte read in integer array for instance + bool _unsafe_access; // Access of unsafe origin. protected: #ifdef ASSERT const TypePtr* _adr_type; // What kind of memory is being addressed? @@ -62,17 +63,17 @@ } MemOrd; protected: MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at ) - : Node(c0,c1,c2 ), _unaligned_access(false), _mismatched_access(false) { + : Node(c0,c1,c2 ), _unaligned_access(false), _mismatched_access(false), _unsafe_access(false) { init_class_id(Class_Mem); debug_only(_adr_type=at; adr_type();) } MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3 ) - : Node(c0,c1,c2,c3), _unaligned_access(false), _mismatched_access(false) { + : Node(c0,c1,c2,c3), _unaligned_access(false), _mismatched_access(false), _unsafe_access(false) { init_class_id(Class_Mem); debug_only(_adr_type=at; adr_type();) } MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3, Node *c4) - : Node(c0,c1,c2,c3,c4), _unaligned_access(false), _mismatched_access(false) { + : Node(c0,c1,c2,c3,c4), _unaligned_access(false), _mismatched_access(false), _unsafe_access(false) { init_class_id(Class_Mem); debug_only(_adr_type=at; adr_type();) } @@ -137,6 +138,8 @@ bool is_unaligned_access() const { return _unaligned_access; } void set_mismatched_access() { _mismatched_access = true; } bool is_mismatched_access() const { return _mismatched_access; } + void set_unsafe_access() { _unsafe_access = true; } + bool is_unsafe_access() const { return _unsafe_access; } #ifndef PRODUCT static void dump_adr_type(const Node* mem, const TypePtr* adr_type, outputStream *st); @@ -207,7 +210,7 @@ static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, - bool unaligned = false, bool mismatched = false); + bool unaligned = false, bool mismatched = false, bool unsafe = false); virtual uint hash() const; // Check the type @@ -388,7 +391,7 @@ bool require_atomic_access() const { return _require_atomic_access; } static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, - bool unaligned = false, bool mismatched = false); + bool unaligned = false, bool mismatched = false, bool unsafe = false); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); @@ -440,7 +443,7 @@ bool require_atomic_access() const { return _require_atomic_access; } static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, - bool unaligned = false, bool mismatched = false); + bool unaligned = false, bool mismatched = false, bool unsafe = false); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/opto/reg_split.cpp --- a/src/hotspot/share/opto/reg_split.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/opto/reg_split.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1192,9 +1192,8 @@ (deflrg._direct_conflict || deflrg._must_spill)) || // Check for LRG being up in a register and we are inside a high // pressure area. Spill it down immediately. - (defup && is_high_pressure(b,&deflrg,insidx))) ) { + (defup && is_high_pressure(b,&deflrg,insidx) && !n->is_SpillCopy())) ) { assert( !n->rematerialize(), "" ); - assert( !n->is_SpillCopy(), "" ); // Do a split at the def site. maxlrg = split_DEF( n, b, insidx, maxlrg, Reachblock, debug_defs, splits, slidx ); // If it wasn't split bail diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/prims/jniCheck.cpp --- a/src/hotspot/share/prims/jniCheck.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/prims/jniCheck.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -418,21 +418,20 @@ size_t sz; void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz); switch (mode) { + // As we never make copies, mode 0 and JNI_COMMIT are the same. case 0: - memcpy(orig_result, carray, sz); - GuardedMemory::free_copy(carray); - break; case JNI_COMMIT: memcpy(orig_result, carray, sz); break; case JNI_ABORT: - GuardedMemory::free_copy(carray); break; default: tty->print_cr("%s: Unrecognized mode %i releasing array " PTR_FORMAT " elements " PTR_FORMAT, fn_name, mode, p2i(obj), p2i(carray)); NativeReportJNIFatalError(thr, "Unrecognized array release mode"); } + // We always need to release the copy we made with GuardedMemory + GuardedMemory::free_copy(carray); return orig_result; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/prims/jvmtiRedefineClasses.cpp --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -512,11 +512,11 @@ case JVM_CONSTANT_InvokeDynamic: { // Index of the bootstrap specifier in the operands array - int old_bs_i = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); + int old_bs_i = scratch_cp->bootstrap_methods_attribute_index(scratch_i); int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p, THREAD); // The bootstrap method NameAndType_info index - int old_ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); + int old_ref_i = scratch_cp->bootstrap_name_and_type_ref_index_at(scratch_i); int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, merge_cp_length_p, THREAD); if (new_bs_i != old_bs_i) { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/prims/methodComparator.cpp --- a/src/hotspot/share/prims/methodComparator.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/prims/methodComparator.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -123,17 +123,17 @@ int cpi_old = _old_cp->cache()->entry_at(cpci_old)->constant_pool_index(); int cpi_new = _new_cp->cache()->entry_at(cpci_new)->constant_pool_index(); - int bsm_old = _old_cp->invoke_dynamic_bootstrap_method_ref_index_at(cpi_old); - int bsm_new = _new_cp->invoke_dynamic_bootstrap_method_ref_index_at(cpi_new); + int bsm_old = _old_cp->bootstrap_method_ref_index_at(cpi_old); + int bsm_new = _new_cp->bootstrap_method_ref_index_at(cpi_new); if (!pool_constants_same(bsm_old, bsm_new)) return false; - int cnt_old = _old_cp->invoke_dynamic_argument_count_at(cpi_old); - int cnt_new = _new_cp->invoke_dynamic_argument_count_at(cpi_new); + int cnt_old = _old_cp->bootstrap_argument_count_at(cpi_old); + int cnt_new = _new_cp->bootstrap_argument_count_at(cpi_new); if (cnt_old != cnt_new) return false; for (int arg_i = 0; arg_i < cnt_old; arg_i++) { - int idx_old = _old_cp->invoke_dynamic_argument_index_at(cpi_old, arg_i); - int idx_new = _new_cp->invoke_dynamic_argument_index_at(cpi_new, arg_i); + int idx_old = _old_cp->bootstrap_argument_index_at(cpi_old, arg_i); + int idx_new = _new_cp->bootstrap_argument_index_at(cpi_new, arg_i); if (!pool_constants_same(idx_old, idx_new)) return false; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/prims/methodHandles.cpp --- a/src/hotspot/share/prims/methodHandles.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/prims/methodHandles.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1427,7 +1427,7 @@ if (bss_index_in_pool <= 0 || bss_index_in_pool >= caller->constants()->length() || index_info->int_at(0) - != caller->constants()->invoke_dynamic_argument_count_at(bss_index_in_pool)) { + != caller->constants()->bootstrap_argument_count_at(bss_index_in_pool)) { THROW_MSG(vmSymbols::java_lang_InternalError(), "bad index info (1)"); } objArrayHandle buf(THREAD, (objArrayOop) JNIHandles::resolve(buf_jh)); @@ -1439,7 +1439,7 @@ switch (pseudo_index) { case -4: // bootstrap method { - int bsm_index = caller->constants()->invoke_dynamic_bootstrap_method_ref_index_at(bss_index_in_pool); + int bsm_index = caller->constants()->bootstrap_method_ref_index_at(bss_index_in_pool); pseudo_arg = caller->constants()->resolve_possibly_cached_constant_at(bsm_index, CHECK); break; } @@ -1464,7 +1464,7 @@ } case -1: // argument count { - int argc = caller->constants()->invoke_dynamic_argument_count_at(bss_index_in_pool); + int argc = caller->constants()->bootstrap_argument_count_at(bss_index_in_pool); jvalue argc_value; argc_value.i = (jint)argc; pseudo_arg = java_lang_boxing_object::create(T_INT, &argc_value, CHECK); break; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/prims/whitebox.cpp --- a/src/hotspot/share/prims/whitebox.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/prims/whitebox.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -694,6 +694,13 @@ return (jlong)(uintptr_t)os::malloc(size, mtTest, stack); WB_END +// Alloc memory with pseudo call stack and specific memory type. +WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type)) + address pc = (address)(size_t)pseudo_stack; + NativeCallStack stack(&pc, 1); + return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack); +WB_END + // Free the memory allocated by NMTAllocTest WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem)) os::free((void*)(uintptr_t)mem); @@ -1537,9 +1544,6 @@ blobs.append(stub); } } - if (blobs.length() == 0) { - return NULL; - } ThreadToNativeFromVM ttn(thread); jobjectArray result = NULL; jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string()); @@ -2161,6 +2165,7 @@ #if INCLUDE_NMT {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc }, {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack}, + {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType}, {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree }, {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory }, {CC"NMTAttemptReserveMemoryAt", CC"(JJ)J", (void*)&WB_NMTAttemptReserveMemoryAt }, diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/arguments.cpp --- a/src/hotspot/share/runtime/arguments.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/arguments.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -528,6 +528,7 @@ { "MinRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "UseMembar", JDK_Version::jdk(10), JDK_Version::jdk(12), JDK_Version::undefined() }, + { "CompilationPolicyChoice", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -541,6 +542,17 @@ { "SharedReadOnlySize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, { "SharedMiscDataSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, { "SharedMiscCodeSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, + { "ProfilerPrintByteCodeStatistics", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfilerRecordPC", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfileVM", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfileIntervals", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfileIntervalsTicks", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfilerCheckIntervals", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfilerNumberOfInterpretedMethods", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfilerNumberOfCompiledMethods", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfilerNumberOfStubMethods", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "ProfilerNumberOfRuntimeStubNodes", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, + { "UseImplicitStableValues", JDK_Version::undefined(), JDK_Version::jdk(13), JDK_Version::jdk(14) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, @@ -3784,8 +3796,8 @@ #endif #if defined(AIX) - UNSUPPORTED_OPTION(AllocateHeapAt); - UNSUPPORTED_OPTION(AllocateOldGenAt); + UNSUPPORTED_OPTION_NULL(AllocateHeapAt); + UNSUPPORTED_OPTION_NULL(AllocateOldGenAt); #endif #ifndef PRODUCT diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/arguments.hpp --- a/src/hotspot/share/runtime/arguments.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/arguments.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -663,4 +663,16 @@ } \ } while(0) +// similar to UNSUPPORTED_OPTION but sets flag to NULL +#define UNSUPPORTED_OPTION_NULL(opt) \ +do { \ + if (opt) { \ + if (FLAG_IS_CMDLINE(opt)) { \ + warning("-XX flag " #opt " not supported in this VM"); \ + } \ + FLAG_SET_DEFAULT(opt, NULL); \ + } \ +} while(0) + + #endif // SHARE_RUNTIME_ARGUMENTS_HPP diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/globals.hpp --- a/src/hotspot/share/runtime/globals.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/globals.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -749,22 +749,6 @@ product(bool, OmitStackTraceInFastThrow, true, \ "Omit backtraces for some 'hot' exceptions in optimized code") \ \ - product(bool, ProfilerPrintByteCodeStatistics, false, \ - "Print bytecode statistics when dumping profiler output") \ - \ - product(bool, ProfilerRecordPC, false, \ - "Collect ticks for each 16 byte interval of compiled code") \ - \ - product(bool, ProfileVM, false, \ - "Profile ticks that fall within VM (either in the VM Thread " \ - "or VM code called through stubs)") \ - \ - product(bool, ProfileIntervals, false, \ - "Print profiles for each interval (see ProfileIntervalsTicks)") \ - \ - notproduct(bool, ProfilerCheckIntervals, false, \ - "Collect and print information on spacing of profiler ticks") \ - \ product(bool, PrintWarnings, true, \ "Print JVM warnings to output stream") \ \ @@ -1650,23 +1634,6 @@ develop(intx, MethodHistogramCutoff, 100, \ "The cutoff value for method invocation histogram (+CountCalls)") \ \ - diagnostic(intx, ProfilerNumberOfInterpretedMethods, 25, \ - "Number of interpreted methods to show in profile") \ - \ - diagnostic(intx, ProfilerNumberOfCompiledMethods, 25, \ - "Number of compiled methods to show in profile") \ - \ - diagnostic(intx, ProfilerNumberOfStubMethods, 25, \ - "Number of stub methods to show in profile") \ - \ - diagnostic(intx, ProfilerNumberOfRuntimeStubNodes, 25, \ - "Number of runtime stub nodes to show in profile") \ - \ - product(intx, ProfileIntervalsTicks, 100, \ - "Number of ticks between printing of interval profile " \ - "(+ProfileIntervals)") \ - range(0, max_intx) \ - \ develop(intx, DontYieldALotInterval, 10, \ "Interval between which yields will be dropped (milliseconds)") \ \ diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/handshake.cpp --- a/src/hotspot/share/runtime/handshake.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/handshake.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -303,13 +303,9 @@ } bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) { - // SafepointSynchronize::safepoint_safe() does not consider an externally - // suspended thread to be safe. However, this function must be called with - // the Threads_lock held so an externally suspended thread cannot be - // resumed thus it is safe. - assert(Threads_lock->owned_by_self(), "Not holding Threads_lock."); - return SafepointSynchronize::safepoint_safe(target, target->thread_state()) || - target->is_ext_suspended() || target->is_terminated(); + // handshake_safe may only be called with polls armed. + // VM thread controls this by first claiming the handshake via claim_handshake_for_vmthread. + return SafepointSynchronize::handshake_safe(target); } static bool possibly_vmthread_can_process_handshake(JavaThread* target) { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/interfaceSupport.inline.hpp --- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -314,10 +314,10 @@ // Once we are blocked vm expects stack to be walkable thread->frame_anchor()->make_walkable(thread); - thread->set_thread_state((JavaThreadState)(_thread_in_vm + 1)); - InterfaceSupport::serialize_thread_state_with_handler(thread); - - SafepointMechanism::callback_if_safepoint(thread); + // All unsafe states are treated the same by the VMThread + // so we can skip the _thread_in_vm_trans state here. Since + // we don't read poll, it's enough to order the stores. + OrderAccess::storestore(); thread->set_thread_state(_thread_blocked); @@ -325,23 +325,13 @@ } ~ThreadBlockInVMWithDeadlockCheck() { // Change to transition state - _thread->set_thread_state((JavaThreadState)(_thread_blocked + 1)); + _thread->set_thread_state((JavaThreadState)(_thread_blocked_trans)); InterfaceSupport::serialize_thread_state_with_handler(_thread); if (SafepointMechanism::should_block(_thread)) { release_monitor(); - SafepointMechanism::callback_if_safepoint(_thread); - // The VMThread might have read that we were in a _thread_blocked state - // and proceeded to process a handshake for us. If that's the case then - // we need to block. - // By doing this we are also making the current thread process its own - // handshake if there is one pending and the VMThread didn't try to process - // it yet. This is more of a side-effect and not really necessary; the - // handshake could be processed later on. - if (_thread->has_handshake()) { - _thread->handshake_process_by_self(); - } + SafepointMechanism::block_if_requested(_thread); } _thread->set_thread_state(_thread_in_vm); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/java.cpp --- a/src/hotspot/share/runtime/java.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/java.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -291,9 +291,6 @@ if (TimeOopMap) { GenerateOopMap::print_time(); } - if (ProfilerCheckIntervals) { - PeriodicTask::print_intervals(); - } if (PrintSymbolTableSizeHistogram) { SymbolTable::print_histogram(); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/mutex.cpp --- a/src/hotspot/share/runtime/mutex.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/mutex.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -401,15 +401,10 @@ // of m2 be less than the rank of m1. // The rank Mutex::native is an exception in that it is not subject // to the verification rules. - // Here are some further notes relating to mutex acquisition anomalies: - // . it is also ok to acquire Safepoint_lock at the very end while we - // already hold Terminator_lock - may happen because of periodic safepoints if (this->rank() != Mutex::native && this->rank() != Mutex::suspend_resume && locks != NULL && locks->rank() <= this->rank() && - !SafepointSynchronize::is_at_safepoint() && - !(this == Safepoint_lock && contains(locks, Terminator_lock) && - SafepointSynchronize::is_synchronizing())) { + !SafepointSynchronize::is_at_safepoint()) { new_owner->print_owned_locks(); fatal("acquiring lock %s/%d out of order with lock %s/%d -- " "possible deadlock", this->name(), this->rank(), diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/mutex.hpp --- a/src/hotspot/share/runtime/mutex.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/mutex.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -56,10 +56,7 @@ // (except for "event" and "access") for the deadlock detection to work correctly. // The rank native is only for use in Mutex's created by JVM_RawMonitorCreate, // which being external to the VM are not subject to deadlock detection. - // The rank safepoint is used only for synchronization in reaching a - // safepoint and leaving a safepoint. It is only used for the Safepoint_lock - // currently. While at a safepoint no mutexes of rank safepoint are held - // by any thread. + // While at a safepoint no mutexes of rank safepoint are held by any thread. // The rank named "leaf" is probably historical (and should // be changed) -- mutexes of this rank aren't really leaf mutexes // at all. diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/mutexLocker.cpp --- a/src/hotspot/share/runtime/mutexLocker.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/mutexLocker.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -72,7 +72,6 @@ Mutex* RetData_lock = NULL; Monitor* VMOperationQueue_lock = NULL; Monitor* VMOperationRequest_lock = NULL; -Monitor* Safepoint_lock = NULL; Monitor* SerializePage_lock = NULL; Monitor* Threads_lock = NULL; Mutex* NonJavaThreadsList_lock = NULL; @@ -275,8 +274,6 @@ // CMS_bitMap_lock leaf 1 // CMS_freeList_lock leaf 2 - def(Safepoint_lock , PaddedMonitor, safepoint, true, Monitor::_safepoint_check_sometimes); // locks SnippetCache_lock/Threads_lock - def(Threads_lock , PaddedMonitor, barrier, true, Monitor::_safepoint_check_sometimes); def(NonJavaThreadsList_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/mutexLocker.hpp --- a/src/hotspot/share/runtime/mutexLocker.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/mutexLocker.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -68,7 +68,6 @@ extern Monitor* CGCPhaseManager_lock; // a lock to protect a concurrent GC's phase management extern Monitor* VMOperationQueue_lock; // a lock on queue of vm_operations waiting to execute extern Monitor* VMOperationRequest_lock; // a lock on Threads waiting for a vm_operation to terminate -extern Monitor* Safepoint_lock; // a lock used by the safepoint abstraction extern Monitor* Threads_lock; // a lock on the Threads table of active Java threads // (also used by Safepoints too to block threads creation/destruction) extern Mutex* NonJavaThreadsList_lock; // a lock on the NonJavaThreads list diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/safepoint.cpp --- a/src/hotspot/share/runtime/safepoint.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/safepoint.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -70,70 +70,63 @@ #include "c1/c1_globals.hpp" #endif -template -static void set_current_safepoint_id(E* event, int adjustment = 0) { - assert(event != NULL, "invariant"); - event->set_safepointId(SafepointSynchronize::safepoint_counter() + adjustment); -} - -static void post_safepoint_begin_event(EventSafepointBegin* event, +static void post_safepoint_begin_event(EventSafepointBegin& event, + uint64_t safepoint_id, int thread_count, int critical_thread_count) { - assert(event != NULL, "invariant"); - assert(event->should_commit(), "invariant"); - set_current_safepoint_id(event); - event->set_totalThreadCount(thread_count); - event->set_jniCriticalThreadCount(critical_thread_count); - event->commit(); + if (event.should_commit()) { + event.set_safepointId(safepoint_id); + event.set_totalThreadCount(thread_count); + event.set_jniCriticalThreadCount(critical_thread_count); + event.commit(); + } } -static void post_safepoint_cleanup_event(EventSafepointCleanup* event) { - assert(event != NULL, "invariant"); - assert(event->should_commit(), "invariant"); - set_current_safepoint_id(event); - event->commit(); -} - -static void post_safepoint_synchronize_event(EventSafepointStateSynchronization* event, - int initial_number_of_threads, - int threads_waiting_to_block, - unsigned int iterations) { - assert(event != NULL, "invariant"); - if (event->should_commit()) { - // Group this event together with the ones committed after the counter is increased - set_current_safepoint_id(event, 1); - event->set_initialThreadCount(initial_number_of_threads); - event->set_runningThreadCount(threads_waiting_to_block); - event->set_iterations(iterations); - event->commit(); +static void post_safepoint_cleanup_event(EventSafepointCleanup& event, uint64_t safepoint_id) { + if (event.should_commit()) { + event.set_safepointId(safepoint_id); + event.commit(); } } -static void post_safepoint_wait_blocked_event(EventSafepointWaitBlocked* event, - int initial_threads_waiting_to_block) { - assert(event != NULL, "invariant"); - assert(event->should_commit(), "invariant"); - set_current_safepoint_id(event); - event->set_runningThreadCount(initial_threads_waiting_to_block); - event->commit(); -} - -static void post_safepoint_cleanup_task_event(EventSafepointCleanupTask* event, - const char* name) { - assert(event != NULL, "invariant"); - if (event->should_commit()) { - set_current_safepoint_id(event); - event->set_name(name); - event->commit(); +static void post_safepoint_synchronize_event(EventSafepointStateSynchronization& event, + uint64_t safepoint_id, + int initial_number_of_threads, + int threads_waiting_to_block, + uint64_t iterations) { + if (event.should_commit()) { + event.set_safepointId(safepoint_id); + event.set_initialThreadCount(initial_number_of_threads); + event.set_runningThreadCount(threads_waiting_to_block); + event.set_iterations(iterations); + event.commit(); } } -static void post_safepoint_end_event(EventSafepointEnd* event) { - assert(event != NULL, "invariant"); - if (event->should_commit()) { - // Group this event together with the ones committed before the counter increased - set_current_safepoint_id(event, -1); - event->commit(); +static void post_safepoint_wait_blocked_event(EventSafepointWaitBlocked& event, + uint64_t safepoint_id, + int initial_threads_waiting_to_block) { + if (event.should_commit()) { + event.set_safepointId(safepoint_id); + event.set_runningThreadCount(initial_threads_waiting_to_block); + event.commit(); + } +} + +static void post_safepoint_cleanup_task_event(EventSafepointCleanupTask& event, + uint64_t safepoint_id, + const char* name) { + if (event.should_commit()) { + event.set_safepointId(safepoint_id); + event.set_name(name); + event.commit(); + } +} + +static void post_safepoint_end_event(EventSafepointEnd& event, uint64_t safepoint_id) { + if (event.should_commit()) { + event.set_safepointId(safepoint_id); + event.commit(); } } @@ -141,64 +134,170 @@ // Implementation of Safepoint begin/end SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized; -volatile int SafepointSynchronize::_waiting_to_block = 0; +int SafepointSynchronize::_waiting_to_block = 0; volatile uint64_t SafepointSynchronize::_safepoint_counter = 0; +const uint64_t SafepointSynchronize::InactiveSafepointCounter = 0; int SafepointSynchronize::_current_jni_active_count = 0; -long SafepointSynchronize::_end_of_last_safepoint = 0; -int SafepointSynchronize::_defer_thr_suspend_loop_count = 4000; -static const int safepoint_spin_before_yield = 2000; -static volatile int PageArmed = 0 ; // safepoint polling page is RO|RW vs PROT_NONE -static volatile int TryingToBlock = 0 ; // proximate value -- for advisory use only +long SafepointSynchronize::_end_of_last_safepoint = 0; + +WaitBarrier* SafepointSynchronize::_wait_barrier; + +// We need a place to save the desc since it is released before we need it. +static char stopped_description[64] = ""; +static bool _vm_is_waiting = false; + +static volatile bool PageArmed = false; // safepoint polling page is RO|RW vs PROT_NONE static bool timeout_error_printed = false; - -// Statistic related statics +// Statistic related julong SafepointSynchronize::_coalesced_vmop_count = 0; static jlong _safepoint_begin_time = 0; static float _ts_of_current_safepoint = 0.0f; static volatile int _nof_threads_hit_polling_page = 0; -// Roll all threads forward to a safepoint and suspend them all -void SafepointSynchronize::begin() { - EventSafepointBegin begin_event; - Thread* myThread = Thread::current(); - assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint"); +void SafepointSynchronize::init(Thread* vmthread) { + // WaitBarrier should never be destroyed since we will have + // threads waiting on it while exiting. + _wait_barrier = new WaitBarrier(vmthread); +} + +void SafepointSynchronize::increment_jni_active_count() { + assert(Thread::current()->is_VM_thread(), "Only VM thread may increment"); + ++_current_jni_active_count; +} + +void SafepointSynchronize::decrement_waiting_to_block() { + assert(_waiting_to_block > 0, "sanity check"); + assert(Thread::current()->is_VM_thread(), "Only VM thread may decrement"); + --_waiting_to_block; +} + +static bool thread_not_running(ThreadSafepointState *cur_state) { + if (!cur_state->is_running()) { + return true; + } + cur_state->examine_state_of_thread(SafepointSynchronize::safepoint_counter()); + if (!cur_state->is_running()) { + return true; + } + LogTarget(Trace, safepoint) lt; + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + cur_state->print_on(&ls); + } + return false; +} +#ifdef ASSERT +static void assert_list_is_valid(const ThreadSafepointState* tss_head, int still_running) { + int a = 0; + const ThreadSafepointState *tmp_tss = tss_head; + while (tmp_tss != NULL) { + ++a; + assert(tmp_tss->is_running(), "Illegal initial state"); + tmp_tss = tmp_tss->get_next(); + } + assert(a == still_running, "Must be the same"); +} +#endif // ASSERT + +static void back_off(int iteration) { + // iteration will be 1 the first time we enter this spin back-off. + // naked_short_nanosleep takes tenths of micros which means that + // number of nanoseconds is irrelevant if it's below that. We do + // 20 1 ns sleeps with a total cost of ~1 ms, then we do 1 ms sleeps. + jlong sleep_ns = 1; + if (iteration > 20) { + sleep_ns = NANOUNITS / MILLIUNITS; // 1 ms + } + os::naked_short_nanosleep(sleep_ns); +} + +int SafepointSynchronize::synchronize_threads(jlong safepoint_limit_time, int nof_threads, int* initial_running) +{ + JavaThreadIteratorWithHandle jtiwh; + +#ifdef ASSERT + for (; JavaThread *cur = jtiwh.next(); ) { + assert(cur->safepoint_state()->is_running(), "Illegal initial state"); + } + jtiwh.rewind(); +#endif // ASSERT + + // Iterate through all threads until it has been determined how to stop them all at a safepoint. + int still_running = nof_threads; + ThreadSafepointState *tss_head = NULL; + ThreadSafepointState **p_prev = &tss_head; + for (; JavaThread *cur = jtiwh.next(); ) { + ThreadSafepointState *cur_tss = cur->safepoint_state(); + assert(cur_tss->get_next() == NULL, "Must be NULL"); + if (thread_not_running(cur_tss)) { + --still_running; + } else { + *p_prev = cur_tss; + p_prev = cur_tss->next_ptr(); + } + } + *p_prev = NULL; + + DEBUG_ONLY(assert_list_is_valid(tss_head, still_running);) + + *initial_running = still_running; if (log_is_enabled(Debug, safepoint, stats)) { - _safepoint_begin_time = os::javaTimeNanos(); - _ts_of_current_safepoint = tty->time_stamp().seconds(); - _nof_threads_hit_polling_page = 0; + begin_statistics(nof_threads, still_running); } - Universe::heap()->safepoint_synchronize_begin(); - - // By getting the Threads_lock, we assure that no threads are about to start or - // exit. It is released again in SafepointSynchronize::end(). - Threads_lock->lock(); + int iterations = 1; // The first iteration is above. - assert( _state == _not_synchronized, "trying to safepoint synchronize with wrong state"); - - int nof_threads = Threads::number_of_threads(); - - log_debug(safepoint)("Safepoint synchronization initiated. (%d threads)", nof_threads); - - RuntimeService::record_safepoint_begin(); + while (still_running > 0) { + // Check if this has taken too long: + if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) { + print_safepoint_timeout(_spinning_timeout); + } + if (int(iterations) == -1) { // overflow - something is wrong. + // We can only overflow here when we are using global + // polling pages. We keep this guarantee in its original + // form so that searches of the bug database for this + // failure mode find the right bugs. + guarantee (!PageArmed, "invariant"); + } - MutexLocker mu(Safepoint_lock); - - // Reset the count of active JNI critical threads - _current_jni_active_count = 0; + p_prev = &tss_head; + ThreadSafepointState *cur_tss = tss_head; + while (cur_tss != NULL) { + assert(cur_tss->is_running(), "Illegal initial state"); + if (thread_not_running(cur_tss)) { + --still_running; + *p_prev = NULL; + ThreadSafepointState *tmp = cur_tss; + cur_tss = cur_tss->get_next(); + tmp->set_next(NULL); + } else { + *p_prev = cur_tss; + p_prev = cur_tss->next_ptr(); + cur_tss = cur_tss->get_next(); + } + } - // Set number of threads to wait for, before we initiate the callbacks - _waiting_to_block = nof_threads; - TryingToBlock = 0 ; - int still_running = nof_threads; + DEBUG_ONLY(assert_list_is_valid(tss_head, still_running);) + + if (still_running > 0) { + back_off(iterations); + } + + iterations++; + } - // Save the starting time, so that it can be compared to see if this has taken - // too long to complete. - jlong safepoint_limit_time = 0; - timeout_error_printed = false; + assert(tss_head == NULL, "Must be empty"); + if (log_is_enabled(Debug, safepoint, stats)) { + update_statistics_on_spin_end(); + } + return iterations; +} + +void SafepointSynchronize::arm_safepoint() { // Begin the process of bringing the system to a safepoint. // Java threads can be in several different states and are // stopped by different mechanisms: @@ -216,7 +315,7 @@ // memory writes are serialized with respect to each other, // the VM thread issues a memory barrier instruction. // 3. Running compiled Code - // Compiled code reads a global (Safepoint Polling) page that + // Compiled code reads the local polling page that // is set to fault if we are trying to get to a safepoint. // 4. Blocked // A thread which is blocked will not be allowed to return from the @@ -226,275 +325,154 @@ // between states, the safepointing code will wait for the thread to // block itself when it attempts transitions to a new state. // - { - EventSafepointStateSynchronization sync_event; - int initial_running = 0; - - _state = _synchronizing; - - if (SafepointMechanism::uses_thread_local_poll()) { - // Arming the per thread poll while having _state != _not_synchronized means safepointing - log_trace(safepoint)("Setting thread local yield flag for threads"); - OrderAccess::storestore(); // storestore, global state -> local state - for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) { - // Make sure the threads start polling, it is time to yield. - SafepointMechanism::arm_local_poll(cur); - } - } - OrderAccess::fence(); // storestore|storeload, global state -> local state - - if (SafepointMechanism::uses_global_page_poll()) { - // Make interpreter safepoint aware - Interpreter::notice_safepoints(); - - // Make polling safepoint aware - guarantee (PageArmed == 0, "invariant") ; - PageArmed = 1 ; - os::make_polling_page_unreadable(); - } - - // Consider using active_processor_count() ... but that call is expensive. - int ncpus = os::processor_count() ; - unsigned int iterations = 0; - - { - JavaThreadIteratorWithHandle jtiwh; -#ifdef ASSERT - for (; JavaThread *cur = jtiwh.next(); ) { - assert(cur->safepoint_state()->is_running(), "Illegal initial state"); - // Clear the visited flag to ensure that the critical counts are collected properly. - cur->set_visited_for_critical_count(false); - } -#endif // ASSERT - if (SafepointTimeout) - safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS; + // We must never miss a thread with correct safepoint id, so we must make sure we arm + // the wait barrier for the next safepoint id/counter. + // Arming must be done after resetting _current_jni_active_count, _waiting_to_block. + _wait_barrier->arm(static_cast(_safepoint_counter + 1)); - // Iterate through all threads until it have been determined how to stop them all at a safepoint - int steps = 0 ; - while(still_running > 0) { - jtiwh.rewind(); - for (; JavaThread *cur = jtiwh.next(); ) { - assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended"); - ThreadSafepointState *cur_state = cur->safepoint_state(); - if (cur_state->is_running()) { - cur_state->examine_state_of_thread(); - if (!cur_state->is_running()) { - still_running--; - // consider adjusting steps downward: - // steps = 0 - // steps -= NNN - // steps >>= 1 - // steps = MIN(steps, 2000-100) - // if (iterations != 0) steps -= NNN - } - LogTarget(Trace, safepoint) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - cur_state->print_on(&ls); - } - } - } - - if (iterations == 0) { - initial_running = still_running; - if (log_is_enabled(Debug, safepoint, stats)) { - begin_statistics(nof_threads, still_running); - } - } - - if (still_running > 0) { - // Check for if it takes to long - if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) { - print_safepoint_timeout(_spinning_timeout); - } + assert((_safepoint_counter & 0x1) == 0, "must be even"); + // The store to _safepoint_counter must happen after any stores in arming. + OrderAccess::release_store(&_safepoint_counter, _safepoint_counter + 1); - // Spin to avoid context switching. - // There's a tension between allowing the mutators to run (and rendezvous) - // vs spinning. As the VM thread spins, wasting cycles, it consumes CPU that - // a mutator might otherwise use profitably to reach a safepoint. Excessive - // spinning by the VM thread on a saturated system can increase rendezvous latency. - // Blocking or yielding incur their own penalties in the form of context switching - // and the resultant loss of $ residency. - // - // Further complicating matters is that yield() does not work as naively expected - // on many platforms -- yield() does not guarantee that any other ready threads - // will run. As such we revert to naked_short_sleep() after some number of iterations. - // nakes_short_sleep() is implemented as a short unconditional sleep. - // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping - // can actually increase the time it takes the VM thread to detect that a system-wide - // stop-the-world safepoint has been reached. In a pathological scenario such as that - // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe. - // In that case the mutators will be stalled waiting for the safepoint to complete and the - // the VMthread will be sleeping, waiting for the mutators to rendezvous. The VMthread - // will eventually wake up and detect that all mutators are safe, at which point - // we'll again make progress. - // - // Beware too that that the VMThread typically runs at elevated priority. - // Its default priority is higher than the default mutator priority. - // Obviously, this complicates spinning. - // - // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0). - // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will. - // - // See the comments in synchronizer.cpp for additional remarks on spinning. - // - // In the future we might: - // -- Modify the safepoint scheme to avoid potentially unbounded spinning. - // This is tricky as the path used by a thread exiting the JVM (say on - // on JNI call-out) simply stores into its state field. The burden - // is placed on the VM thread, which must poll (spin). - // -- Find something useful to do while spinning. If the safepoint is GC-related - // we might aggressively scan the stacks of threads that are already safe. - // -- YieldTo() any still-running mutators that are ready but OFFPROC. - // -- Check system saturation. If the system is not fully saturated then - // simply spin and avoid sleep/yield. - // -- As still-running mutators rendezvous they could unpark the sleeping - // VMthread. This works well for still-running mutators that become - // safe. The VMthread must still poll for mutators that call-out. - // -- Drive the policy on time-since-begin instead of iterations. - // -- Consider making the spin duration a function of the # of CPUs: - // Spin = (((ncpus-1) * M) + K) + F(still_running) - // Alternately, instead of counting iterations of the outer loop - // we could count the # of threads visited in the inner loop, above. - // -- On windows consider using the return value from SwitchThreadTo() - // to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions. + // We are synchronizing + OrderAccess::storestore(); // Ordered with _safepoint_counter + _state = _synchronizing; - if (int(iterations) == -1) { // overflow - something is wrong. - // We can only overflow here when we are using global - // polling pages. We keep this guarantee in its original - // form so that searches of the bug database for this - // failure mode find the right bugs. - guarantee (PageArmed == 0, "invariant"); - } - - // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or - // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus) - ++steps ; - if (ncpus > 1 && steps < safepoint_spin_before_yield) { - SpinPause() ; // MP-Polite spin - } else - if (steps < _defer_thr_suspend_loop_count) { - os::naked_yield() ; - } else { - os::naked_short_sleep(1); - } - - iterations ++ ; - } - assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long"); - } - } // ThreadsListHandle destroyed here. - assert(still_running == 0, "sanity check"); - - if (log_is_enabled(Debug, safepoint, stats)) { - update_statistics_on_spin_end(); - } - if (sync_event.should_commit()) { - post_safepoint_synchronize_event(&sync_event, initial_running, _waiting_to_block, iterations); + if (SafepointMechanism::uses_thread_local_poll()) { + // Arming the per thread poll while having _state != _not_synchronized means safepointing + log_trace(safepoint)("Setting thread local yield flag for threads"); + OrderAccess::storestore(); // storestore, global state -> local state + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) { + // Make sure the threads start polling, it is time to yield. + SafepointMechanism::arm_local_poll(cur); } } + OrderAccess::fence(); // storestore|storeload, global state -> local state - // wait until all threads are stopped - { - EventSafepointWaitBlocked wait_blocked_event; - int initial_waiting_to_block = _waiting_to_block; + if (SafepointMechanism::uses_global_page_poll()) { + // Make interpreter safepoint aware + Interpreter::notice_safepoints(); + + // Make polling safepoint aware + guarantee (!PageArmed, "invariant") ; + PageArmed = true; + os::make_polling_page_unreadable(); + } +} + +// Roll all threads forward to a safepoint and suspend them all +void SafepointSynchronize::begin() { + EventSafepointBegin begin_event; + assert(Thread::current()->is_VM_thread(), "Only VM thread may execute a safepoint"); + + strncpy(stopped_description, VMThread::vm_safepoint_description(), sizeof(stopped_description) - 1); + stopped_description[sizeof(stopped_description) - 1] = '\0'; + + if (log_is_enabled(Debug, safepoint, stats)) { + _safepoint_begin_time = os::javaTimeNanos(); + _ts_of_current_safepoint = tty->time_stamp().seconds(); + _nof_threads_hit_polling_page = 0; + } + + Universe::heap()->safepoint_synchronize_begin(); + + // By getting the Threads_lock, we assure that no threads are about to start or + // exit. It is released again in SafepointSynchronize::end(). + Threads_lock->lock(); + + assert( _state == _not_synchronized, "trying to safepoint synchronize with wrong state"); - while (_waiting_to_block > 0) { - log_debug(safepoint)("Waiting for %d thread(s) to block", _waiting_to_block); - if (!SafepointTimeout || timeout_error_printed) { - Safepoint_lock->wait(true); // true, means with no safepoint checks - } else { - // Compute remaining time - jlong remaining_time = safepoint_limit_time - os::javaTimeNanos(); + int nof_threads = Threads::number_of_threads(); + + log_debug(safepoint)("Safepoint synchronization initiated using %s wait barrier. (%d threads)", _wait_barrier->description(), nof_threads); + + RuntimeService::record_safepoint_begin(); + + // Reset the count of active JNI critical threads + _current_jni_active_count = 0; + + // Set number of threads to wait for + _waiting_to_block = nof_threads; - // If there is no remaining time, then there is an error - if (remaining_time < 0 || Safepoint_lock->wait(true, remaining_time / MICROUNITS)) { - print_safepoint_timeout(_blocking_timeout); - } - } - } - assert(_waiting_to_block == 0, "sanity check"); + jlong safepoint_limit_time = 0; + if (SafepointTimeout) { + // Set the limit time, so that it can be compared to see if this has taken + // too long to complete. + safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS; + } + timeout_error_printed = false; + + EventSafepointStateSynchronization sync_event; + int initial_running = 0; + + // Arms the safepoint, _current_jni_active_count and _waiting_to_block must be set before. + arm_safepoint(); + + // Will spin until all threads are safe. + int iterations = synchronize_threads(safepoint_limit_time, nof_threads, &initial_running); + assert(_waiting_to_block == 0, "No thread should be running"); + + post_safepoint_synchronize_event(sync_event, _safepoint_counter, initial_running, + _waiting_to_block, iterations); + + // Keep event from now. + EventSafepointWaitBlocked wait_blocked_event; #ifndef PRODUCT - if (SafepointTimeout) { - jlong current_time = os::javaTimeNanos(); - if (safepoint_limit_time < current_time) { - log_warning(safepoint)("# SafepointSynchronize: Finished after " - INT64_FORMAT_W(6) " ms", - (int64_t)((current_time - safepoint_limit_time) / MICROUNITS + - (jlong)SafepointTimeoutDelay)); - } + if (SafepointTimeout) { + jlong current_time = os::javaTimeNanos(); + if (safepoint_limit_time < current_time) { + log_warning(safepoint)("# SafepointSynchronize: Finished after " + INT64_FORMAT_W(6) " ms", + (int64_t)((current_time - safepoint_limit_time) / MICROUNITS + + (jlong)SafepointTimeoutDelay)); } + } #endif - assert((_safepoint_counter & 0x1) == 0, "must be even"); - assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); - _safepoint_counter ++; + assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); - // Record state - _state = _synchronized; + // Record state + _state = _synchronized; - OrderAccess::fence(); - if (wait_blocked_event.should_commit()) { - post_safepoint_wait_blocked_event(&wait_blocked_event, initial_waiting_to_block); - } - } + OrderAccess::fence(); + + post_safepoint_wait_blocked_event(wait_blocked_event, _safepoint_counter, 0); #ifdef ASSERT // Make sure all the threads were visited. for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) { - assert(cur->was_visited_for_critical_count(), "missed a thread"); + assert(cur->was_visited_for_critical_count(_safepoint_counter), "missed a thread"); } #endif // ASSERT // Update the count of active JNI critical regions GCLocker::set_jni_lock_count(_current_jni_active_count); - log_info(safepoint)("Entering safepoint region: %s", VMThread::vm_safepoint_description()); + log_info(safepoint)("Entering safepoint region: %s", stopped_description); RuntimeService::record_safepoint_synchronized(); if (log_is_enabled(Debug, safepoint, stats)) { update_statistics_on_sync_end(os::javaTimeNanos()); } - // Call stuff that needs to be run when a safepoint is just about to be completed - { - EventSafepointCleanup cleanup_event; - do_cleanup_tasks(); - if (cleanup_event.should_commit()) { - post_safepoint_cleanup_event(&cleanup_event); - } - } + // We do the safepoint cleanup first since a GC related safepoint + // needs cleanup to be completed before running the GC op. + EventSafepointCleanup cleanup_event; + do_cleanup_tasks(); + post_safepoint_cleanup_event(cleanup_event, _safepoint_counter); if (log_is_enabled(Debug, safepoint, stats)) { // Record how much time spend on the above cleanup tasks update_statistics_on_cleanup_end(os::javaTimeNanos()); } - if (begin_event.should_commit()) { - post_safepoint_begin_event(&begin_event, nof_threads, _current_jni_active_count); - } + post_safepoint_begin_event(begin_event, _safepoint_counter, nof_threads, _current_jni_active_count); } -// Wake up all threads, so they are ready to resume execution after the safepoint -// operation has been carried out -void SafepointSynchronize::end() { - assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); - assert((_safepoint_counter & 0x1) == 1, "must be odd"); - EventSafepointEnd event; - _safepoint_counter ++; - // memory fence isn't required here since an odd _safepoint_counter - // value can do no harm and a fence is issued below anyway. - - DEBUG_ONLY(Thread* myThread = Thread::current();) - assert(myThread->is_VM_thread(), "Only VM thread can execute a safepoint"); - - if (log_is_enabled(Debug, safepoint, stats)) { - end_statistics(os::javaTimeNanos()); - } - +void SafepointSynchronize::disarm_safepoint() { + uint64_t safepoint_id = _safepoint_counter; { JavaThreadIteratorWithHandle jtiwh; #ifdef ASSERT @@ -508,66 +486,74 @@ } #endif // ASSERT - if (PageArmed) { - assert(SafepointMechanism::uses_global_page_poll(), "sanity"); + if (SafepointMechanism::uses_global_page_poll()) { + guarantee (PageArmed, "invariant"); // Make polling safepoint aware os::make_polling_page_readable(); - PageArmed = 0 ; - } - - if (SafepointMechanism::uses_global_page_poll()) { + PageArmed = false; // Remove safepoint check from interpreter Interpreter::ignore_safepoints(); } - { - MutexLocker mu(Safepoint_lock); + OrderAccess::fence(); // keep read and write of _state from floating up + assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization"); + + // Change state first to _not_synchronized. + // No threads should see _synchronized when running. + _state = _not_synchronized; + + // Set the next dormant (even) safepoint id. + assert((_safepoint_counter & 0x1) == 1, "must be odd"); + OrderAccess::release_store(&_safepoint_counter, _safepoint_counter + 1); - assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization"); + OrderAccess::fence(); // Keep the local state from floating up. + + jtiwh.rewind(); + for (; JavaThread *current = jtiwh.next(); ) { + // Clear the visited flag to ensure that the critical counts are collected properly. + DEBUG_ONLY(current->reset_visited_for_critical_count(safepoint_id);) + ThreadSafepointState* cur_state = current->safepoint_state(); + assert(!cur_state->is_running(), "Thread not suspended at safepoint"); + cur_state->restart(); // TSS _running + assert(cur_state->is_running(), "safepoint state has not been reset"); + SafepointMechanism::disarm_local_poll(current); + } + } // ~JavaThreadIteratorWithHandle - if (SafepointMechanism::uses_thread_local_poll()) { - _state = _not_synchronized; - OrderAccess::storestore(); // global state -> local state - jtiwh.rewind(); - for (; JavaThread *current = jtiwh.next(); ) { - ThreadSafepointState* cur_state = current->safepoint_state(); - cur_state->restart(); // TSS _running - SafepointMechanism::disarm_local_poll(current); - } - log_info(safepoint)("Leaving safepoint region"); - } else { - // Set to not synchronized, so the threads will not go into the signal_thread_blocked method - // when they get restarted. - _state = _not_synchronized; - OrderAccess::fence(); + log_info(safepoint)("Leaving safepoint region"); + + RuntimeService::record_safepoint_end(); - log_info(safepoint)("Leaving safepoint region"); + // Release threads lock, so threads can be created/destroyed again. + Threads_lock->unlock(); + + // Wake threads after local state is correctly set. + _wait_barrier->disarm(); +} - // Start suspended threads - jtiwh.rewind(); - for (; JavaThread *current = jtiwh.next(); ) { - ThreadSafepointState* cur_state = current->safepoint_state(); - assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint"); - cur_state->restart(); - assert(cur_state->is_running(), "safepoint state has not been reset"); - } - } +// Wake up all threads, so they are ready to resume execution after the safepoint +// operation has been carried out +void SafepointSynchronize::end() { + assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); + EventSafepointEnd event; + uint64_t safepoint_id = _safepoint_counter; + assert(Thread::current()->is_VM_thread(), "Only VM thread can execute a safepoint"); - RuntimeService::record_safepoint_end(); + if (log_is_enabled(Debug, safepoint, stats)) { + end_statistics(os::javaTimeNanos()); + } - // Release threads lock, so threads can be created/destroyed again. - // It will also release all threads blocked in signal_thread_blocked. - Threads_lock->unlock(); - } - } // ThreadsListHandle destroyed here. + disarm_safepoint(); + + RuntimeService::record_safepoint_epilog(stopped_description); Universe::heap()->safepoint_synchronize_end(); + // record this time so VMThread can keep track how much time has elapsed // since last safepoint. _end_of_last_safepoint = os::javaTimeMillis(); - if (event.should_commit()) { - post_safepoint_end_event(&event); - } + + post_safepoint_end_event(event, safepoint_id); } bool SafepointSynchronize::is_cleanup_needed() { @@ -613,6 +599,7 @@ _counters(counters) {} void work(uint worker_id) { + uint64_t safepoint_id = SafepointSynchronize::safepoint_counter(); // All threads deflate monitors and mark nmethods (if necessary). Threads::possibly_parallel_threads_do(true, &_cleanup_threads_cl); @@ -621,9 +608,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); ObjectSynchronizer::deflate_idle_monitors(_counters); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_UPDATE_INLINE_CACHES)) { @@ -631,9 +617,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); InlineCacheBuffer::update_inline_caches(); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_COMPILATION_POLICY)) { @@ -641,9 +626,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); CompilationPolicy::policy()->do_safepoint_work(); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH)) { @@ -652,9 +636,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); SymbolTable::rehash_table(); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } } @@ -664,9 +647,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); StringTable::rehash_table(); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } } @@ -677,9 +659,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); ClassLoaderDataGraph::purge_if_needed(); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_SYSTEM_DICTIONARY_RESIZE)) { @@ -687,9 +668,8 @@ EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); ClassLoaderDataGraph::resize_if_needed(); - if (event.should_commit()) { - post_safepoint_cleanup_task_event(&event, name); - } + + post_safepoint_cleanup_task_event(event, safepoint_id, name); } _subtasks.all_tasks_completed(_num_workers); @@ -736,15 +716,48 @@ assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); } +// Methods for determining if a JavaThread is safepoint safe. -bool SafepointSynchronize::safepoint_safe(JavaThread *thread, JavaThreadState state) { +// False means unsafe with undetermined state. +// True means a determined state, but it may be an unsafe state. +// If called from a non-safepoint context safepoint_count MUST be InactiveSafepointCounter. +bool SafepointSynchronize::try_stable_load_state(JavaThreadState *state, JavaThread *thread, uint64_t safepoint_count) { + assert((safepoint_count != InactiveSafepointCounter && + Thread::current() == (Thread*)VMThread::vm_thread() && + SafepointSynchronize::_state != _not_synchronized) + || safepoint_count == InactiveSafepointCounter, "Invalid check"); + + // To handle the thread_blocked state on the backedge of the WaitBarrier from + // previous safepoint and reading the reset value (0/InactiveSafepointCounter) we + // re-read state after we read thread safepoint id. The JavaThread changes its + // thread state from thread_blocked before resetting safepoint id to 0. + // This guarantees the second read will be from an updated thread state. It can + // either be different state making this an unsafe state or it can see blocked + // again. When we see blocked twice with a 0 safepoint id, either: + // - It is normally blocked, e.g. on Mutex, TBIVM. + // - It was in SS:block(), looped around to SS:block() and is blocked on the WaitBarrier. + // - It was in SS:block() but now on a Mutex. + // All of these cases are safe. + + *state = thread->thread_state(); + OrderAccess::loadload(); + uint64_t sid = thread->safepoint_state()->get_safepoint_id(); // Load acquire + if (sid != InactiveSafepointCounter && sid != safepoint_count) { + // In an old safepoint, state not relevant. + return false; + } + return *state == thread->thread_state(); +} + +static bool safepoint_safe_with(JavaThread *thread, JavaThreadState state) { switch(state) { case _thread_in_native: // native threads are safe if they have no java stack or have walkable stack return !thread->has_last_Java_frame() || thread->frame_anchor()->walkable(); - // blocked threads should have already have walkable stack case _thread_blocked: + // On wait_barrier or blocked. + // Blocked threads should already have walkable stack. assert(!thread->has_last_Java_frame() || thread->frame_anchor()->walkable(), "blocked and not walkable"); return true; @@ -753,12 +766,28 @@ } } +bool SafepointSynchronize::handshake_safe(JavaThread *thread) { + // The polls must be armed otherwise the safe state can change to unsafe at any time. + assert(SafepointMechanism::should_block(thread), "Must be armed"); + // This function must be called with the Threads_lock held so an externally + // suspended thread cannot be resumed thus it is safe. + assert(Threads_lock->owned_by_self() && Thread::current()->is_VM_thread(), + "Must hold Threads_lock and be VMThread"); + if (thread->is_ext_suspended() || thread->is_terminated()) { + return true; + } + JavaThreadState stable_state; + if (try_stable_load_state(&stable_state, thread, InactiveSafepointCounter)) { + return safepoint_safe_with(thread, stable_state); + } + return false; +} // See if the thread is running inside a lazy critical native and // update the thread critical count if so. Also set a suspend flag to // cause the native wrapper to return into the JVM to do the unlock // once the native finishes. -void SafepointSynchronize::check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state) { +static void check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state) { if (state == _thread_in_native && thread->has_last_Java_frame() && thread->frame_anchor()->walkable()) { @@ -788,12 +817,10 @@ } } - +// ------------------------------------------------------------------------------------------------------- +// Implementation of Safepoint blocking point -// ------------------------------------------------------------------------------------------------------- -// Implementation of Safepoint callback point - -void SafepointSynchronize::block(JavaThread *thread, bool block_in_safepoint_check) { +void SafepointSynchronize::block(JavaThread *thread) { assert(thread != NULL, "thread must be set"); assert(thread->is_Java_thread(), "not a Java thread"); @@ -813,101 +840,45 @@ JavaThreadState state = thread->thread_state(); thread->frame_anchor()->make_walkable(thread); + uint64_t safepoint_id = SafepointSynchronize::safepoint_counter(); // Check that we have a valid thread_state at this point switch(state) { case _thread_in_vm_trans: case _thread_in_Java: // From compiled code - - // We are highly likely to block on the Safepoint_lock. In order to avoid blocking in this case, - // we pretend we are still in the VM. - thread->set_thread_state(_thread_in_vm); - - if (is_synchronizing()) { - Atomic::inc (&TryingToBlock) ; - } - - // We will always be holding the Safepoint_lock when we are examine the state - // of a thread. Hence, the instructions between the Safepoint_lock->lock() and - // Safepoint_lock->unlock() are happening atomic with regards to the safepoint code - Safepoint_lock->lock_without_safepoint_check(); - if (is_synchronizing()) { - // Decrement the number of threads to wait for and signal vm thread - assert(_waiting_to_block > 0, "sanity check"); - _waiting_to_block--; - thread->safepoint_state()->set_has_called_back(true); - - DEBUG_ONLY(thread->set_visited_for_critical_count(true)); - if (thread->in_critical()) { - // Notice that this thread is in a critical section - increment_jni_active_count(); - } - - // Consider (_waiting_to_block < 2) to pipeline the wakeup of the VM thread - if (_waiting_to_block == 0) { - Safepoint_lock->notify_all(); - } - } - - if (block_in_safepoint_check) { - // We transition the thread to state _thread_blocked here, but - // we can't do our usual check for external suspension and then - // self-suspend after the lock_without_safepoint_check() call - // below because we are often called during transitions while - // we hold different locks. That would leave us suspended while - // holding a resource which results in deadlocks. - thread->set_thread_state(_thread_blocked); - Safepoint_lock->unlock(); - - // We now try to acquire the threads lock. Since this lock is hold by the VM thread during - // the entire safepoint, the threads will all line up here during the safepoint. - Threads_lock->lock_without_safepoint_check(); - // restore original state. This is important if the thread comes from compiled code, so it - // will continue to execute with the _thread_in_Java state. - thread->set_thread_state(state); - Threads_lock->unlock(); - } else { - // We choose not to block in this call since we would be - // caught when transitioning back anyways if the safepoint - // is still going on. - thread->set_thread_state(state); - Safepoint_lock->unlock(); - } - break; - case _thread_in_native_trans: case _thread_blocked_trans: case _thread_new_trans: - if (thread->safepoint_state()->type() == ThreadSafepointState::_call_back && - block_in_safepoint_check) { - thread->print_thread_state(); - fatal("Deadlock in safepoint code. " - "Should have called back to the VM before blocking."); - } + + // We have no idea where the VMThread is, it might even be at next safepoint. + // So we can miss this poll, but stop at next. - // We transition the thread to state _thread_blocked here, but - // we can't do our usual check for external suspension and then - // self-suspend after the lock_without_safepoint_check() call - // below because we are often called during transitions while - // we hold different locks. That would leave us suspended while - // holding a resource which results in deadlocks. + // Load dependent store, it must not pass loading of safepoint_id. + thread->safepoint_state()->set_safepoint_id(safepoint_id); // Release store + + // This part we can skip if we notice we miss or are in a future safepoint. + OrderAccess::storestore(); thread->set_thread_state(_thread_blocked); - // It is not safe to suspend a thread if we discover it is in _thread_in_native_trans. Hence, - // the safepoint code might still be waiting for it to block. We need to change the state here, - // so it can see that it is at a safepoint. + OrderAccess::fence(); // Load in wait barrier should not float up + _wait_barrier->wait(static_cast(safepoint_id)); + assert(_state != _synchronized, "Can't be"); - // Block until the safepoint operation is completed. - Threads_lock->lock_without_safepoint_check(); - - // Restore state + // If barrier is disarmed stop store from floating above loads in barrier. + OrderAccess::loadstore(); thread->set_thread_state(state); - Threads_lock->unlock(); + // Then we reset the safepoint id to inactive. + thread->safepoint_state()->reset_safepoint_id(); // Release store + + OrderAccess::fence(); + break; default: fatal("Illegal threadstate encountered: %d", state); } + guarantee(thread->safepoint_state()->get_safepoint_id() == InactiveSafepointCounter, + "The safepoint id should be set only in block path"); // Check for pending. async. exceptions or suspends - except if the // thread was blocked inside the VM. has_special_runtime_exit_condition() @@ -979,7 +950,7 @@ if (cur_thread->thread_state() != _thread_blocked && ((reason == _spinning_timeout && cur_state->is_running()) || - (reason == _blocking_timeout && !cur_state->has_called_back()))) { + (reason == _blocking_timeout))) { ls.print("# "); cur_thread->print_on(&ls); ls.cr(); @@ -1001,11 +972,10 @@ // ------------------------------------------------------------------------------------------------------- // Implementation of ThreadSafepointState -ThreadSafepointState::ThreadSafepointState(JavaThread *thread) { - _thread = thread; - _type = _running; - _has_called_back = false; - _at_poll_safepoint = false; +ThreadSafepointState::ThreadSafepointState(JavaThread *thread) + : _at_poll_safepoint(false), _thread(thread), _safepoint_safe(false), + _safepoint_id(SafepointSynchronize::InactiveSafepointCounter), + _orig_thread_state(_thread_uninitialized), _next(NULL) { } void ThreadSafepointState::create(JavaThread *thread) { @@ -1020,13 +990,30 @@ } } -void ThreadSafepointState::examine_state_of_thread() { +uint64_t ThreadSafepointState::get_safepoint_id() const { + return OrderAccess::load_acquire(&_safepoint_id); +} + +void ThreadSafepointState::reset_safepoint_id() { + OrderAccess::release_store(&_safepoint_id, SafepointSynchronize::InactiveSafepointCounter); +} + +void ThreadSafepointState::set_safepoint_id(uint64_t safepoint_id) { + OrderAccess::release_store(&_safepoint_id, safepoint_id); +} + +void ThreadSafepointState::examine_state_of_thread(uint64_t safepoint_count) { assert(is_running(), "better be running or just have hit safepoint poll"); - JavaThreadState state = _thread->thread_state(); + JavaThreadState stable_state; + if (!SafepointSynchronize::try_stable_load_state(&stable_state, _thread, safepoint_count)) { + // We could not get stable state of the JavaThread. + // Consider it running and just return. + return; + } // Save the state at the start of safepoint processing. - _orig_thread_state = state; + _orig_thread_state = stable_state; // Check for a thread that is suspended. Note that thread resume tries // to grab the Threads_lock which we own here, so a thread cannot be @@ -1050,21 +1037,13 @@ // bool is_suspended = _thread->is_ext_suspended(); if (is_suspended) { - roll_forward(_at_safepoint); + account_safe_thread(); return; } - // Some JavaThread states have an initial safepoint state of - // running, but are actually at a safepoint. We will happily - // agree and update the safepoint state here. - if (SafepointSynchronize::safepoint_safe(_thread, state)) { - SafepointSynchronize::check_for_lazy_critical_native(_thread, state); - roll_forward(_at_safepoint); - return; - } - - if (state == _thread_in_vm) { - roll_forward(_call_back); + if (safepoint_safe_with(_thread, stable_state)) { + check_for_lazy_critical_native(_thread, stable_state); + account_safe_thread(); return; } @@ -1077,63 +1056,28 @@ return; } -// Returns true is thread could not be rolled forward at present position. -void ThreadSafepointState::roll_forward(suspend_type type) { - _type = type; - - switch(_type) { - case _at_safepoint: - SafepointSynchronize::signal_thread_at_safepoint(); - DEBUG_ONLY(_thread->set_visited_for_critical_count(true)); - if (_thread->in_critical()) { - // Notice that this thread is in a critical section - SafepointSynchronize::increment_jni_active_count(); - } - break; - - case _call_back: - set_has_called_back(false); - break; - - case _running: - default: - ShouldNotReachHere(); +void ThreadSafepointState::account_safe_thread() { + SafepointSynchronize::decrement_waiting_to_block(); + if (_thread->in_critical()) { + // Notice that this thread is in a critical section + SafepointSynchronize::increment_jni_active_count(); } + DEBUG_ONLY(_thread->set_visited_for_critical_count(SafepointSynchronize::safepoint_counter());) + assert(!_safepoint_safe, "Must be unsafe before safe"); + _safepoint_safe = true; } void ThreadSafepointState::restart() { - switch(type()) { - case _at_safepoint: - case _call_back: - break; - - case _running: - default: - tty->print_cr("restart thread " INTPTR_FORMAT " with state %d", - p2i(_thread), _type); - _thread->print(); - ShouldNotReachHere(); - } - _type = _running; - set_has_called_back(false); + assert(_safepoint_safe, "Must be safe before unsafe"); + _safepoint_safe = false; } - void ThreadSafepointState::print_on(outputStream *st) const { - const char *s = NULL; - - switch(_type) { - case _running : s = "_running"; break; - case _at_safepoint : s = "_at_safepoint"; break; - case _call_back : s = "_call_back"; break; - default: - ShouldNotReachHere(); - } + const char *s = _safepoint_safe ? "_at_safepoint" : "_running"; st->print_cr("Thread: " INTPTR_FORMAT - " [0x%2x] State: %s _has_called_back %d _at_poll_safepoint %d", - p2i(_thread), _thread->osthread()->thread_id(), s, _has_called_back, - _at_poll_safepoint); + " [0x%2x] State: %s _at_poll_safepoint %d", + p2i(_thread), _thread->osthread()->thread_id(), s, _at_poll_safepoint); _thread->print_thread_state_on(st); } @@ -1143,11 +1087,10 @@ // Block the thread at poll or poll return for safepoint/handshake. void ThreadSafepointState::handle_polling_page_exception() { - // Check state. block() will set thread state to thread_in_vm which will - // cause the safepoint state _type to become _call_back. - suspend_type t = type(); - assert(!SafepointMechanism::uses_global_page_poll() || t == ThreadSafepointState::_running, - "polling page exception on thread not running state: %u", uint(t)); + // If we're using a global poll, then the thread should not be + // marked as safepoint safe yet. + assert(!SafepointMechanism::uses_global_page_poll() || !_safepoint_safe, + "polling page exception on thread safepoint safe"); // Step 1: Find the nmethod from the return address address real_return_addr = thread()->saved_exception_pc(); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/safepoint.hpp --- a/src/hotspot/share/runtime/safepoint.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/safepoint.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -26,15 +26,15 @@ #define SHARE_RUNTIME_SAFEPOINT_HPP #include "memory/allocation.hpp" -#include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" -#include "utilities/globalDefinitions.hpp" +#include "runtime/thread.hpp" #include "utilities/ostream.hpp" +#include "utilities/waitBarrier.hpp" // // Safepoint synchronization //// -// The VMThread or CMS_thread uses the SafepointSynchronize::begin/end +// The VMThread uses the SafepointSynchronize::begin/end // methods to enter/exit a safepoint region. The begin method will roll // all JavaThreads forward to a safepoint. // @@ -45,9 +45,7 @@ // exit safepoint methods, when a thread is blocked/restarted. Hence, all mutex exter/ // exit points *must* be at a safepoint. - class ThreadSafepointState; -class JavaThread; // // Implements roll-forward to safepoint (safepoint synchronization) @@ -55,21 +53,10 @@ class SafepointSynchronize : AllStatic { public: enum SynchronizeState { - _not_synchronized = 0, // Threads not synchronized at a safepoint - // Keep this value 0. See the comment in do_call_back() + _not_synchronized = 0, // Threads not synchronized at a safepoint. Keep this value 0. _synchronizing = 1, // Synchronizing in progress - _synchronized = 2 // All Java threads are stopped at a safepoint. Only VM thread is running - }; - - enum SafepointingThread { - _null_thread = 0, - _vm_thread = 1, - _other_thread = 2 - }; - - enum SafepointTimeoutReason { - _spinning_timeout = 0, - _blocking_timeout = 1 + _synchronized = 2 // All Java threads are running in native, blocked in OS or stopped at safepoint. + // VM thread and any NonJavaThread may be running. }; // The enums are listed in the order of the tasks when done serially. @@ -86,22 +73,33 @@ }; private: - static volatile SynchronizeState _state; // Threads might read this flag directly, without acquiring the Threads_lock - static volatile int _waiting_to_block; // number of threads we are waiting for to block - static int _current_jni_active_count; // Counts the number of active critical natives during the safepoint - static int _defer_thr_suspend_loop_count; // Iterations before blocking VM threads + friend class SafepointMechanism; + friend class ThreadSafepointState; + friend class HandshakeState; + + enum SafepointTimeoutReason { + _spinning_timeout = 0, + _blocking_timeout = 1 + }; + + // Threads might read this flag directly, without acquiring the Threads_lock: + static volatile SynchronizeState _state; + // Number of threads we are waiting for to block: + static int _waiting_to_block; + // Counts the number of active critical natives during the safepoint: + static int _current_jni_active_count; // This counter is used for fast versions of jni_GetField. - // An even value means there is no ongoing safepoint operations. + // An even value means there are no ongoing safepoint operations. // The counter is incremented ONLY at the beginning and end of each - // safepoint. The fact that Threads_lock is held throughout each pair of - // increments (at the beginning and end of each safepoint) guarantees - // race freedom. + // safepoint. static volatile uint64_t _safepoint_counter; -private: - static long _end_of_last_safepoint; // Time of last safepoint in milliseconds - static julong _coalesced_vmop_count; // coalesced vmop count + // JavaThreads that need to block for the safepoint will stop on the + // _wait_barrier, where they can quickly be started again. + static WaitBarrier* _wait_barrier; + static long _end_of_last_safepoint; // Time of last safepoint in milliseconds + static julong _coalesced_vmop_count; // coalesced vmop count // Statistics static void begin_statistics(int nof_threads, int nof_running); @@ -114,42 +112,41 @@ // For debug long safepoint static void print_safepoint_timeout(SafepointTimeoutReason timeout_reason); + // Helper methods for safepoint procedure: + static void arm_safepoint(); + static int synchronize_threads(jlong safepoint_limit_time, int nof_threads, int* initial_running); + static void disarm_safepoint(); + static void increment_jni_active_count(); + static void decrement_waiting_to_block(); + + // Used in safepoint_safe to do a stable load of the thread state. + static bool try_stable_load_state(JavaThreadState *state, + JavaThread *thread, + uint64_t safepoint_count); + + // Called when a thread voluntarily blocks + static void block(JavaThread *thread); + + // Called from VMThread during handshakes. + // If true the VMThread may safely process the handshake operation for the JavaThread. + static bool handshake_safe(JavaThread *thread); + public: - // Main entry points + static void init(Thread* vmthread); - // Roll all threads forward to safepoint. Must be called by the - // VMThread or CMS_thread. + // Roll all threads forward to safepoint. Must be called by the VMThread. static void begin(); static void end(); // Start all suspended threads again... - static bool safepoint_safe(JavaThread *thread, JavaThreadState state); - - static void check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state); + // The value for a not set safepoint id. + static const uint64_t InactiveSafepointCounter; // Query - inline static bool is_at_safepoint() { return _state == _synchronized; } - inline static bool is_synchronizing() { return _state == _synchronizing; } - inline static uint64_t safepoint_counter() { return _safepoint_counter; } - - inline static void increment_jni_active_count() { - assert_locked_or_safepoint(Safepoint_lock); - _current_jni_active_count++; - } - -private: - inline static bool do_call_back() { - return (_state != _not_synchronized); - } - - // Called when a thread voluntarily blocks - static void block(JavaThread *thread, bool block_in_safepoint_check = true); - - friend class SafepointMechanism; - -public: - static void signal_thread_at_safepoint() { _waiting_to_block--; } - + static bool is_at_safepoint() { return _state == _synchronized; } + static bool is_synchronizing() { return _state == _synchronizing; } + static uint64_t safepoint_counter() { return _safepoint_counter; } + static bool is_same_safepoint(uint64_t counter) { return (SafepointSynchronize::safepoint_counter() - counter) < 2; } // Exception handling for page polling static void handle_polling_page_exception(JavaThread *thread); @@ -164,13 +161,13 @@ static void do_cleanup_tasks(); static void print_stat_on_exit(); - inline static void inc_vmop_coalesced_count() { _coalesced_vmop_count++; } + static void inc_vmop_coalesced_count() { _coalesced_vmop_count++; } - static void set_is_at_safepoint() { _state = _synchronized; } - static void set_is_not_at_safepoint() { _state = _not_synchronized; } + static void set_is_at_safepoint() { _state = _synchronized; } + static void set_is_not_at_safepoint() { _state = _not_synchronized; } // Assembly support - static address address_of_state() { return (address)&_state; } + static address address_of_state() { return (address)&_state; } // Only used for making sure that no safepoint has happened in // JNI_FastGetField. Therefore only the low 32-bits are needed @@ -201,44 +198,43 @@ // State class for a thread suspended at a safepoint class ThreadSafepointState: public CHeapObj { - public: - // These states are maintained by VM thread while threads are being brought - // to a safepoint. After SafepointSynchronize::end(), they are reset to - // _running. - enum suspend_type { - _running = 0, // Thread state not yet determined (i.e., not at a safepoint yet) - _at_safepoint = 1, // Thread at a safepoint (f.ex., when blocked on a lock) - _call_back = 2 // Keep executing and wait for callback (if thread is in interpreted or vm) - }; private: - volatile bool _at_poll_safepoint; // At polling page safepoint (NOT a poll return safepoint) - // Thread has called back the safepoint code (for debugging) - bool _has_called_back; + // At polling page safepoint (NOT a poll return safepoint): + volatile bool _at_poll_safepoint; + JavaThread* _thread; + bool _safepoint_safe; + volatile uint64_t _safepoint_id; + JavaThreadState _orig_thread_state; - JavaThread * _thread; - volatile suspend_type _type; - JavaThreadState _orig_thread_state; + ThreadSafepointState* _next; + void account_safe_thread(); public: ThreadSafepointState(JavaThread *thread); - // examine/roll-forward/restart - void examine_state_of_thread(); - void roll_forward(suspend_type type); + // Linked list support: + ThreadSafepointState* get_next() const { return _next; } + void set_next(ThreadSafepointState* value) { _next = value; } + ThreadSafepointState** next_ptr() { return &_next; } + + // examine/restart + void examine_state_of_thread(uint64_t safepoint_count); void restart(); // Query JavaThread* thread() const { return _thread; } - suspend_type type() const { return _type; } - bool is_running() const { return (_type==_running); } + bool is_running() const { return !_safepoint_safe; } + + uint64_t get_safepoint_id() const; + void reset_safepoint_id(); + void set_safepoint_id(uint64_t sid); + JavaThreadState orig_thread_state() const { return _orig_thread_state; } // Support for safepoint timeout (debugging) - bool has_called_back() const { return _has_called_back; } - void set_has_called_back(bool val) { _has_called_back = val; } - bool is_at_poll_safepoint() { return _at_poll_safepoint; } - void set_at_poll_safepoint(bool val) { _at_poll_safepoint = val; } + bool is_at_poll_safepoint() { return _at_poll_safepoint; } + void set_at_poll_safepoint(bool val) { _at_poll_safepoint = val; } void handle_polling_page_exception(); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/safepointMechanism.cpp --- a/src/hotspot/share/runtime/safepointMechanism.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/safepointMechanism.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -86,6 +86,9 @@ void SafepointMechanism::block_if_requested_slow(JavaThread *thread) { // local poll already checked, if used. if (global_poll()) { + // Any load in ::block must not pass the global poll load. + // Otherwise we might load an old safepoint counter (for example). + OrderAccess::loadload(); SafepointSynchronize::block(thread); } if (uses_thread_local_poll() && thread->has_handshake()) { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/safepointMechanism.hpp --- a/src/hotspot/share/runtime/safepointMechanism.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/safepointMechanism.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -78,9 +78,6 @@ // Blocks a thread until safepoint/handshake is completed. static inline void block_if_requested(JavaThread* thread); - // Calls back if there is a pending safepoint but does not block for it. - static inline void callback_if_safepoint(JavaThread* thread); - // Caller is responsible for using a memory barrier if needed. static inline void arm_local_poll(JavaThread* thread); static inline void disarm_local_poll(JavaThread* thread); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/safepointMechanism.inline.hpp --- a/src/hotspot/share/runtime/safepointMechanism.inline.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/safepointMechanism.inline.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -35,7 +35,7 @@ } bool SafepointMechanism::global_poll() { - return SafepointSynchronize::do_call_back(); + return (SafepointSynchronize::_state != SafepointSynchronize::_not_synchronized); } bool SafepointMechanism::local_poll(Thread* thread) { @@ -62,20 +62,6 @@ block_if_requested_slow(thread); } -void SafepointMechanism::callback_if_safepoint(JavaThread* thread) { - if (!uses_thread_local_poll() || local_poll_armed(thread)) { - // If using thread local polls, we should not check the - // global_poll() and callback via block() if the VMThread - // has not yet armed the local poll. Otherwise, when used in - // combination with should_block(), the latter could miss - // detecting the same safepoint that this method would detect - // if only checking global polls. - if (global_poll()) { - SafepointSynchronize::block(thread, false); - } - } -} - void SafepointMechanism::arm_local_poll(JavaThread* thread) { thread->set_polling_page(poll_armed_value()); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/task.cpp --- a/src/hotspot/share/runtime/task.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/task.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -31,48 +31,20 @@ int PeriodicTask::_num_tasks = 0; PeriodicTask* PeriodicTask::_tasks[PeriodicTask::max_tasks]; -#ifndef PRODUCT -elapsedTimer PeriodicTask::_timer; -int PeriodicTask::_intervalHistogram[PeriodicTask::max_interval]; -int PeriodicTask::_ticks; - -void PeriodicTask::print_intervals() { - if (ProfilerCheckIntervals) { - for (int i = 0; i < PeriodicTask::max_interval; i++) { - int n = _intervalHistogram[i]; - if (n > 0) tty->print_cr("%3d: %5d (%4.1f%%)", i, n, 100.0 * n / _ticks); - } - } -} -#endif void PeriodicTask::real_time_tick(int delay_time) { assert(Thread::current()->is_Watcher_thread(), "must be WatcherThread"); -#ifndef PRODUCT - if (ProfilerCheckIntervals) { - _ticks++; - _timer.stop(); - int ms = (int)_timer.milliseconds(); - _timer.reset(); - _timer.start(); - if (ms >= PeriodicTask::max_interval) ms = PeriodicTask::max_interval - 1; - _intervalHistogram[ms]++; - } -#endif + // The WatcherThread does not participate in the safepoint protocol + // for the PeriodicTask_lock because it is not a JavaThread. + MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); + int orig_num_tasks = _num_tasks; - { - // The WatcherThread does not participate in the safepoint protocol - // for the PeriodicTask_lock because it is not a JavaThread. - MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); - int orig_num_tasks = _num_tasks; - - for(int index = 0; index < _num_tasks; index++) { - _tasks[index]->execute_if_pending(delay_time); - if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself - index--; // re-do current slot as it has changed - orig_num_tasks = _num_tasks; - } + for(int index = 0; index < _num_tasks; index++) { + _tasks[index]->execute_if_pending(delay_time); + if (_num_tasks < orig_num_tasks) { // task dis-enrolled itself + index--; // re-do current slot as it has changed + orig_num_tasks = _num_tasks; } } } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/task.hpp --- a/src/hotspot/share/runtime/task.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/task.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -58,13 +58,6 @@ // Can only be called by the WatcherThread static void real_time_tick(int delay_time); -#ifndef PRODUCT - static elapsedTimer _timer; // measures time between ticks - static int _ticks; // total number of ticks - static int _intervalHistogram[max_interval]; // to check spacing of timer interrupts - public: - static void print_intervals(); -#endif // Only the WatcherThread can cause us to execute PeriodicTasks friend class WatcherThread; public: diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/thread.hpp --- a/src/hotspot/share/runtime/thread.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/thread.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -421,11 +421,21 @@ #ifdef ASSERT private: - bool _visited_for_critical_count; + volatile uint64_t _visited_for_critical_count; public: - void set_visited_for_critical_count(bool z) { _visited_for_critical_count = z; } - bool was_visited_for_critical_count() const { return _visited_for_critical_count; } + void set_visited_for_critical_count(uint64_t safepoint_id) { + assert(_visited_for_critical_count == 0, "Must be reset before set"); + assert((safepoint_id & 0x1) == 1, "Must be odd"); + _visited_for_critical_count = safepoint_id; + } + void reset_visited_for_critical_count(uint64_t safepoint_id) { + assert(_visited_for_critical_count == safepoint_id, "Was not visited"); + _visited_for_critical_count = 0; + } + bool was_visited_for_critical_count(uint64_t safepoint_id) const { + return _visited_for_critical_count == safepoint_id; + } #endif public: diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/vmThread.cpp --- a/src/hotspot/share/runtime/vmThread.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/vmThread.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -458,6 +458,8 @@ void VMThread::loop() { assert(_cur_vm_operation == NULL, "no current one should be executing"); + SafepointSynchronize::init(_vm_thread); + while(true) { VM_Operation* safepoint_ops = NULL; // diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/runtime/vm_version.cpp --- a/src/hotspot/share/runtime/vm_version.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/runtime/vm_version.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -230,13 +230,7 @@ #define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER) #endif #elif defined(__SUNPRO_CC) - #if __SUNPRO_CC == 0x420 - #define HOTSPOT_BUILD_COMPILER "Workshop 4.2" - #elif __SUNPRO_CC == 0x500 - #define HOTSPOT_BUILD_COMPILER "Workshop 5.0 compat=" XSTR(__SUNPRO_CC_COMPAT) - #elif __SUNPRO_CC == 0x520 - #define HOTSPOT_BUILD_COMPILER "Workshop 5.2 compat=" XSTR(__SUNPRO_CC_COMPAT) - #elif __SUNPRO_CC == 0x580 + #if __SUNPRO_CC == 0x580 #define HOTSPOT_BUILD_COMPILER "Workshop 5.8" #elif __SUNPRO_CC == 0x590 #define HOTSPOT_BUILD_COMPILER "Workshop 5.9" @@ -249,6 +243,8 @@ #else #define HOTSPOT_BUILD_COMPILER "unknown Workshop:" XSTR(__SUNPRO_CC) #endif + #elif defined(__clang_version__) + #define HOTSPOT_BUILD_COMPILER "clang " __VERSION__ #elif defined(__GNUC__) #define HOTSPOT_BUILD_COMPILER "gcc " __VERSION__ #elif defined(__IBMCPP__) diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/services/classLoadingService.cpp --- a/src/hotspot/share/services/classLoadingService.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/services/classLoadingService.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -137,11 +137,6 @@ _class_methods_size->inc(-methods->at(i)->size()); } } - - if (log_is_enabled(Info, class, unload)) { - ResourceMark rm; - log_info(class, unload)("unloading class %s " INTPTR_FORMAT , k->external_name(), p2i(k)); - } } void ClassLoadingService::notify_class_loaded(InstanceKlass* k, bool shared_class) { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/services/memReporter.cpp --- a/src/hotspot/share/services/memReporter.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/services/memReporter.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -704,9 +704,15 @@ void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early, const MallocSite* current) const { - assert(early->flag() == current->flag(), "Must be the same memory type"); - diff_malloc_site(current->call_stack(), current->size(), current->count(), - early->size(), early->count(), early->flag()); + if (early->flag() != current->flag()) { + // If malloc site type changed, treat it as deallocation of old type and + // allocation of new type. + old_malloc_site(early); + new_malloc_site(current); + } else { + diff_malloc_site(current->call_stack(), current->size(), current->count(), + early->size(), early->count(), early->flag()); + } } void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_t current_size, diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/services/runtimeService.cpp --- a/src/hotspot/share/services/runtimeService.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/services/runtimeService.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/classLoader.hpp" #include "logging/log.hpp" +#include "runtime/timer.hpp" #include "runtime/vm_version.hpp" #include "services/attachListener.hpp" #include "services/management.hpp" @@ -40,7 +41,9 @@ PerfCounter* RuntimeService::_total_safepoints = NULL; PerfCounter* RuntimeService::_safepoint_time_ticks = NULL; PerfCounter* RuntimeService::_application_time_ticks = NULL; -double RuntimeService::_last_safepoint_sync_time_sec = 0.0; +jlong RuntimeService::_last_safepoint_sync_time_ns = 0; +jlong RuntimeService::_last_safepoint_end_time_ns = 0; +jlong RuntimeService::_last_app_time_ns = 0; void RuntimeService::init() { @@ -89,12 +92,14 @@ // Print the time interval in which the app was executing if (_app_timer.is_updated()) { - log_info(safepoint)("Application time: %3.7f seconds", last_application_time_sec()); + _last_app_time_ns = _app_timer.ticks_since_update(); + log_info(safepoint)("Application time: %3.7f seconds", TimeHelper::counter_to_seconds(_last_app_time_ns)); } // update the time stamp to begin recording safepoint time + _last_safepoint_sync_time_ns = 0; + _last_safepoint_end_time_ns = 0; _safepoint_timer.update(); - _last_safepoint_sync_time_sec = 0.0; if (UsePerfData) { _total_safepoints->inc(); if (_app_timer.is_updated()) { @@ -107,18 +112,24 @@ if (UsePerfData) { _sync_time_ticks->inc(_safepoint_timer.ticks_since_update()); } - if (log_is_enabled(Info, safepoint)) { - _last_safepoint_sync_time_sec = last_safepoint_time_sec(); + if (log_is_enabled(Info, safepoint) || log_is_enabled(Info, safepoint, stats)) { + _last_safepoint_sync_time_ns = _safepoint_timer.ticks_since_update(); } } void RuntimeService::record_safepoint_end() { HS_PRIVATE_SAFEPOINT_END(); - // Print the time interval for which the app was stopped - // during the current safepoint operation. - log_info(safepoint)("Total time for which application threads were stopped: %3.7f seconds, Stopping threads took: %3.7f seconds", - last_safepoint_time_sec(), _last_safepoint_sync_time_sec); + // Logging of safepoint+stats=info needs _last_safepoint_end_time_ns to be set. + // Logging of safepoint=info needs _last_safepoint_end_time_ns for following log. + if (log_is_enabled(Info, safepoint) || log_is_enabled(Info, safepoint, stats)) { + _last_safepoint_end_time_ns = _safepoint_timer.ticks_since_update(); + log_info(safepoint)( + "Total time for which application threads were stopped: %3.7f seconds, " + "Stopping threads took: %3.7f seconds", + TimeHelper::counter_to_seconds(_last_safepoint_end_time_ns), + TimeHelper::counter_to_seconds(_last_safepoint_sync_time_ns)); + } // update the time stamp to begin recording app time _app_timer.update(); @@ -127,6 +138,25 @@ } } +void RuntimeService::record_safepoint_epilog(const char* operation_name) { + if (!log_is_enabled(Info, safepoint, stats)) { + return; + } + + log_info(safepoint, stats)( + "Safepoint \"%s\", " + "Time since last: " JLONG_FORMAT " ns; " + "Reaching safepoint: " JLONG_FORMAT " ns; " + "At safepoint: " JLONG_FORMAT " ns; " + "Total: " JLONG_FORMAT " ns", + operation_name, + _last_app_time_ns, + _last_safepoint_sync_time_ns, + _last_safepoint_end_time_ns - _last_safepoint_sync_time_ns, + _last_safepoint_end_time_ns + ); +} + void RuntimeService::record_application_start() { // update the time stamp to begin recording app time _app_timer.update(); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/services/runtimeService.hpp --- a/src/hotspot/share/services/runtimeService.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/services/runtimeService.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -37,7 +37,9 @@ static TimeStamp _safepoint_timer; static TimeStamp _app_timer; - static double _last_safepoint_sync_time_sec; + static jlong _last_safepoint_sync_time_ns; + static jlong _last_safepoint_end_time_ns; + static jlong _last_app_time_ns; public: static void init(); @@ -47,13 +49,11 @@ static jlong safepoint_time_ms(); static jlong application_time_ms(); - static double last_safepoint_time_sec() { return _safepoint_timer.seconds(); } - static double last_application_time_sec() { return _app_timer.seconds(); } - // callbacks static void record_safepoint_begin() NOT_MANAGEMENT_RETURN; static void record_safepoint_synchronized() NOT_MANAGEMENT_RETURN; static void record_safepoint_end() NOT_MANAGEMENT_RETURN; + static void record_safepoint_epilog(const char* operation_name) NOT_MANAGEMENT_RETURN; static void record_application_start() NOT_MANAGEMENT_RETURN; }; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/constantTag.hpp --- a/src/hotspot/share/utilities/constantTag.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/constantTag.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -100,6 +100,12 @@ bool is_dynamic_constant() const { return _tag == JVM_CONSTANT_Dynamic; } bool is_invoke_dynamic() const { return _tag == JVM_CONSTANT_InvokeDynamic; } + bool has_bootstrap() const { + return (_tag == JVM_CONSTANT_Dynamic || + _tag == JVM_CONSTANT_DynamicInError || + _tag == JVM_CONSTANT_InvokeDynamic); + } + bool is_loadable_constant() const { return ((_tag >= JVM_CONSTANT_Integer && _tag <= JVM_CONSTANT_String) || is_method_type() || is_method_handle() || is_dynamic_constant() || diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/debug.cpp --- a/src/hotspot/share/utilities/debug.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/debug.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -61,6 +61,7 @@ #include "utilities/vmError.hpp" #include +#include // Support for showing register content on asserts/guarantees. #ifdef CAN_SHOW_REGISTERS_ON_ASSERT @@ -244,6 +245,22 @@ context = g_assertion_context; } #endif // CAN_SHOW_REGISTERS_ON_ASSERT + +#ifdef ASSERT + if (detail_fmt != NULL && ExecutingUnitTests) { + // Special handling for the sake of gtest death tests which expect the assert + // message to be printed in one short line to stderr (see TEST_VM_ASSERT_MSG) and + // cannot be tweaked to accept our normal assert message. + va_list detail_args_copy; + va_copy(detail_args_copy, detail_args); + ::fputs("assert failed: ", stderr); + ::vfprintf(stderr, detail_fmt, detail_args_copy); + ::fputs("\n", stderr); + ::fflush(stderr); + va_end(detail_args_copy); + } +#endif + VMError::report_and_die(Thread::current_or_null(), context, file, line, error_msg, detail_fmt, detail_args); va_end(detail_args); } @@ -293,21 +310,6 @@ report_vm_error(file, line, "Unimplemented()"); } -#ifdef ASSERT -bool is_executing_unit_tests() { - return ExecutingUnitTests; -} - -void report_assert_msg(const char* msg, ...) { - va_list ap; - va_start(ap, msg); - - fprintf(stderr, "assert failed: %s\n", err_msg(FormatBufferDummy(), msg, ap).buffer()); - - va_end(ap); -} -#endif // ASSERT - void report_untested(const char* file, int line, const char* message) { #ifndef PRODUCT warning("Untested: %s in %s: %d\n", message, file, line); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/debug.hpp --- a/src/hotspot/share/utilities/debug.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/debug.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -54,9 +54,6 @@ do { \ if (!(p)) { \ TOUCH_ASSERT_POISON; \ - if (is_executing_unit_tests()) { \ - report_assert_msg(__VA_ARGS__); \ - } \ report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", __VA_ARGS__); \ BREAKPOINT; \ } \ @@ -157,16 +154,10 @@ // ATTRIBUTE_PRINTF works with gcc >= 4.8 and any other compiler. void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...) ATTRIBUTE_PRINTF(4, 5); -#ifdef ASSERT -void report_assert_msg(const char* msg, ...) ATTRIBUTE_PRINTF(1, 2); -#endif // ASSERT #else // GCC < 4.8 warns because of empty format string. Warning can not be switched off selectively. void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...); -#ifdef ASSERT -void report_assert_msg(const char* msg, ...); -#endif // ASSERT #endif void report_vm_status_error(const char* file, int line, const char* error_msg, int status, const char* detail); @@ -178,11 +169,6 @@ void report_unimplemented(const char* file, int line); void report_untested(const char* file, int line, const char* message); -#ifdef ASSERT -// unit test support -bool is_executing_unit_tests(); -#endif // ASSERT - void warning(const char* format, ...) ATTRIBUTE_PRINTF(1, 2); // Compile-time asserts. Cond must be a compile-time constant expression that diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/events.cpp --- a/src/hotspot/share/utilities/events.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/events.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, 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 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "memory/allocation.inline.hpp" +#include "oops/instanceKlass.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.inline.hpp" #include "runtime/osThread.hpp" @@ -35,8 +36,9 @@ EventLog* Events::_logs = NULL; StringEventLog* Events::_messages = NULL; -StringEventLog* Events::_exceptions = NULL; +ExtendedStringEventLog* Events::_exceptions = NULL; StringEventLog* Events::_redefinitions = NULL; +UnloadingEventLog* Events::_class_unloading = NULL; StringEventLog* Events::_deopt_messages = NULL; EventLog::EventLog() { @@ -65,8 +67,9 @@ void Events::init() { if (LogEvents) { _messages = new StringEventLog("Events"); - _exceptions = new StringEventLog("Internal exceptions"); + _exceptions = new ExtendedStringEventLog("Internal exceptions"); _redefinitions = new StringEventLog("Classes redefined"); + _class_unloading = new UnloadingEventLog("Classes unloaded"); _deopt_messages = new StringEventLog("Deoptimization events"); } } @@ -96,3 +99,16 @@ Events::log(NULL, "%s", _buffer.buffer()); } } + +void UnloadingEventLog::log(Thread* thread, InstanceKlass* ik) { + if (!should_log()) return; + + double timestamp = fetch_timestamp(); + // Unloading events are single threaded. + int index = compute_log_index(); + _records[index].thread = thread; + _records[index].timestamp = timestamp; + stringStream st = _records[index].data.stream(); + st.print("Unloading class " INTPTR_FORMAT " ", p2i(ik)); + ik->name()->print_value_on(&st); +} diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/events.hpp --- a/src/hotspot/share/utilities/events.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/events.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -135,39 +135,53 @@ }; // A simple wrapper class for fixed size text messages. -class StringLogMessage : public FormatBuffer<256> { +template +class FormatStringLogMessage : public FormatBuffer { public: // Wrap this buffer in a stringStream. stringStream stream() { - return stringStream(_buf, size()); + return stringStream(this->_buf, this->size()); } }; +typedef FormatStringLogMessage<256> StringLogMessage; +typedef FormatStringLogMessage<512> ExtendedStringLogMessage; // A simple ring buffer of fixed size text messages. -class StringEventLog : public EventLogBase { +template +class FormatStringEventLog : public EventLogBase< FormatStringLogMessage > { public: - StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase(name, count) {} + FormatStringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase< FormatStringLogMessage >(name, count) {} void logv(Thread* thread, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0) { - if (!should_log()) return; + if (!this->should_log()) return; - double timestamp = fetch_timestamp(); - MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); - int index = compute_log_index(); - _records[index].thread = thread; - _records[index].timestamp = timestamp; - _records[index].data.printv(format, ap); + double timestamp = this->fetch_timestamp(); + MutexLockerEx ml(&this->_mutex, Mutex::_no_safepoint_check_flag); + int index = this->compute_log_index(); + this->_records[index].thread = thread; + this->_records[index].timestamp = timestamp; + this->_records[index].data.printv(format, ap); } void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(3, 4) { va_list ap; va_start(ap, format); - logv(thread, format, ap); + this->logv(thread, format, ap); va_end(ap); } - }; +typedef FormatStringEventLog<256> StringEventLog; +typedef FormatStringEventLog<512> ExtendedStringEventLog; +class InstanceKlass; + +// Event log for class unloading events to materialize the class name in place in the log stream. +class UnloadingEventLog : public EventLogBase { + public: + UnloadingEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase(name, count) {} + + void log(Thread* thread, InstanceKlass* ik); +}; class Events : AllStatic { @@ -181,7 +195,7 @@ // A log for internal exception related messages, like internal // throws and implicit exceptions. - static StringEventLog* _exceptions; + static ExtendedStringEventLog* _exceptions; // Deoptization related messages static StringEventLog* _deopt_messages; @@ -189,6 +203,8 @@ // Redefinition related messages static StringEventLog* _redefinitions; + // Class unloading events + static UnloadingEventLog* _class_unloading; public: static void print_all(outputStream* out); @@ -203,6 +219,8 @@ static void log_redefinition(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + static void log_class_unloading(Thread* thread, InstanceKlass* ik); + static void log_deopt_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); // Register default loggers @@ -236,6 +254,12 @@ } } +inline void Events::log_class_unloading(Thread* thread, InstanceKlass* ik) { + if (LogEvents) { + _class_unloading->log(thread, ik); + } +} + inline void Events::log_deopt_message(Thread* thread, const char* format, ...) { if (LogEvents) { va_list ap; @@ -289,6 +313,13 @@ out->cr(); } +// Implement a printing routine for the ExtendedStringLogMessage +template <> +inline void EventLogBase::print(outputStream* out, ExtendedStringLogMessage& lm) { + out->print_raw(lm); + out->cr(); +} + // Place markers for the beginning and end up of a set of events. // These end up in the default log. class EventMark : public StackObj { diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/exceptions.cpp --- a/src/hotspot/share/utilities/exceptions.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/exceptions.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -411,7 +411,7 @@ // Pass through an Error, including BootstrapMethodError, any other form // of linkage error, or say ThreadDeath/OutOfMemoryError if (TraceMethodHandles) { - tty->print_cr("[constant/invoke]dynamic passes through an Error for " INTPTR_FORMAT, p2i((void *)exception)); + tty->print_cr("bootstrap method invocation wraps BSME around " INTPTR_FORMAT, p2i((void *)exception)); exception->print(); } return; diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/exceptions.hpp --- a/src/hotspot/share/utilities/exceptions.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/exceptions.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -237,7 +237,11 @@ // visible within the scope containing the THROW. Usually this is achieved by declaring the function // with a TRAPS argument. +#ifdef THIS_FILE +#define THREAD_AND_LOCATION THREAD, THIS_FILE, __LINE__ +#else #define THREAD_AND_LOCATION THREAD, __FILE__, __LINE__ +#endif #define THROW_OOP(e) \ { Exceptions::_throw_oop(THREAD_AND_LOCATION, e); return; } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/globalDefinitions_xlc.hpp --- a/src/hotspot/share/utilities/globalDefinitions_xlc.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/globalDefinitions_xlc.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,6 +1,6 @@ /* * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,51 +51,43 @@ #include +// __IBMCPP__ is not defined any more with xlclang++ +#ifdef __IBMCPP__ +#if __IBMCPP__ < 1200 +#error "xlc < 12 not supported" +#endif +#endif + +#ifndef _AIX +#error "missing AIX-specific definition _AIX" +#endif + // Use XLC compiler builtins instead of inline assembler #define USE_XLC_BUILTINS + #ifdef USE_XLC_BUILTINS #include - #if __IBMCPP__ < 1000 - // the funtion prototype for __dcbtst(void *) is missing in XLC V8.0 - // I could compile a little test, where I provided the prototype. - // The generated code was correct there. This is the prototype: - // extern "builtin" void __dcbtst (void *); - // For now we don't make use of it when compiling with XLC V8.0 - #else - // __IBMCPP__ >= 1000 - // XLC V10 provides the prototype for __dcbtst (void *); - #define USE_XLC_PREFETCH_WRITE_BUILTIN - #endif +// XLC V10 and higher provide the prototype for __dcbtst (void *); #endif // USE_XLC_BUILTINS // NULL vs NULL_WORD: -// On Linux NULL is defined as a special type '__null'. Assigning __null to -// integer variable will cause gcc warning. Use NULL_WORD in places where a -// pointer is stored as integer value. On some platforms, sizeof(intptr_t) > -// sizeof(void*), so here we want something which is integer type, but has the -// same size as a pointer. -#ifdef __GNUC__ - #error XLC and __GNUC__? -#else - #define NULL_WORD NULL -#endif +// Some platform/tool-chain combinations can't assign NULL to an integer +// type so we define NULL_WORD to use in those contexts. For xlc they are the same. +#define NULL_WORD NULL // AIX also needs a 64 bit NULL to work as a null address pointer. // Most system includes on AIX would define it as an int 0 if not already defined with one // exception: /usr/include/dirent.h will unconditionally redefine NULL to int 0 again. // In this case you need to copy the following defines to a position after #include -// (see jmv_aix.h). -#ifdef AIX - #include - #ifdef _LP64 - #undef NULL - #define NULL 0L - #else - #ifndef NULL - #define NULL 0 - #endif +#include +#ifdef _LP64 + #undef NULL + #define NULL 0L +#else + #ifndef NULL + #define NULL 0 #endif -#endif // AIX +#endif // Compiler-specific primitive types // All defs of int (uint16_6 etc) are defined in AIX' /usr/include/stdint.h @@ -108,21 +100,14 @@ typedef uint64_t julong; // checking for nanness -#ifdef AIX inline int g_isnan(float f) { return isnan(f); } inline int g_isnan(double f) { return isnan(f); } -#else -#error "missing platform-specific definition here" -#endif // Checking for finiteness - inline int g_isfinite(jfloat f) { return finite(f); } inline int g_isfinite(jdouble f) { return finite(f); } - // Wide characters - inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/utf8.cpp --- a/src/hotspot/share/utilities/utf8.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/utf8.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -228,7 +228,9 @@ *p = '\0'; } - +#ifndef PRODUCT +// converts a quoted ascii string back to utf8 +// no longer used, but could be useful to test output of UTF8::as_quoted_ascii const char* UTF8::from_quoted_ascii(const char* quoted_ascii_str) { const char *ptr = quoted_ascii_str; char* result = NULL; @@ -302,7 +304,7 @@ } return buffer; } - +#endif // !PRODUCT // Returns NULL if 'c' it not found. This only works as long // as 'c' is an ASCII character @@ -468,7 +470,6 @@ char* UNICODE::as_utf8(const jbyte* base, int length, char* buf, int buflen) { u_char* p = (u_char*)buf; - u_char* end = (u_char*)buf + buflen; for (int index = 0; index < length; index++) { jbyte c = base[index]; int sz = utf8_size(c); diff -r 4964feb6d75d -r de9dd71ef18c src/hotspot/share/utilities/utf8.hpp --- a/src/hotspot/share/utilities/utf8.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/src/hotspot/share/utilities/utf8.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -54,9 +54,11 @@ // converts a utf8 string to quoted ascii static void as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen); +#ifndef PRODUCT // converts a quoted ascii string to utf8 string. returns the original // string unchanged if nothing needs to be done. static const char* from_quoted_ascii(const char* quoted_ascii_string); +#endif // decodes the current utf8 character, stores the result in value, // and returns the end of the current utf8 chararacter. diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/aix/native/libnet/aix_close.c --- a/src/java.base/aix/native/libnet/aix_close.c Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/aix/native/libnet/aix_close.c Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, SAP SE and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -429,10 +429,6 @@ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); } -int NET_WriteV(int s, const struct iovec * vector, int count) { - BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); -} - int NET_SendTo(int s, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen) { BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/linux/native/libnet/linux_close.c --- a/src/java.base/linux/native/libnet/linux_close.c Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/linux/native/libnet/linux_close.c Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -386,10 +386,6 @@ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); } -int NET_WriteV(int s, const struct iovec * vector, int count) { - BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); -} - int NET_SendTo(int s, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen) { BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/macosx/native/libnet/bsd_close.c --- a/src/java.base/macosx/native/libnet/bsd_close.c Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/macosx/native/libnet/bsd_close.c Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -390,10 +390,6 @@ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); } -int NET_WriteV(int s, const struct iovec * vector, int count) { - BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); -} - int NET_SendTo(int s, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen) { BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -61,6 +61,9 @@ // can only be returned by the doFinal(...) call. private static final int MAX_BUF_SIZE = Integer.MAX_VALUE; + // data size when buffer is divided up to aid in intrinsics + private static final int TRIGGERLEN = 65536; // 64k + // buffer for AAD data; if null, meaning update has been called private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); private int sizeOfAAD = 0; @@ -380,12 +383,10 @@ // Utility to process the last block; used by encryptFinal and decryptFinal void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs, boolean isEncrypt) throws IllegalBlockSizeException { - // process data in 'in' - gctrPAndC.doFinal(in, inOfs, len, out, outOfs); - processed += len; - byte[] ct; int ctOfs; + int ilen = len; // internal length + if (isEncrypt) { ct = out; ctOfs = outOfs; @@ -393,14 +394,38 @@ ct = in; ctOfs = inOfs; } + + // Divide up larger data sizes to trigger CTR & GHASH intrinsic quicker + if (len > TRIGGERLEN) { + int i = 0; + int tlen; // incremental lengths + // 96bit CTR x86 intrinsic + final int plen = AES_BLOCK_SIZE * 6; + // arbitrary formula to aid intrinsic without reaching buffer end + final int count = len / 1024; + + while (count > i) { + tlen = gctrPAndC.update(in, inOfs, plen, out, outOfs); + ghashAllToS.update(ct, ctOfs, tlen); + inOfs += tlen; + outOfs += tlen; + ctOfs += tlen; + i++; + } + ilen -= count * plen; + processed += count * plen; + } + + gctrPAndC.doFinal(in, inOfs, ilen, out, outOfs); + processed += ilen; + int lastLen = len % AES_BLOCK_SIZE; if (lastLen != 0) { ghashAllToS.update(ct, ctOfs, len - lastLen); - byte[] padded = - expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen); - ghashAllToS.update(padded); + ghashAllToS.update( + expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen)); } else { - ghashAllToS.update(ct, ctOfs, len); + ghashAllToS.update(ct, ctOfs, ilen); } } @@ -562,15 +587,19 @@ System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes); len -= tagLenBytes; - if (len > 0) { - ibuffer.write(in, inOfs, len); - } + // If decryption is in-place or there is buffered "ibuffer" data, copy + // the "in" byte array into the ibuffer before proceeding. + if (in == out || ibuffer.size() > 0) { + if (len > 0) { + ibuffer.write(in, inOfs, len); + } - // refresh 'in' to all buffered-up bytes - in = ibuffer.toByteArray(); - inOfs = 0; - len = in.length; - ibuffer.reset(); + // refresh 'in' to all buffered-up bytes + in = ibuffer.toByteArray(); + inOfs = 0; + len = in.length; + ibuffer.reset(); + } if (len > 0) { doLastBlock(in, inOfs, len, out, outOfs, false); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java --- a/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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,21 +42,6 @@ super(); } - // preferred constructor to enable FIPS mode at runtime - public Provider(java.security.Provider cryptoProvider) { - super(cryptoProvider); - } - - // constructor to enable FIPS mode from java.security file - public Provider(String cryptoProvider) { - super(cryptoProvider); - } - - // public for now, but we may want to change it or not document it. - public static synchronized boolean isFIPS() { - return SunJSSE.isFIPS(); - } - /** * Installs the JSSE provider. */ diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/java/util/HashMap.java --- a/src/java.base/share/classes/java/util/HashMap.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/java/util/HashMap.java Sun Feb 17 12:21:11 2019 +0000 @@ -501,9 +501,14 @@ (int)ft : MAXIMUM_CAPACITY); if (t > threshold) threshold = tableSizeFor(t); + } else { + // Because of linked-list bucket constraints, we cannot + // expand all at once, but can reduce total resize + // effort by repeated doubling now vs later + while (s > threshold && table.length < MAXIMUM_CAPACITY) + resize(); } - else if (s > threshold) - resize(); + for (Map.Entry e : m.entrySet()) { K key = e.getKey(); V value = e.getValue(); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java --- a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Sun Feb 17 12:21:11 2019 +0000 @@ -98,12 +98,11 @@ * } * }} * - * Here, each worker thread processes a row of the matrix then waits at the - * barrier until all rows have been processed. When all rows are processed - * the supplied {@link Runnable} barrier action is executed and merges the - * rows. If the merger - * determines that a solution has been found then {@code done()} will return - * {@code true} and each worker will terminate. + * Here, each worker thread processes a row of the matrix, then waits at the + * barrier until all rows have been processed. When all rows are processed the + * supplied {@link Runnable} barrier action is executed and merges the rows. + * If the merger determines that a solution has been found then {@code done()} + * will return {@code true} and each worker will terminate. * *

If the barrier action does not rely on the parties being suspended when * it is executed, then any of the threads in the party could execute that @@ -132,6 +131,7 @@ * corresponding {@code await()} in other threads. * * @see CountDownLatch + * @see Phaser * * @author Doug Lea * @since 1.5 @@ -214,18 +214,17 @@ int index = --count; if (index == 0) { // tripped - boolean ranAction = false; - try { - final Runnable command = barrierCommand; - if (command != null) + Runnable command = barrierCommand; + if (command != null) { + try { command.run(); - ranAction = true; - nextGeneration(); - return 0; - } finally { - if (!ranAction) + } catch (Throwable ex) { breakBarrier(); + throw ex; + } } + nextGeneration(); + return 0; } // loop until tripped, broken, interrupted, or timed out diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Sun Feb 17 12:21:11 2019 +0000 @@ -445,8 +445,7 @@ * if to its current value). This would be extremely costly. So * we relax it in several ways: (1) Producers only signal when * their queue is possibly empty at some point during a push - * operation (which requires conservatively checking size zero or - * one to cover races). (2) Other workers propagate this signal + * operation. (2) Other workers propagate this signal * when they find tasks in a queue with size greater than one. (3) * Workers only enqueue after scanning (see below) and not finding * any tasks. (4) Rather than CASing ctl to its current value in @@ -762,10 +761,8 @@ /** * The maximum number of top-level polls per worker before - * checking other queues, expressed as a bit shift to, in effect, - * multiply by pool size, and then use as random value mask, so - * average bound is about poolSize*(1< task) { ForkJoinTask[] a; - int s = top, d, cap, m; + int s = top, d = s - base, cap, m; ForkJoinPool p = pool; if ((a = array) != null && (cap = a.length) > 0) { QA.setRelease(a, (m = cap - 1) & s, task); top = s + 1; - if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 && - p != null) { // size 0 or 1 - VarHandle.fullFence(); - p.signalWork(); + if (d == m) + growArray(false); + else if (QA.getAcquire(a, m & (s - 1)) == null && p != null) { + VarHandle.fullFence(); // was empty + p.signalWork(null); } - else if (d == m) - growArray(false); } } @@ -863,16 +859,16 @@ final boolean lockedPush(ForkJoinTask task) { ForkJoinTask[] a; boolean signal = false; - int s = top, b = base, cap, d; + int s = top, d = s - base, cap, m; if ((a = array) != null && (cap = a.length) > 0) { - a[(cap - 1) & s] = task; + a[(m = (cap - 1)) & s] = task; top = s + 1; - if (b - s + cap - 1 == 0) + if (d == m) growArray(true); else { phase = 0; // full volatile unlock - if (((s - base) & ~1) == 0) // size 0 or 1 - signal = true; + if (a[m & (s - 1)] == null) + signal = true; // was empty } } return signal; @@ -1014,25 +1010,30 @@ * queue, up to bound n (to avoid infinite unfairness). */ final void topLevelExec(ForkJoinTask t, WorkQueue q, int n) { - if (t != null && q != null) { // hoist checks - int nstolen = 1; - for (;;) { + int nstolen = 1; + for (int j = 0;;) { + if (t != null) t.doExec(); - if (n-- < 0) + if (j++ <= n) + t = nextLocalTask(); + else { + j = 0; + t = null; + } + if (t == null) { + if (q != null && (t = q.poll()) != null) { + ++nstolen; + j = 0; + } + else if (j != 0) break; - else if ((t = nextLocalTask()) == null) { - if ((t = q.poll()) == null) - break; - else - ++nstolen; - } } - ForkJoinWorkerThread thread = owner; - nsteals += nstolen; - source = 0; - if (thread != null) - thread.afterTopLevelExec(); } + ForkJoinWorkerThread thread = owner; + nsteals += nstolen; + source = 0; + if (thread != null) + thread.afterTopLevelExec(); } /** @@ -1455,7 +1456,7 @@ if (!tryTerminate(false, false) && // possibly replace worker w != null && w.array != null) // avoid repeated failures - signalWork(); + signalWork(null); if (ex == null) // help clean on way out ForkJoinTask.helpExpungeStaleExceptions(); @@ -1465,8 +1466,9 @@ /** * Tries to create or release a worker if too few are running. + * @param q if non-null recheck if empty on CAS failure */ - final void signalWork() { + final void signalWork(WorkQueue q) { for (;;) { long c; int sp; WorkQueue[] ws; int i; WorkQueue v; if ((c = ctl) >= 0L) // enough workers @@ -1493,6 +1495,8 @@ LockSupport.unpark(vt); break; } + else if (q != null && q.isEmpty()) // no need to retry + break; } } } @@ -1613,19 +1617,24 @@ else if (rc <= 0 && (md & SHUTDOWN) != 0 && tryTerminate(false, false)) break; // quiescent shutdown - else if (rc <= 0 && pred != 0 && phase == (int)c) { - long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred); - long d = keepAlive + System.currentTimeMillis(); - LockSupport.parkUntil(this, d); - if (ctl == c && // drop on timeout if all idle - d - System.currentTimeMillis() <= TIMEOUT_SLOP && - CTL.compareAndSet(this, c, nc)) { - w.phase = QUIET; - break; + else if (w.phase < 0) { + if (rc <= 0 && pred != 0 && phase == (int)c) { + long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred); + long d = keepAlive + System.currentTimeMillis(); + LockSupport.parkUntil(this, d); + if (ctl == c && // drop on timeout if all idle + d - System.currentTimeMillis() <= TIMEOUT_SLOP && + CTL.compareAndSet(this, c, nc)) { + w.phase = QUIET; + break; + } + } + else { + LockSupport.park(this); + if (w.phase < 0) // one spurious wakeup check + LockSupport.park(this); } } - else if (w.phase < 0) - LockSupport.park(this); // OK if spuriously woken w.source = 0; // disable signal } } @@ -1651,10 +1660,10 @@ QA.compareAndSet(a, k, t, null)) { q.base = b; w.source = qid; - if (q.top - b > 0) - signalWork(); + if (a[(cap - 1) & b] != null) + signalWork(q); // help signal if more tasks w.topLevelExec(t, q, // random fairness bound - r & ((n << TOP_BOUND_SHIFT) - 1)); + (r | (1 << TOP_BOUND_SHIFT)) & SMASK); } } return true; @@ -1900,7 +1909,7 @@ r = ThreadLocalRandom.advanceProbe(r); else { if (q.lockedPush(task)) - signalWork(); + signalWork(null); return; } } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Sun Feb 17 12:21:11 2019 +0000 @@ -236,7 +236,8 @@ @Override // paranoically public void setContextClassLoader(ClassLoader cl) { - throw new SecurityException("setContextClassLoader"); + if (cl != null && ClassLoader.getSystemClassLoader() != cl) + throw new SecurityException("setContextClassLoader"); } } } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/Alert.java --- a/src/java.base/share/classes/sun/security/ssl/Alert.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/Alert.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -48,7 +48,7 @@ HANDSHAKE_FAILURE ((byte)40, "handshake_failure", true), NO_CERTIFICATE ((byte)41, "no_certificate", true), BAD_CERTIFICATE ((byte)42, "bad_certificate", true), - UNSUPPORTED_CERTIFCATE ((byte)43, "unsupported_certificate", true), + UNSUPPORTED_CERTIFICATE ((byte)43, "unsupported_certificate", true), CERTIFICATE_REVOKED ((byte)44, "certificate_revoked", true), CERTIFICATE_EXPIRED ((byte)45, "certificate_expired", true), CERTIFICATE_UNKNOWN ((byte)46, "certificate_unknown", true), diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/Authenticator.java --- a/src/java.base/share/classes/sun/security/ssl/Authenticator.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/Authenticator.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -484,7 +484,7 @@ throw new RuntimeException("Unknown MacAlg " + macAlg); } - Mac m = JsseJce.getMac(algorithm); + Mac m = Mac.getInstance(algorithm); m.init(key); this.macAlg = macAlg; this.mac = m; diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/CertificateMessage.java --- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -717,6 +717,13 @@ alert = chc.staplingActive ? Alert.BAD_CERT_STATUS_RESPONSE : Alert.CERTIFICATE_UNKNOWN; + } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { + alert = Alert.UNSUPPORTED_CERTIFICATE; + } else if (reason == BasicReason.EXPIRED) { + alert = Alert.CERTIFICATE_EXPIRED; + } else if (reason == BasicReason.INVALID_SIGNATURE || + reason == BasicReason.NOT_YET_VALID) { + alert = Alert.BAD_CERTIFICATE; } } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/CertificateVerify.java --- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -196,13 +196,13 @@ Signature signer = null; switch (algorithm) { case "RSA": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_RAWRSA); break; case "DSA": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_RAWDSA); break; case "EC": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_RAWECDSA); break; default: throw new SignatureException("Unrecognized algorithm: " @@ -439,13 +439,13 @@ Signature signer = null; switch (algorithm) { case "RSA": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_RAWRSA); break; case "DSA": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_RAWDSA); break; case "EC": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_RAWECDSA); break; default: throw new SignatureException("Unrecognized algorithm: " diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/ClientHello.java --- a/src/java.base/share/classes/sun/security/ssl/ClientHello.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/ClientHello.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -519,7 +519,7 @@ if (session != null && identityAlg != null) { String sessionIdentityAlg = session.getIdentificationProtocol(); - if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { SSLLogger.finest("Can't resume, endpoint id" + @@ -803,8 +803,13 @@ shc.sslConfig.getEnabledExtensions( SSLHandshake.CLIENT_HELLO); - ClientHelloMessage chm = - new ClientHelloMessage(shc, message, enabledExtensions); + ClientHelloMessage chm; + try { + chm = new ClientHelloMessage(shc, message, enabledExtensions); + } catch (Exception e) { + throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "ClientHelloMessage failure", e); + } if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine("Consuming ClientHello handshake message", chm); } @@ -1036,7 +1041,7 @@ if (resumingSession && identityAlg != null) { String sessionIdentityAlg = previous.getIdentificationProtocol(); - if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { SSLLogger.finest("Can't resume, endpoint id" + diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -280,7 +280,7 @@ DHPublicKeySpec spec = new DHPublicKeySpec( new BigInteger(1, ckem.y), params.getP(), params.getG()); - KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); + KeyFactory kf = KeyFactory.getInstance("DiffieHellman"); DHPublicKey peerPublicKey = (DHPublicKey)kf.generatePublic(spec); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -87,7 +87,7 @@ return null; } - KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); + KeyFactory kf = KeyFactory.getInstance("DiffieHellman"); DHPublicKeySpec spec = new DHPublicKeySpec( new BigInteger(1, encodedPublic), params.getP(), params.getG()); @@ -106,7 +106,7 @@ DHEPossession(NamedGroup namedGroup, SecureRandom random) { try { KeyPairGenerator kpg = - JsseJce.getKeyPairGenerator("DiffieHellman"); + KeyPairGenerator.getInstance("DiffieHellman"); DHParameterSpec params = (DHParameterSpec)namedGroup.getParameterSpec(); kpg.initialize(params, random); @@ -129,7 +129,7 @@ PredefinedDHParameterSpecs.definedParams.get(keyLength); try { KeyPairGenerator kpg = - JsseJce.getKeyPairGenerator("DiffieHellman"); + KeyPairGenerator.getInstance("DiffieHellman"); if (params != null) { kpg.initialize(params, random); } else { @@ -155,7 +155,7 @@ DHEPossession(DHECredentials credentials, SecureRandom random) { try { KeyPairGenerator kpg = - JsseJce.getKeyPairGenerator("DiffieHellman"); + KeyPairGenerator.getInstance("DiffieHellman"); kpg.initialize(credentials.popPublicKey.getParams(), random); KeyPair kp = generateDHKeyPair(kpg); if (kp == null) { @@ -208,7 +208,7 @@ params.getP(), params.getG()); } try { - KeyFactory factory = JsseJce.getKeyFactory("DiffieHellman"); + KeyFactory factory = KeyFactory.getInstance("DiffieHellman"); return factory.getKeySpec(key, DHPublicKeySpec.class); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { // unlikely @@ -473,7 +473,7 @@ private SecretKey t12DeriveKey(String algorithm, AlgorithmParameterSpec params) throws IOException { try { - KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman"); + KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman"); ka.init(localPrivateKey); ka.doPhase(peerPublicKey, true); SecretKey preMasterSecret = @@ -499,7 +499,7 @@ private SecretKey t13DeriveKey(String algorithm, AlgorithmParameterSpec params) throws IOException { try { - KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman"); + KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman"); ka.init(localPrivateKey); ka.doPhase(peerPublicKey, true); SecretKey sharedSecret = diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -420,7 +420,7 @@ Signature signer = null; switch (keyAlgorithm) { case "DSA": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_DSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_DSA); break; case "RSA": signer = RSASignature.getInstance(); @@ -524,7 +524,7 @@ // check constraints of EC PublicKey DHPublicKey publicKey; try { - KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); + KeyFactory kf = KeyFactory.getInstance("DiffieHellman"); DHPublicKeySpec spec = new DHPublicKeySpec( new BigInteger(1, skem.y), new BigInteger(1, skem.p), diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -49,6 +49,7 @@ import sun.security.ssl.SupportedGroupsExtension.NamedGroup; import sun.security.ssl.X509Authentication.X509Credentials; import sun.security.ssl.X509Authentication.X509Possession; +import sun.security.util.ECUtil; import sun.security.util.HexDumpEncoder; /** @@ -78,7 +79,7 @@ ECPoint point = publicKey.getW(); ECParameterSpec params = publicKey.getParams(); - encodedPoint = JsseJce.encodePoint(point, params.getCurve()); + encodedPoint = ECUtil.encodePoint(point, params.getCurve()); } ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext, @@ -99,10 +100,10 @@ try { ECParameterSpec params = publicKey.getParams(); ECPoint point = - JsseJce.decodePoint(encodedPoint, params.getCurve()); + ECUtil.decodePoint(encodedPoint, params.getCurve()); ECPublicKeySpec spec = new ECPublicKeySpec(point, params); - KeyFactory kf = JsseJce.getKeyFactory("EC"); + KeyFactory kf = KeyFactory.getInstance("EC"); ECPublicKey peerPublicKey = (ECPublicKey)kf.generatePublic(spec); @@ -319,10 +320,10 @@ // create the credentials try { ECPoint point = - JsseJce.decodePoint(cke.encodedPoint, params.getCurve()); + ECUtil.decodePoint(cke.encodedPoint, params.getCurve()); ECPublicKeySpec spec = new ECPublicKeySpec(point, params); - KeyFactory kf = JsseJce.getKeyFactory("EC"); + KeyFactory kf = KeyFactory.getInstance("EC"); ECPublicKey peerPublicKey = (ECPublicKey)kf.generatePublic(spec); @@ -493,10 +494,10 @@ // create the credentials try { ECPoint point = - JsseJce.decodePoint(cke.encodedPoint, params.getCurve()); + ECUtil.decodePoint(cke.encodedPoint, params.getCurve()); ECPublicKeySpec spec = new ECPublicKeySpec(point, params); - KeyFactory kf = JsseJce.getKeyFactory("EC"); + KeyFactory kf = KeyFactory.getInstance("EC"); ECPublicKey peerPublicKey = (ECPublicKey)kf.generatePublic(spec); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -85,14 +85,14 @@ } ECParameterSpec parameters = - JsseJce.getECParameterSpec(namedGroup.oid); + ECUtil.getECParameterSpec(null, namedGroup.oid); if (parameters == null) { return null; } - ECPoint point = JsseJce.decodePoint( + ECPoint point = ECUtil.decodePoint( encodedPoint, parameters.getCurve()); - KeyFactory factory = JsseJce.getKeyFactory("EC"); + KeyFactory factory = KeyFactory.getInstance("EC"); ECPublicKey publicKey = (ECPublicKey)factory.generatePublic( new ECPublicKeySpec(point, parameters)); return new ECDHECredentials(publicKey, namedGroup); @@ -106,7 +106,7 @@ ECDHEPossession(NamedGroup namedGroup, SecureRandom random) { try { - KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); ECGenParameterSpec params = (ECGenParameterSpec)namedGroup.getParameterSpec(); kpg.initialize(params, random); @@ -124,7 +124,7 @@ ECDHEPossession(ECDHECredentials credentials, SecureRandom random) { ECParameterSpec params = credentials.popPublicKey.getParams(); try { - KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(params, random); KeyPair kp = kpg.generateKeyPair(); privateKey = kp.getPrivate(); @@ -149,7 +149,7 @@ PublicKey peerPublicKey) throws SSLHandshakeException { try { - KeyAgreement ka = JsseJce.getKeyAgreement("ECDH"); + KeyAgreement ka = KeyAgreement.getInstance("ECDH"); ka.init(privateKey); ka.doPhase(peerPublicKey, true); return ka.generateSecret("TlsPremasterSecret"); @@ -165,8 +165,8 @@ try { ECParameterSpec params = publicKey.getParams(); ECPoint point = - JsseJce.decodePoint(encodedPoint, params.getCurve()); - KeyFactory kf = JsseJce.getKeyFactory("EC"); + ECUtil.decodePoint(encodedPoint, params.getCurve()); + KeyFactory kf = KeyFactory.getInstance("EC"); ECPublicKeySpec spec = new ECPublicKeySpec(point, params); PublicKey peerPublicKey = kf.generatePublic(spec); return getAgreedSecret(peerPublicKey); @@ -183,10 +183,10 @@ ECParameterSpec params = publicKey.getParams(); ECPoint point = - JsseJce.decodePoint(encodedPoint, params.getCurve()); + ECUtil.decodePoint(encodedPoint, params.getCurve()); ECPublicKeySpec spec = new ECPublicKeySpec(point, params); - KeyFactory kf = JsseJce.getKeyFactory("EC"); + KeyFactory kf = KeyFactory.getInstance("EC"); ECPublicKey pubKey = (ECPublicKey)kf.generatePublic(spec); // check constraints of ECPublicKey @@ -424,7 +424,7 @@ private SecretKey t12DeriveKey(String algorithm, AlgorithmParameterSpec params) throws IOException { try { - KeyAgreement ka = JsseJce.getKeyAgreement("ECDH"); + KeyAgreement ka = KeyAgreement.getInstance("ECDH"); ka.init(localPrivateKey); ka.doPhase(peerPublicKey, true); SecretKey preMasterSecret = @@ -451,7 +451,7 @@ private SecretKey t13DeriveKey(String algorithm, AlgorithmParameterSpec params) throws IOException { try { - KeyAgreement ka = JsseJce.getKeyAgreement("ECDH"); + KeyAgreement ka = KeyAgreement.getInstance("ECDH"); ka.init(localPrivateKey); ka.doPhase(peerPublicKey, true); SecretKey sharedSecret = diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -52,6 +52,7 @@ import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Credentials; import sun.security.ssl.X509Authentication.X509Possession; +import sun.security.util.ECUtil; import sun.security.util.HexDumpEncoder; /** @@ -120,7 +121,7 @@ publicKey = ecdhePossession.publicKey; ECParameterSpec params = publicKey.getParams(); ECPoint point = publicKey.getW(); - publicPoint = JsseJce.encodePoint(point, params.getCurve()); + publicPoint = ECUtil.encodePoint(point, params.getCurve()); this.namedGroup = NamedGroup.valueOf(params); if ((namedGroup == null) || (namedGroup.oid == null) ) { @@ -221,7 +222,7 @@ } ECParameterSpec parameters = - JsseJce.getECParameterSpec(namedGroup.oid); + ECUtil.getECParameterSpec(null, namedGroup.oid); if (parameters == null) { throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER, "No supported EC parameter: " + namedGroup); @@ -236,8 +237,8 @@ ECPublicKey ecPublicKey = null; try { ECPoint point = - JsseJce.decodePoint(publicPoint, parameters.getCurve()); - KeyFactory factory = JsseJce.getKeyFactory("EC"); + ECUtil.decodePoint(publicPoint, parameters.getCurve()); + KeyFactory factory = KeyFactory.getInstance("EC"); ecPublicKey = (ECPublicKey)factory.generatePublic( new ECPublicKeySpec(point, parameters)); } catch (NoSuchAlgorithmException | @@ -446,7 +447,7 @@ Signature signer = null; switch (keyAlgorithm) { case "EC": - signer = JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA); + signer = Signature.getInstance(JsseJce.SIGNATURE_ECDSA); break; case "RSA": signer = RSASignature.getInstance(); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/EphemeralKeyManager.java --- a/src/java.base/share/classes/sun/security/ssl/EphemeralKeyManager.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/EphemeralKeyManager.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -69,7 +69,7 @@ KeyPair kp = keys[index].getKeyPair(); if (kp == null) { try { - KeyPairGenerator kgen = JsseJce.getKeyPairGenerator("RSA"); + KeyPairGenerator kgen = KeyPairGenerator.getInstance("RSA"); kgen.initialize(length, random); keys[index] = new EphemeralKeyPair(kgen.genKeyPair()); kp = keys[index].getKeyPair(); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/Finished.java --- a/src/java.base/share/classes/sun/security/ssl/Finished.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/Finished.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -257,7 +257,7 @@ TlsPrfParameterSpec spec = new TlsPrfParameterSpec( masterSecretKey, tlsLabel, seed, 12, hashAlg.name, hashAlg.hashLength, hashAlg.blockSize); - KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg); + KeyGenerator kg = KeyGenerator.getInstance(prfAlg); kg.init(spec); SecretKey prfKey = kg.generateKey(); if (!"RAW".equals(prfKey.getFormat())) { @@ -309,7 +309,7 @@ TlsPrfParameterSpec spec = new TlsPrfParameterSpec( masterSecretKey, tlsLabel, seed, 12, hashAlg.name, hashAlg.hashLength, hashAlg.blockSize); - KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg); + KeyGenerator kg = KeyGenerator.getInstance(prfAlg); kg.init(spec); SecretKey prfKey = kg.generateKey(); if (!"RAW".equals(prfKey.getFormat())) { @@ -350,7 +350,7 @@ String hmacAlg = "Hmac" + hashAlg.name.replace("-", ""); try { - Mac hmac = JsseJce.getMac(hmacAlg); + Mac hmac = Mac.getInstance(hmacAlg); hmac.init(finishedSecret); return hmac.doFinal(context.handshakeHash.digest()); } catch (NoSuchAlgorithmException |InvalidKeyException ex) { diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/HKDF.java --- a/src/java.base/share/classes/sun/security/ssl/HKDF.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/HKDF.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -62,7 +62,7 @@ Objects.requireNonNull(hashAlg, "Must provide underlying HKDF Digest algorithm."); hmacAlg = "Hmac" + hashAlg.replace("-", ""); - hmacObj = JsseJce.getMac(hmacAlg); + hmacObj = Mac.getInstance(hmacAlg); hmacLen = hmacObj.getMacLength(); } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/HandshakeHash.java --- a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java Sun Feb 17 12:21:11 2019 +0000 @@ -29,6 +29,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.LinkedList; import javax.crypto.SecretKey; @@ -269,8 +270,13 @@ private final ByteArrayOutputStream baos; S30HandshakeHash(CipherSuite cipherSuite) { - this.mdMD5 = JsseJce.getMessageDigest("MD5"); - this.mdSHA = JsseJce.getMessageDigest("SHA"); + try { + this.mdMD5 = MessageDigest.getInstance("MD5"); + this.mdSHA = MessageDigest.getInstance("SHA"); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "Hash algorithm MD5 or SHA is not available", nsae); + } boolean hasArchived = false; if (mdMD5 instanceof Cloneable) { @@ -379,7 +385,12 @@ "MessageDigest does no support clone operation"); } } else { - md5Clone = JsseJce.getMessageDigest("MD5"); + try { + md5Clone = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "Hash algorithm MD5 is not available", nsae); + } md5Clone.update(md5.archived()); } @@ -396,7 +407,12 @@ "MessageDigest does no support clone operation"); } } else { - shaClone = JsseJce.getMessageDigest("SHA"); + try { + shaClone = MessageDigest.getInstance("SHA"); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "Hash algorithm SHA is not available", nsae); + } shaClone.update(sha.archived()); } @@ -447,8 +463,15 @@ private final ByteArrayOutputStream baos; T10HandshakeHash(CipherSuite cipherSuite) { - MessageDigest mdMD5 = JsseJce.getMessageDigest("MD5"); - MessageDigest mdSHA = JsseJce.getMessageDigest("SHA"); + MessageDigest mdMD5; + MessageDigest mdSHA; + try { + mdMD5 = MessageDigest.getInstance("MD5"); + mdSHA = MessageDigest.getInstance("SHA"); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "Hash algorithm MD5 or SHA is not available", nsae); + } boolean hasArchived = false; if (mdMD5 instanceof Cloneable) { @@ -514,8 +537,15 @@ private final ByteArrayOutputStream baos; T12HandshakeHash(CipherSuite cipherSuite) { - MessageDigest md = - JsseJce.getMessageDigest(cipherSuite.hashAlg.name); + MessageDigest md; + try { + md = MessageDigest.getInstance(cipherSuite.hashAlg.name); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "Hash algorithm " + + cipherSuite.hashAlg.name + " is not available", nsae); + } + if (md instanceof Cloneable) { transcriptHash = new CloneableHash(md); this.baos = new ByteArrayOutputStream(); @@ -552,8 +582,15 @@ private final TranscriptHash transcriptHash; T13HandshakeHash(CipherSuite cipherSuite) { - MessageDigest md = - JsseJce.getMessageDigest(cipherSuite.hashAlg.name); + MessageDigest md; + try { + md = MessageDigest.getInstance(cipherSuite.hashAlg.name); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "Hash algorithm " + + cipherSuite.hashAlg.name + " is not available", nsae); + } + if (md instanceof Cloneable) { transcriptHash = new CloneableHash(md); } else { diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java --- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java Sun Feb 17 12:21:11 2019 +0000 @@ -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,6 +27,7 @@ import java.io.IOException; import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; import static sun.security.ssl.ClientHello.ClientHelloMessage; @@ -143,7 +144,13 @@ cookieVersion++; } - MessageDigest md = JsseJce.getMessageDigest("SHA-256"); + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "MessageDigest algorithm SHA-256 is not available", nsae); + } byte[] helloBytes = clientHello.getHelloCookieBytes(); md.update(helloBytes); byte[] cookie = md.digest(secret); // 32 bytes @@ -169,7 +176,13 @@ } } - MessageDigest md = JsseJce.getMessageDigest("SHA-256"); + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "MessageDigest algorithm SHA-256 is not available", nsae); + } byte[] helloBytes = clientHello.getHelloCookieBytes(); md.update(helloBytes); byte[] target = md.digest(secret); // 32 bytes @@ -234,8 +247,16 @@ cookieVersion++; // allow wrapped version number } - MessageDigest md = JsseJce.getMessageDigest( + MessageDigest md; + try { + md = MessageDigest.getInstance( context.negotiatedCipherSuite.hashAlg.name); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "MessageDigest algorithm " + + context.negotiatedCipherSuite.hashAlg.name + + " is not available", nsae); + } byte[] headerBytes = clientHello.getHeaderBytes(); md.update(headerBytes); byte[] headerCookie = md.digest(secret); @@ -300,7 +321,14 @@ } } - MessageDigest md = JsseJce.getMessageDigest(cs.hashAlg.name); + MessageDigest md; + try { + md = MessageDigest.getInstance(cs.hashAlg.name); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException( + "MessageDigest algorithm " + + cs.hashAlg.name + " is not available", nsae); + } byte[] headerBytes = clientHello.getHeaderBytes(); md.update(headerBytes); byte[] headerCookie = md.digest(secret); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/JsseJce.java --- a/src/java.base/share/classes/sun/security/ssl/JsseJce.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/JsseJce.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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,13 +29,7 @@ import java.security.*; import java.security.interfaces.RSAPublicKey; import java.security.spec.*; -import java.util.*; import javax.crypto.*; -import sun.security.jca.ProviderList; -import sun.security.jca.Providers; -import static sun.security.ssl.SunJSSE.cryptoProvider; -import sun.security.util.ECUtil; -import static sun.security.util.SecurityConstants.PROVIDER_VER; /** * This class contains a few static methods for interaction with the JCA/JCE @@ -47,54 +41,6 @@ static final boolean ALLOW_ECC = Utilities.getBooleanProperty("com.sun.net.ssl.enableECC", true); - private static final ProviderList fipsProviderList; - - static { - // force FIPS flag initialization - // Because isFIPS() is synchronized and cryptoProvider is not modified - // after it completes, this also eliminates the need for any further - // synchronization when accessing cryptoProvider - if (SunJSSE.isFIPS() == false) { - fipsProviderList = null; - } else { - // Setup a ProviderList that can be used by the trust manager - // during certificate chain validation. All the crypto must be - // from the FIPS provider, but we also allow the required - // certificate related services from the SUN provider. - Provider sun = Security.getProvider("SUN"); - if (sun == null) { - throw new RuntimeException - ("FIPS mode: SUN provider must be installed"); - } - Provider sunCerts = new SunCertificates(sun); - fipsProviderList = ProviderList.newList(cryptoProvider, sunCerts); - } - } - - private static final class SunCertificates extends Provider { - private static final long serialVersionUID = -3284138292032213752L; - - SunCertificates(final Provider p) { - super("SunCertificates", PROVIDER_VER, "SunJSSE internal"); - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - // copy certificate related services from the Sun provider - for (Map.Entry entry : p.entrySet()) { - String key = (String)entry.getKey(); - if (key.startsWith("CertPathValidator.") - || key.startsWith("CertPathBuilder.") - || key.startsWith("CertStore.") - || key.startsWith("CertificateFactory.")) { - put(key, entry.getValue()); - } - } - return null; - } - }); - } - } - /** * JCE transformation string for RSA with PKCS#1 v1.5 padding. * Can be used for encryption, decryption, signing, verifying. @@ -180,153 +126,6 @@ return EcAvailability.isAvailable; } - /** - * Return an JCE cipher implementation for the specified algorithm. - */ - static Cipher getCipher(String transformation) - throws NoSuchAlgorithmException { - try { - if (cryptoProvider == null) { - return Cipher.getInstance(transformation); - } else { - return Cipher.getInstance(transformation, cryptoProvider); - } - } catch (NoSuchPaddingException e) { - throw new NoSuchAlgorithmException(e); - } - } - - /** - * Return an JCA signature implementation for the specified algorithm. - * The algorithm string should be one of the constants defined - * in this class. - */ - static Signature getSignature(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return Signature.getInstance(algorithm); - } else { - // reference equality - if (algorithm == SIGNATURE_SSLRSA) { - // The SunPKCS11 provider currently does not support this - // special algorithm. We allow a fallback in this case because - // the SunJSSE implementation does the actual crypto using - // a NONEwithRSA signature obtained from the cryptoProvider. - if (cryptoProvider.getService("Signature", algorithm) == null) { - // Calling Signature.getInstance() and catching the - // exception would be cleaner, but exceptions are a little - // expensive. So we check directly via getService(). - try { - return Signature.getInstance(algorithm, "SunJSSE"); - } catch (NoSuchProviderException e) { - throw new NoSuchAlgorithmException(e); - } - } - } - return Signature.getInstance(algorithm, cryptoProvider); - } - } - - static KeyGenerator getKeyGenerator(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return KeyGenerator.getInstance(algorithm); - } else { - return KeyGenerator.getInstance(algorithm, cryptoProvider); - } - } - - static KeyPairGenerator getKeyPairGenerator(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return KeyPairGenerator.getInstance(algorithm); - } else { - return KeyPairGenerator.getInstance(algorithm, cryptoProvider); - } - } - - static KeyAgreement getKeyAgreement(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return KeyAgreement.getInstance(algorithm); - } else { - return KeyAgreement.getInstance(algorithm, cryptoProvider); - } - } - - static Mac getMac(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return Mac.getInstance(algorithm); - } else { - return Mac.getInstance(algorithm, cryptoProvider); - } - } - - static KeyFactory getKeyFactory(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return KeyFactory.getInstance(algorithm); - } else { - return KeyFactory.getInstance(algorithm, cryptoProvider); - } - } - - static AlgorithmParameters getAlgorithmParameters(String algorithm) - throws NoSuchAlgorithmException { - if (cryptoProvider == null) { - return AlgorithmParameters.getInstance(algorithm); - } else { - return AlgorithmParameters.getInstance(algorithm, cryptoProvider); - } - } - - static SecureRandom getSecureRandom() throws KeyManagementException { - if (cryptoProvider == null) { - return new SecureRandom(); - } - // Try "PKCS11" first. If that is not supported, iterate through - // the provider and return the first working implementation. - try { - return SecureRandom.getInstance("PKCS11", cryptoProvider); - } catch (NoSuchAlgorithmException e) { - // ignore - } - for (Provider.Service s : cryptoProvider.getServices()) { - if (s.getType().equals("SecureRandom")) { - try { - return SecureRandom.getInstance( - s.getAlgorithm(), cryptoProvider); - } catch (NoSuchAlgorithmException ee) { - // ignore - } - } - } - throw new KeyManagementException("FIPS mode: no SecureRandom " - + " implementation found in provider " + cryptoProvider.getName()); - } - - static MessageDigest getMD5() { - return getMessageDigest("MD5"); - } - - static MessageDigest getSHA() { - return getMessageDigest("SHA"); - } - - static MessageDigest getMessageDigest(String algorithm) { - try { - if (cryptoProvider == null) { - return MessageDigest.getInstance(algorithm); - } else { - return MessageDigest.getInstance(algorithm, cryptoProvider); - } - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException - ("Algorithm " + algorithm + " not available", e); - } - } - static int getRSAKeyLength(PublicKey key) { BigInteger modulus; if (key instanceof RSAPublicKey) { @@ -345,47 +144,13 @@ rsaKey.getPublicExponent()); } try { - KeyFactory factory = JsseJce.getKeyFactory("RSA"); + KeyFactory factory = KeyFactory.getInstance("RSA"); return factory.getKeySpec(key, RSAPublicKeySpec.class); } catch (Exception e) { throw new RuntimeException(e); } } - static ECParameterSpec getECParameterSpec(String namedCurveOid) { - return ECUtil.getECParameterSpec(cryptoProvider, namedCurveOid); - } - - static String getNamedCurveOid(ECParameterSpec params) { - return ECUtil.getCurveName(cryptoProvider, params); - } - - static ECPoint decodePoint(byte[] encoded, EllipticCurve curve) - throws java.io.IOException { - return ECUtil.decodePoint(encoded, curve); - } - - static byte[] encodePoint(ECPoint point, EllipticCurve curve) { - return ECUtil.encodePoint(point, curve); - } - - // In FIPS mode, set thread local providers; otherwise a no-op. - // Must be paired with endFipsProvider. - static Object beginFipsProvider() { - if (fipsProviderList == null) { - return null; - } else { - return Providers.beginThreadProviderList(fipsProviderList); - } - } - - static void endFipsProvider(Object o) { - if (fipsProviderList != null) { - Providers.endThreadProviderList((ProviderList)o); - } - } - - // lazy initialization holder class idiom for static default parameters // // See Effective Java Second Edition: Item 71. @@ -396,12 +161,12 @@ static { boolean mediator = true; try { - JsseJce.getSignature(SIGNATURE_ECDSA); - JsseJce.getSignature(SIGNATURE_RAWECDSA); - JsseJce.getKeyAgreement("ECDH"); - JsseJce.getKeyFactory("EC"); - JsseJce.getKeyPairGenerator("EC"); - JsseJce.getAlgorithmParameters("EC"); + Signature.getInstance(SIGNATURE_ECDSA); + Signature.getInstance(SIGNATURE_RAWECDSA); + KeyAgreement.getInstance("ECDH"); + KeyFactory.getInstance("EC"); + KeyPairGenerator.getInstance("EC"); + AlgorithmParameters.getInstance("EC"); } catch (Exception e) { mediator = false; } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java --- a/src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -61,12 +61,6 @@ protected void engineInit(KeyStore ks, char[] password) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { - if ((ks != null) && SunJSSE.isFIPS()) { - if (ks.getProvider() != SunJSSE.cryptoProvider) { - throw new KeyStoreException("FIPS mode: KeyStore must be " - + "from provider " + SunJSSE.cryptoProvider.getName()); - } - } keyManager = new SunX509KeyManagerImpl(ks, password); isInitialized = true; } @@ -91,12 +85,6 @@ keyManager = new X509KeyManagerImpl( Collections.emptyList()); } else { - if (SunJSSE.isFIPS() && - (ks.getProvider() != SunJSSE.cryptoProvider)) { - throw new KeyStoreException( - "FIPS mode: KeyStore must be " + - "from provider " + SunJSSE.cryptoProvider.getName()); - } try { Builder builder = Builder.newInstance(ks, new PasswordProtection(password)); @@ -115,10 +103,7 @@ throw new InvalidAlgorithmParameterException( "Parameters must be instance of KeyStoreBuilderParameters"); } - if (SunJSSE.isFIPS()) { - throw new InvalidAlgorithmParameterException - ("FIPS mode: KeyStoreBuilderParameters not supported"); - } + List builders = ((KeyStoreBuilderParameters)params).getParameters(); keyManager = new X509KeyManagerImpl(builders); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java --- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -458,7 +458,7 @@ String identityAlg = shc.sslConfig.identificationProtocol; if (result && identityAlg != null) { String sessionIdentityAlg = s.getIdentificationProtocol(); - if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { @@ -765,7 +765,7 @@ String hmacAlg = "Hmac" + hashAlg.name.replace("-", ""); try { - Mac hmac = JsseJce.getMac(hmacAlg); + Mac hmac = Mac.getInstance(hmacAlg); hmac.init(finishedKey); return hmac.doFinal(digest); } catch (NoSuchAlgorithmException | InvalidKeyException ex) { diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/RSAKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -109,7 +109,7 @@ byte[] getEncoded(PublicKey publicKey, SecureRandom secureRandom) throws GeneralSecurityException { - Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); + Cipher cipher = Cipher.getInstance(JsseJce.CIPHER_RSA_PKCS1); cipher.init(Cipher.WRAP_MODE, publicKey, secureRandom); return cipher.wrap(premasterSecret); } @@ -119,7 +119,7 @@ ClientHandshakeContext chc) throws GeneralSecurityException { String algorithm = chc.negotiatedProtocol.useTLS12PlusSpec() ? "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"; - KeyGenerator kg = JsseJce.getKeyGenerator(algorithm); + KeyGenerator kg = KeyGenerator.getInstance(algorithm); TlsRsaPremasterSecretParameterSpec spec = new TlsRsaPremasterSecretParameterSpec( chc.clientHelloVersion, @@ -136,7 +136,7 @@ byte[] encoded = null; boolean needFailover = false; - Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); + Cipher cipher = Cipher.getInstance(JsseJce.CIPHER_RSA_PKCS1); try { // Try UNWRAP_MODE mode firstly. cipher.init(Cipher.UNWRAP_MODE, privateKey, @@ -163,7 +163,7 @@ if (needFailover) { // The cipher might be spoiled by unsuccessful call to init(), // so request a fresh instance - cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); + cipher = Cipher.getInstance(JsseJce.CIPHER_RSA_PKCS1); // Use DECRYPT_MODE and dispose the previous initialization. cipher.init(Cipher.DECRYPT_MODE, privateKey); @@ -227,7 +227,7 @@ try { String s = ((clientVersion >= ProtocolVersion.TLS12.id) ? "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); - KeyGenerator kg = JsseJce.getKeyGenerator(s); + KeyGenerator kg = KeyGenerator.getInstance(s); kg.init(new TlsRsaPremasterSecretParameterSpec( clientVersion, serverVersion, encodedSecret), generator); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/RSAServerKeyExchange.java --- a/src/java.base/share/classes/sun/security/ssl/RSAServerKeyExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/RSAServerKeyExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -306,7 +306,7 @@ // check constraints of RSA PublicKey RSAPublicKey publicKey; try { - KeyFactory kf = JsseJce.getKeyFactory("RSA"); + KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPublicKeySpec spec = new RSAPublicKeySpec( new BigInteger(1, skem.modulus), new BigInteger(1, skem.exponent)); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/RSASignature.java --- a/src/java.base/share/classes/sun/security/ssl/RSASignature.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/RSASignature.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -53,9 +53,9 @@ public RSASignature() throws NoSuchAlgorithmException { super(); - rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA); - this.mdMD5 = JsseJce.getMessageDigest("MD5"); - this.mdSHA = JsseJce.getMessageDigest("SHA"); + rawRsa = Signature.getInstance(JsseJce.SIGNATURE_RAWRSA); + this.mdMD5 = MessageDigest.getInstance("MD5"); + this.mdSHA = MessageDigest.getInstance("SHA"); } /** @@ -66,7 +66,7 @@ * which may be this class. */ static Signature getInstance() throws NoSuchAlgorithmException { - return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA); + return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA); } @Override diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SSLCipher.java --- a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -851,7 +851,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.DECRYPT_MODE, key, params, random); } @@ -933,7 +933,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.ENCRYPT_MODE, key, params, random); } @@ -1023,7 +1023,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.DECRYPT_MODE, key, params, random); } @@ -1175,7 +1175,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.ENCRYPT_MODE, key, params, random); } @@ -1291,7 +1291,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); if (params == null) { params = new IvParameterSpec(new byte[sslCipher.ivSize]); } @@ -1455,7 +1455,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.random = random; if (params == null) { params = new IvParameterSpec(new byte[sslCipher.ivSize]); @@ -1590,7 +1590,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.fixedIv = ((IvParameterSpec)params).getIV(); @@ -1705,7 +1705,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.fixedIv = ((IvParameterSpec)params).getIV(); @@ -1838,7 +1838,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.iv = ((IvParameterSpec)params).getIV(); @@ -1992,7 +1992,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.iv = ((IvParameterSpec)params).getIV(); @@ -2133,7 +2133,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.iv = ((IvParameterSpec)params).getIV(); @@ -2252,7 +2252,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.iv = ((IvParameterSpec)params).getIV(); @@ -2392,7 +2392,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.iv = ((IvParameterSpec)params).getIV(); @@ -2534,7 +2534,7 @@ Key key, AlgorithmParameterSpec params, SecureRandom random) throws GeneralSecurityException { super(authenticator, protocolVersion); - this.cipher = JsseJce.getCipher(algorithm); + this.cipher = Cipher.getInstance(algorithm); this.tagSize = sslCipher.tagSize; this.key = key; this.iv = ((IvParameterSpec)params).getIV(); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java --- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -36,6 +36,7 @@ import java.util.HashMap; import java.util.List; import java.util.function.BiFunction; +import javax.crypto.KeyGenerator; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SNIMatcher; import javax.net.ssl.SNIServerName; @@ -104,7 +105,7 @@ "jdk.tls.useExtendedMasterSecret", true); if (supportExtendedMasterSecret) { try { - JsseJce.getKeyGenerator("SunTlsExtendedMasterSecret"); + KeyGenerator.getInstance("SunTlsExtendedMasterSecret"); } catch (NoSuchAlgorithmException nae) { supportExtendedMasterSecret = false; } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java --- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -94,14 +94,8 @@ trustManager = chooseTrustManager(tm); if (sr == null) { - secureRandom = JsseJce.getSecureRandom(); + secureRandom = new SecureRandom(); } else { - if (SunJSSE.isFIPS() && - (sr.getProvider() != SunJSSE.cryptoProvider)) { - throw new KeyManagementException - ("FIPS mode: SecureRandom must be from provider " - + SunJSSE.cryptoProvider.getName()); - } secureRandom = sr; } @@ -127,12 +121,6 @@ // We only use the first instance of X509TrustManager passed to us. for (int i = 0; tm != null && i < tm.length; i++) { if (tm[i] instanceof X509TrustManager) { - if (SunJSSE.isFIPS() && - !(tm[i] instanceof X509TrustManagerImpl)) { - throw new KeyManagementException - ("FIPS mode: only SunJSSE TrustManagers may be used"); - } - if (tm[i] instanceof X509ExtendedTrustManager) { return (X509TrustManager)tm[i]; } else { @@ -153,20 +141,7 @@ if (!(km instanceof X509KeyManager)) { continue; } - if (SunJSSE.isFIPS()) { - // In FIPS mode, require that one of SunJSSE's own keymanagers - // is used. Otherwise, we cannot be sure that only keys from - // the FIPS token are used. - if ((km instanceof X509KeyManagerImpl) - || (km instanceof SunX509KeyManagerImpl)) { - return (X509ExtendedKeyManager)km; - } else { - // throw exception, we don't want to silently use the - // dummy keymanager without telling the user. - throw new KeyManagementException - ("FIPS mode: only SunJSSE KeyManagers may be used"); - } - } + if (km instanceof X509ExtendedKeyManager) { return (X509ExtendedKeyManager)km; } @@ -548,41 +523,24 @@ private static final List serverDefaultCipherSuites; static { - if (SunJSSE.isFIPS()) { - supportedProtocols = Arrays.asList( - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - ); + supportedProtocols = Arrays.asList( + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30, + ProtocolVersion.SSL20Hello + ); - serverDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - }); - } else { - supportedProtocols = Arrays.asList( - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30, - ProtocolVersion.SSL20Hello - ); - - serverDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30, - ProtocolVersion.SSL20Hello - }); - } + serverDefaultProtocols = getAvailableProtocols( + new ProtocolVersion[] { + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30, + ProtocolVersion.SSL20Hello + }); supportedCipherSuites = getApplicableSupportedCipherSuites( supportedProtocols); @@ -626,23 +584,14 @@ } static ProtocolVersion[] getSupportedProtocols() { - if (SunJSSE.isFIPS()) { - return new ProtocolVersion[] { - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - }; - } else { - return new ProtocolVersion[]{ - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30, - ProtocolVersion.SSL20Hello - }; - } + return new ProtocolVersion[]{ + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30, + ProtocolVersion.SSL20Hello + }; } } @@ -656,18 +605,11 @@ private static final List clientDefaultCipherSuites; static { - if (SunJSSE.isFIPS()) { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS10 - }); - } else { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS10, - ProtocolVersion.SSL30 - }); - } + clientDefaultProtocols = getAvailableProtocols( + new ProtocolVersion[] { + ProtocolVersion.TLS10, + ProtocolVersion.SSL30 + }); clientDefaultCipherSuites = getApplicableEnabledCipherSuites( clientDefaultProtocols, true); @@ -694,20 +636,12 @@ private static final List clientDefaultCipherSuites; static { - if (SunJSSE.isFIPS()) { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - }); - } else { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30 - }); - } + clientDefaultProtocols = getAvailableProtocols( + new ProtocolVersion[] { + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30 + }); clientDefaultCipherSuites = getApplicableEnabledCipherSuites( clientDefaultProtocols, true); @@ -735,22 +669,13 @@ private static final List clientDefaultCipherSuites; static { - if (SunJSSE.isFIPS()) { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - }); - } else { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30 - }); - } + clientDefaultProtocols = getAvailableProtocols( + new ProtocolVersion[] { + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30 + }); clientDefaultCipherSuites = getApplicableEnabledCipherSuites( clientDefaultProtocols, true); @@ -777,24 +702,14 @@ private static final List clientDefaultCipherSuites; static { - if (SunJSSE.isFIPS()) { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - }); - } else { - clientDefaultProtocols = getAvailableProtocols( - new ProtocolVersion[] { - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30 - }); - } + clientDefaultProtocols = getAvailableProtocols( + new ProtocolVersion[] { + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30 + }); clientDefaultCipherSuites = getApplicableEnabledCipherSuites( clientDefaultProtocols, true); @@ -866,16 +781,6 @@ " is not a supported SSL protocol name"); } - if (SunJSSE.isFIPS() && - ((pv == ProtocolVersion.SSL30) || - (pv == ProtocolVersion.SSL20Hello))) { - reservedException = new IllegalArgumentException( - propname + ": " + pv + - " is not FIPS compliant"); - - break; - } - // ignore duplicated protocols if (!arrayList.contains(pv)) { arrayList.add(pv); @@ -955,22 +860,13 @@ } static ProtocolVersion[] getProtocols() { - if (SunJSSE.isFIPS()) { - return new ProtocolVersion[]{ - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - }; - } else { - return new ProtocolVersion[]{ - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30 - }; - } + return new ProtocolVersion[]{ + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30 + }; } protected CustomizedTLSContext() { diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SSLMasterKeyDerivation.java --- a/src/java.base/share/classes/sun/security/ssl/SSLMasterKeyDerivation.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SSLMasterKeyDerivation.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -145,7 +145,7 @@ } try { - KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg); + KeyGenerator kg = KeyGenerator.getInstance(masterAlg); kg.init(spec); return kg.generateKey(); } catch (InvalidAlgorithmParameterException | diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java --- a/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -280,7 +280,7 @@ hashAlg.name, hashAlg.hashLength, hashAlg.blockSize); try { - KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg); + KeyGenerator kg = KeyGenerator.getInstance(keyMaterialAlg); kg.init(spec); this.keyMaterialSpec = (TlsKeyMaterialSpec)kg.generateKey(); diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SignatureScheme.java --- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -194,7 +194,7 @@ boolean mediator = true; try { - Signature signer = JsseJce.getSignature("RSASSA-PSS"); + Signature signer = Signature.getInstance("RSASSA-PSS"); signer.setParameter(pssParamSpec); } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException exp) { @@ -275,7 +275,7 @@ mediator = signAlgParamSpec.isAvailable; } else { try { - JsseJce.getSignature(algorithm); + Signature.getInstance(algorithm); } catch (Exception e) { mediator = false; if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { @@ -466,7 +466,7 @@ return null; } - Signature signer = JsseJce.getSignature(algorithm); + Signature signer = Signature.getInstance(algorithm); if (key instanceof PublicKey) { signer.initVerify((PublicKey)(key)); } else { diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SunJSSE.java --- a/src/java.base/share/classes/sun/security/ssl/SunJSSE.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SunJSSE.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -66,97 +66,16 @@ "(PKCS12, SunX509/PKIX key/trust factories, " + "SSLv3/TLSv1/TLSv1.1/TLSv1.2/TLSv1.3/DTLSv1.0/DTLSv1.2)"; - private static String fipsInfo = - "Sun JSSE provider (FIPS mode, crypto provider "; - - // tri-valued flag: - // null := no final decision made - // false := data structures initialized in non-FIPS mode - // true := data structures initialized in FIPS mode - private static Boolean fips; - - // the FIPS certificate crypto provider that we use to perform all crypto - // operations. null in non-FIPS mode - static java.security.Provider cryptoProvider; - - protected static synchronized boolean isFIPS() { - if (fips == null) { - fips = false; - } - return fips; - } - - // ensure we can use FIPS mode using the specified crypto provider. - // enable FIPS mode if not already enabled. - private static synchronized void ensureFIPS(java.security.Provider p) { - if (fips == null) { - fips = true; - cryptoProvider = p; - } else { - if (fips == false) { - throw new ProviderException - ("SunJSSE already initialized in non-FIPS mode"); - } - if (cryptoProvider != p) { - throw new ProviderException - ("SunJSSE already initialized with FIPS crypto provider " - + cryptoProvider); - } - } - } - - // standard constructor protected SunJSSE() { super("SunJSSE", PROVIDER_VER, info); subclassCheck(); - if (Boolean.TRUE.equals(fips)) { - throw new ProviderException - ("SunJSSE is already initialized in FIPS mode"); - } - registerAlgorithms(false); - } - - // preferred constructor to enable FIPS mode at runtime - protected SunJSSE(java.security.Provider cryptoProvider){ - this(checkNull(cryptoProvider), cryptoProvider.getName()); - } - - // constructor to enable FIPS mode from java.security file - protected SunJSSE(String cryptoProvider){ - this(null, checkNull(cryptoProvider)); - } - - private static T checkNull(T t) { - if (t == null) { - throw new ProviderException("cryptoProvider must not be null"); - } - return t; + registerAlgorithms(); } - private SunJSSE(java.security.Provider cryptoProvider, - String providerName) { - super("SunJSSE", PROVIDER_VER, fipsInfo + providerName + ")"); - subclassCheck(); - if (cryptoProvider == null) { - // Calling Security.getProvider() will cause other providers to be - // loaded. That is not good but unavoidable here. - cryptoProvider = Security.getProvider(providerName); - if (cryptoProvider == null) { - throw new ProviderException - ("Crypto provider not installed: " + providerName); - } - } - ensureFIPS(cryptoProvider); - registerAlgorithms(true); - } - - private void registerAlgorithms(final boolean isfips) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - doRegister(isfips); - return null; - } + private void registerAlgorithms() { + AccessController.doPrivileged((PrivilegedAction) () -> { + doRegister(); + return null; }); } @@ -165,14 +84,13 @@ putService(new Provider.Service(this, type, algo, cn, aliases, attrs)); } - private void doRegister(boolean isfips) { - if (isfips == false) { - Iterator rsaIter = - new SunRsaSignEntries(this).iterator(); - while (rsaIter.hasNext()) { - putService(rsaIter.next()); - } + private void doRegister() { + Iterator rsaIter = + new SunRsaSignEntries(this).iterator(); + while (rsaIter.hasNext()) { + putService(rsaIter.next()); } + ps("Signature", "MD5andSHA1withRSA", "sun.security.ssl.RSASignature", null, null); @@ -183,14 +101,15 @@ createAliases("PKIX"), null); ps("TrustManagerFactory", "SunX509", - "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory", null, null); + "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory", + null, null); ps("TrustManagerFactory", "PKIX", "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", createAliases("SunPKIX", "X509", "X.509"), null); ps("SSLContext", "TLSv1", "sun.security.ssl.SSLContextImpl$TLS10Context", - (isfips? null : createAliases("SSLv3")), null); + createAliases("SSLv3"), null); ps("SSLContext", "TLSv1.1", "sun.security.ssl.SSLContextImpl$TLS11Context", null, null); ps("SSLContext", "TLSv1.2", @@ -199,7 +118,7 @@ "sun.security.ssl.SSLContextImpl$TLS13Context", null, null); ps("SSLContext", "TLS", "sun.security.ssl.SSLContextImpl$TLSContext", - (isfips? null : createAliases("SSL")), null); + createAliases("SSL"), null); ps("SSLContext", "DTLSv1.0", "sun.security.ssl.SSLContextImpl$DTLS10Context", null, null); @@ -225,12 +144,4 @@ throw new AssertionError("Illegal subclass: " + getClass()); } } - - @Override - @SuppressWarnings("deprecation") - protected final void finalize() throws Throwable { - // empty - super.finalize(); - } - } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java --- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -52,6 +52,7 @@ import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.SSLExtensionSpec; import sun.security.ssl.SSLHandshake.HandshakeMessage; +import sun.security.util.ECUtil; /** * Pack of the "supported_groups" extensions [RFC 4492/7919]. @@ -158,15 +159,23 @@ } static enum NamedGroupType { - NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE) - NAMED_GROUP_FFDHE, // Finite Field Groups (DHE) - NAMED_GROUP_XDH, // Finite Field Groups (XDH) - NAMED_GROUP_ARBITRARY, // arbitrary prime and curves (ECDHE) - NAMED_GROUP_NONE; // Not predefined named group + NAMED_GROUP_ECDHE ("EC"), + NAMED_GROUP_FFDHE ("DiffieHellman"), + NAMED_GROUP_X25519 ("x25519"), + NAMED_GROUP_X448 ("x448"), + NAMED_GROUP_ARBITRARY ("EC"), + NAMED_GROUP_NONE (""); + + private final String algorithm; + + private NamedGroupType(String algorithm) { + this.algorithm = algorithm; + } boolean isSupported(List cipherSuites) { for (CipherSuite cs : cipherSuites) { - if (cs.keyExchange == null || cs.keyExchange.groupType == this) { + if (cs.keyExchange == null || + cs.keyExchange.groupType == this) { return true; } } @@ -180,108 +189,142 @@ // // See sun.security.util.CurveDB for the OIDs // NIST K-163 - SECT163_K1 (0x0001, "sect163k1", "1.3.132.0.1", true, + SECT163_K1 (0x0001, "sect163k1", "1.3.132.0.1", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECT163_R1 (0x0002, "sect163r1", "1.3.132.0.2", false, + SECT163_R1 (0x0002, "sect163r1", "1.3.132.0.2", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST B-163 - SECT163_R2 (0x0003, "sect163r2", "1.3.132.0.15", true, + SECT163_R2 (0x0003, "sect163r2", "1.3.132.0.15", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECT193_R1 (0x0004, "sect193r1", "1.3.132.0.24", false, + SECT193_R1 (0x0004, "sect193r1", "1.3.132.0.24", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECT193_R2 (0x0005, "sect193r2", "1.3.132.0.25", false, + SECT193_R2 (0x0005, "sect193r2", "1.3.132.0.25", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST K-233 - SECT233_K1 (0x0006, "sect233k1", "1.3.132.0.26", true, + SECT233_K1 (0x0006, "sect233k1", "1.3.132.0.26", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST B-233 - SECT233_R1 (0x0007, "sect233r1", "1.3.132.0.27", true, + SECT233_R1 (0x0007, "sect233r1", "1.3.132.0.27", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECT239_K1 (0x0008, "sect239k1", "1.3.132.0.3", false, + SECT239_K1 (0x0008, "sect239k1", "1.3.132.0.3", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST K-283 - SECT283_K1 (0x0009, "sect283k1", "1.3.132.0.16", true, + SECT283_K1 (0x0009, "sect283k1", "1.3.132.0.16", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST B-283 - SECT283_R1 (0x000A, "sect283r1", "1.3.132.0.17", true, + SECT283_R1 (0x000A, "sect283r1", "1.3.132.0.17", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST K-409 - SECT409_K1 (0x000B, "sect409k1", "1.3.132.0.36", true, + SECT409_K1 (0x000B, "sect409k1", "1.3.132.0.36", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST B-409 - SECT409_R1 (0x000C, "sect409r1", "1.3.132.0.37", true, + SECT409_R1 (0x000C, "sect409r1", "1.3.132.0.37", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST K-571 - SECT571_K1 (0x000D, "sect571k1", "1.3.132.0.38", true, + SECT571_K1 (0x000D, "sect571k1", "1.3.132.0.38", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST B-571 - SECT571_R1 (0x000E, "sect571r1", "1.3.132.0.39", true, + SECT571_R1 (0x000E, "sect571r1", "1.3.132.0.39", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECP160_K1 (0x000F, "secp160k1", "1.3.132.0.9", false, + SECP160_K1 (0x000F, "secp160k1", "1.3.132.0.9", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECP160_R1 (0x0010, "secp160r1", "1.3.132.0.8", false, + SECP160_R1 (0x0010, "secp160r1", "1.3.132.0.8", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECP160_R2 (0x0011, "secp160r2", "1.3.132.0.30", false, + SECP160_R2 (0x0011, "secp160r2", "1.3.132.0.30", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECP192_K1 (0x0012, "secp192k1", "1.3.132.0.31", false, + SECP192_K1 (0x0012, "secp192k1", "1.3.132.0.31", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST P-192 - SECP192_R1 (0x0013, "secp192r1", "1.2.840.10045.3.1.1", true, + SECP192_R1 (0x0013, "secp192r1", "1.2.840.10045.3.1.1", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECP224_K1 (0x0014, "secp224k1", "1.3.132.0.32", false, + SECP224_K1 (0x0014, "secp224k1", "1.3.132.0.32", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST P-224 - SECP224_R1 (0x0015, "secp224r1", "1.3.132.0.33", true, + SECP224_R1 (0x0015, "secp224r1", "1.3.132.0.33", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), - SECP256_K1 (0x0016, "secp256k1", "1.3.132.0.10", false, + SECP256_K1 (0x0016, "secp256k1", "1.3.132.0.10", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_12), // NIST P-256 - SECP256_R1 (0x0017, "secp256r1", "1.2.840.10045.3.1.7", true, + SECP256_R1 (0x0017, "secp256r1", "1.2.840.10045.3.1.7", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_13), // NIST P-384 - SECP384_R1 (0x0018, "secp384r1", "1.3.132.0.34", true, + SECP384_R1 (0x0018, "secp384r1", "1.3.132.0.34", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_13), // NIST P-521 - SECP521_R1 (0x0019, "secp521r1", "1.3.132.0.35", true, + SECP521_R1 (0x0019, "secp521r1", "1.3.132.0.35", + NamedGroupType.NAMED_GROUP_ECDHE, ProtocolVersion.PROTOCOLS_TO_13), // x25519 and x448 - X25519 (0x001D, "x25519", true, "x25519", + X25519 (0x001D, "x25519", null, + NamedGroupType.NAMED_GROUP_X25519, ProtocolVersion.PROTOCOLS_TO_13), - X448 (0x001E, "x448", true, "x448", + X448 (0x001E, "x448", null, + NamedGroupType.NAMED_GROUP_X448, ProtocolVersion.PROTOCOLS_TO_13), // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919) - FFDHE_2048 (0x0100, "ffdhe2048", true, + FFDHE_2048 (0x0100, "ffdhe2048", null, + NamedGroupType.NAMED_GROUP_FFDHE, ProtocolVersion.PROTOCOLS_TO_13), - FFDHE_3072 (0x0101, "ffdhe3072", true, + FFDHE_3072 (0x0101, "ffdhe3072", null, + NamedGroupType.NAMED_GROUP_FFDHE, ProtocolVersion.PROTOCOLS_TO_13), - FFDHE_4096 (0x0102, "ffdhe4096", true, + FFDHE_4096 (0x0102, "ffdhe4096", null, + NamedGroupType.NAMED_GROUP_FFDHE, ProtocolVersion.PROTOCOLS_TO_13), - FFDHE_6144 (0x0103, "ffdhe6144", true, + FFDHE_6144 (0x0103, "ffdhe6144", null, + NamedGroupType.NAMED_GROUP_FFDHE, ProtocolVersion.PROTOCOLS_TO_13), - FFDHE_8192 (0x0104, "ffdhe8192", true, + FFDHE_8192 (0x0104, "ffdhe8192", null, + NamedGroupType.NAMED_GROUP_FFDHE, ProtocolVersion.PROTOCOLS_TO_13), // Elliptic Curves (RFC 4492) // // arbitrary prime and characteristic-2 curves - ARBITRARY_PRIME (0xFF01, "arbitrary_explicit_prime_curves", + ARBITRARY_PRIME (0xFF01, "arbitrary_explicit_prime_curves", null, + NamedGroupType.NAMED_GROUP_ARBITRARY, ProtocolVersion.PROTOCOLS_TO_12), - ARBITRARY_CHAR2 (0xFF02, "arbitrary_explicit_char2_curves", + ARBITRARY_CHAR2 (0xFF02, "arbitrary_explicit_char2_curves", null, + NamedGroupType.NAMED_GROUP_ARBITRARY, ProtocolVersion.PROTOCOLS_TO_12); final int id; // hash + signature @@ -289,55 +332,16 @@ final String name; // literal name final String oid; // object identifier of the named group final String algorithm; // signature algorithm - final boolean isFips; // can be used in FIPS mode? final ProtocolVersion[] supportedProtocols; - // Constructor used for Elliptic Curve Groups (ECDHE) - private NamedGroup(int id, String name, String oid, boolean isFips, - ProtocolVersion[] supportedProtocols) { - this.id = id; - this.type = NamedGroupType.NAMED_GROUP_ECDHE; - this.name = name; - this.oid = oid; - this.algorithm = "EC"; - this.isFips = isFips; - this.supportedProtocols = supportedProtocols; - } - - // Constructor used for Elliptic Curve Groups (XDH) - private NamedGroup(int id, String name, - boolean isFips, String algorithm, + private NamedGroup(int id, String name, String oid, + NamedGroupType namedGroupType, ProtocolVersion[] supportedProtocols) { this.id = id; - this.type = NamedGroupType.NAMED_GROUP_XDH; - this.name = name; - this.oid = null; - this.algorithm = algorithm; - this.isFips = isFips; - this.supportedProtocols = supportedProtocols; - } - - // Constructor used for Finite Field Diffie-Hellman Groups (FFDHE) - private NamedGroup(int id, String name, boolean isFips, - ProtocolVersion[] supportedProtocols) { - this.id = id; - this.type = NamedGroupType.NAMED_GROUP_FFDHE; + this.type = namedGroupType; this.name = name; - this.oid = null; - this.algorithm = "DiffieHellman"; - this.isFips = isFips; - this.supportedProtocols = supportedProtocols; - } - - // Constructor used for arbitrary prime and curves (ECDHE) - private NamedGroup(int id, String name, - ProtocolVersion[] supportedProtocols) { - this.id = id; - this.type = NamedGroupType.NAMED_GROUP_ARBITRARY; - this.name = name; - this.oid = null; - this.algorithm = "EC"; - this.isFips = false; + this.oid = oid; + this.algorithm = namedGroupType.algorithm; this.supportedProtocols = supportedProtocols; } @@ -352,7 +356,7 @@ } static NamedGroup valueOf(ECParameterSpec params) { - String oid = JsseJce.getNamedCurveOid(params); + String oid = ECUtil.getCurveName(null, params); if ((oid != null) && (!oid.isEmpty())) { for (NamedGroup group : NamedGroup.values()) { if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE) && @@ -472,8 +476,6 @@ static final NamedGroup[] supportedNamedGroups; static { - boolean requireFips = SunJSSE.isFIPS(); - // The value of the System Property defines a list of enabled named // groups in preference order, separated with comma. For example: // @@ -499,8 +501,7 @@ group = group.trim(); if (!group.isEmpty()) { NamedGroup namedGroup = NamedGroup.nameOf(group); - if (namedGroup != null && - (!requireFips || namedGroup.isFips)) { + if (namedGroup != null) { if (isAvailableGroup(namedGroup)) { groupList.add(namedGroup); } @@ -514,29 +515,7 @@ property + ") contains no supported named groups"); } } else { // default groups - NamedGroup[] groups; - if (requireFips) { - groups = new NamedGroup[] { - // only NIST curves in FIPS mode - NamedGroup.SECP256_R1, - NamedGroup.SECP384_R1, - NamedGroup.SECP521_R1, - NamedGroup.SECT283_K1, - NamedGroup.SECT283_R1, - NamedGroup.SECT409_K1, - NamedGroup.SECT409_R1, - NamedGroup.SECT571_K1, - NamedGroup.SECT571_R1, - - // FFDHE 2048 - NamedGroup.FFDHE_2048, - NamedGroup.FFDHE_3072, - NamedGroup.FFDHE_4096, - NamedGroup.FFDHE_6144, - NamedGroup.FFDHE_8192, - }; - } else { - groups = new NamedGroup[] { + NamedGroup[] groups = new NamedGroup[] { // NIST curves first NamedGroup.SECP256_R1, NamedGroup.SECP384_R1, @@ -558,7 +537,6 @@ NamedGroup.FFDHE_6144, NamedGroup.FFDHE_8192, }; - } groupList = new ArrayList<>(groups.length); for (NamedGroup group : groups) { @@ -587,7 +565,7 @@ if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) { if (namedGroup.oid != null) { try { - params = JsseJce.getAlgorithmParameters("EC"); + params = AlgorithmParameters.getInstance("EC"); spec = new ECGenParameterSpec(namedGroup.oid); } catch (NoSuchAlgorithmException e) { return false; @@ -595,7 +573,7 @@ } } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) { try { - params = JsseJce.getAlgorithmParameters("DiffieHellman"); + params = AlgorithmParameters.getInstance("DiffieHellman"); spec = getFFDHEDHParameterSpec(namedGroup); } catch (NoSuchAlgorithmException e) { return false; diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java --- a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -218,7 +218,7 @@ responseList = ((ExtendedSSLSession)session).getStatusResponses(); } - trustedChain = validate(v, chain, responseList, + trustedChain = v.validate(chain, null, responseList, constraints, isClient ? null : authType); // check if EE certificate chains to a public root CA (as @@ -234,7 +234,7 @@ getRequestedServerNames(socket), chainsToPublicCA); } } else { - trustedChain = validate(v, chain, Collections.emptyList(), + trustedChain = v.validate(chain, null, Collections.emptyList(), null, isClient ? null : authType); } @@ -276,7 +276,7 @@ responseList = ((ExtendedSSLSession)session).getStatusResponses(); } - trustedChain = validate(v, chain, responseList, + trustedChain = v.validate(chain, null, responseList, constraints, isClient ? null : authType); // check if EE certificate chains to a public root CA (as @@ -292,7 +292,7 @@ getRequestedServerNames(engine), chainsToPublicCA); } } else { - trustedChain = validate(v, chain, Collections.emptyList(), + trustedChain = v.validate(chain, null, Collections.emptyList(), null, isClient ? null : authType); } @@ -312,18 +312,6 @@ return v; } - private static X509Certificate[] validate(Validator v, - X509Certificate[] chain, List responseList, - AlgorithmConstraints constraints, String authType) - throws CertificateException { - Object o = JsseJce.beginFipsProvider(); - try { - return v.validate(chain, null, responseList, constraints, authType); - } finally { - JsseJce.endFipsProvider(o); - } - } - // Get string representation of HostName from a list of server names. // // We are only accepting host_name name type in the list. diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/share/classes/sun/security/tools/keytool/Main.java --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Sun Feb 17 12:21:11 2019 +0000 @@ -211,7 +211,7 @@ STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V, PROTECTED), GENKEYPAIR("Generates.a.key.pair", - ALIAS, KEYALG, KEYSIZE, CURVENAME, SIGALG, DESTALIAS, DNAME, + ALIAS, KEYALG, KEYSIZE, CURVENAME, SIGALG, DNAME, STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V, PROTECTED), diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/solaris/native/libnet/solaris_close.c --- a/src/java.base/solaris/native/libnet/solaris_close.c Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/solaris/native/libnet/solaris_close.c Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -59,10 +59,6 @@ RESTARTABLE_RETURN_INT(readv(s, vector, count)); } -int NET_WriteV(int s, const struct iovec * vector, int count) { - RESTARTABLE_RETURN_INT(writev(s, vector, count)); -} - int NET_Send(int s, void *msg, int len, unsigned int flags) { RESTARTABLE_RETURN_INT(send(s, msg, len, flags)); } diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/unix/classes/java/lang/ProcessImpl.java --- a/src/java.base/unix/classes/java/lang/ProcessImpl.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java Sun Feb 17 12:21:11 2019 +0000 @@ -89,7 +89,7 @@ private static enum Platform { - LINUX(LaunchMechanism.VFORK, LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK), + LINUX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.VFORK, LaunchMechanism.FORK), BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK), @@ -106,27 +106,6 @@ EnumSet.copyOf(Arrays.asList(launchMechanisms)); } - @SuppressWarnings("fallthrough") - private String helperPath(String javahome, String osArch) { - switch (this) { - case SOLARIS: - // fall through... - case LINUX: - case AIX: - case BSD: - return javahome + "/lib/jspawnhelper"; - - default: - throw new AssertionError("Unsupported platform: " + this); - } - } - - String helperPath() { - Properties props = GetPropertyAction.privilegedGetProperties(); - return helperPath(StaticProperty.javaHome(), - props.getProperty("os.arch")); - } - LaunchMechanism launchMechanism() { return AccessController.doPrivileged( (PrivilegedAction) () -> { @@ -169,7 +148,7 @@ private static final Platform platform = Platform.get(); private static final LaunchMechanism launchMechanism = platform.launchMechanism(); - private static final byte[] helperpath = toCString(platform.helperPath()); + private static final byte[] helperpath = toCString(StaticProperty.javaHome() + "/lib/jspawnhelper"); private static byte[] toCString(String s) { if (s == null) diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/unix/native/libjava/ProcessImpl_md.c --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c Sun Feb 17 12:21:11 2019 +0000 @@ -49,56 +49,139 @@ #include "childproc.h" /* - * There are 4 possible strategies we might use to "fork": + * + * When starting a child on Unix, we need to do three things: + * - fork off + * - in the child process, do some pre-exec work: duping/closing file + * descriptors to set up stdio-redirection, setting environment variables, + * changing paths... + * - then exec(2) the target binary + * + * There are three ways to fork off: + * + * A) fork(2). Portable and safe (no side effects) but may fail with ENOMEM on + * all Unices when invoked from a VM with a high memory footprint. On Unices + * with strict no-overcommit policy this problem is most visible. * - * - fork(2). Very portable and reliable but subject to - * failure due to overcommit (see the documentation on - * /proc/sys/vm/overcommit_memory in Linux proc(5)). - * This is the ancient problem of spurious failure whenever a large - * process starts a small subprocess. + * This is because forking the VM will first create a child process with + * theoretically the same memory footprint as the parent - even if you plan + * to follow up with exec'ing a tiny binary. In reality techniques like + * copy-on-write etc mitigate the problem somewhat but we still run the risk + * of hitting system limits. + * + * For a Linux centric description of this problem, see the documentation on + * /proc/sys/vm/overcommit_memory in Linux proc(5). + * + * B) vfork(2): Portable and fast but very unsafe. It bypasses the memory + * problems related to fork(2) by starting the child in the memory image of + * the parent. Things that can go wrong include: + * - Programming errors in the child process before the exec(2) call may + * trash memory in the parent process, most commonly the stack of the + * thread invoking vfork. + * - Signals received by the child before the exec(2) call may be at best + * misdirected to the parent, at worst immediately kill child and parent. * - * - vfork(). Using this is scary because all relevant man pages - * contain dire warnings, e.g. Linux vfork(2). But at least it's - * documented in the glibc docs and is standardized by XPG4. - * http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html - * On Linux, one might think that vfork() would be implemented using - * the clone system call with flag CLONE_VFORK, but in fact vfork is - * a separate system call (which is a good sign, suggesting that - * vfork will continue to be supported at least on Linux). - * Another good sign is that glibc implements posix_spawn using - * vfork whenever possible. Note that we cannot use posix_spawn - * ourselves because there's no reliable way to close all inherited - * file descriptors. + * This is mitigated by very strict rules about what one is allowed to do in + * the child process between vfork(2) and exec(2), which is basically nothing. + * However, we always broke this rule by doing the pre-exec work between + * vfork(2) and exec(2). + * + * Also note that vfork(2) has been deprecated by the OpenGroup, presumably + * because of its many dangers. + * + * C) clone(2): This is a Linux specific call which gives the caller fine + * grained control about how exactly the process fork is executed. It is + * powerful, but Linux-specific. + * + * Aside from these three possibilities there is a forth option: posix_spawn(3). + * Where fork/vfork/clone all fork off the process and leave pre-exec work and + * calling exec(2) to the user, posix_spawn(3) offers the user fork+exec-like + * functionality in one package, similar to CreateProcess() on Windows. + * + * It is not a system call in itself, but usually a wrapper implemented within + * the libc in terms of one of (fork|vfork|clone)+exec - so whether or not it + * has advantages over calling the naked (fork|vfork|clone) functions depends + * on how posix_spawn(3) is implemented. + * + * Note that when using posix_spawn(3), we exec twice: first a tiny binary called + * the jspawnhelper, then in the jspawnhelper we do the pre-exec work and exec a + * second time, this time the target binary (similar to the "exec-twice-technique" + * described in http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-September/055333.html). + * + * This is a JDK-specific implementation detail which just happens to be + * implemented for jdk.lang.Process.launchMechanism=POSIX_SPAWN. + * + * --- Linux-specific --- * - * - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is - * Linux-specific, but this ought to work - at least the glibc - * sources contain code to handle different combinations of CLONE_VM - * and CLONE_THREAD. However, when this was implemented, it - * appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with - * the simple program - * Runtime.getRuntime().exec("/bin/true").waitFor(); - * with: - * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536 - * # Error: pthread_getattr_np failed with errno = 3 (ESRCH) - * We believe this is a glibc bug, reported here: - * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311 - * but the glibc maintainers closed it as WONTFIX. + * How does glibc implement posix_spawn? + * (see: sysdeps/posix/spawni.c for glibc < 2.24, + * sysdeps/unix/sysv/linux/spawni.c for glibc >= 2.24): + * + * 1) Before glibc 2.4 (released 2006), posix_spawn(3) used just fork(2)/exec(2). + * This would be bad for the JDK since we would risk the known memory issues with + * fork(2). But since this only affects glibc variants which have long been + * phased out by modern distributions, this is irrelevant. + * + * 2) Between glibc 2.4 and glibc 2.23, posix_spawn uses either fork(2) or + * vfork(2) depending on how exactly the user called posix_spawn(3): + * + * + * The child process is created using vfork(2) instead of fork(2) when + * either of the following is true: + * + * * the spawn-flags element of the attributes object pointed to by + * attrp contains the GNU-specific flag POSIX_SPAWN_USEVFORK; or + * + * * file_actions is NULL and the spawn-flags element of the attributes + * object pointed to by attrp does not contain + * POSIX_SPAWN_SETSIGMASK, POSIX_SPAWN_SETSIGDEF, + * POSIX_SPAWN_SETSCHEDPARAM, POSIX_SPAWN_SETSCHEDULER, + * POSIX_SPAWN_SETPGROUP, or POSIX_SPAWN_RESETIDS. + * + * + * Due to the way the JDK calls posix_spawn(3), it would therefore call vfork(2). + * So we would avoid the fork(2) memory problems. However, there still remains the + * risk associated with vfork(2). But it is smaller than were we to call vfork(2) + * directly since we use the jspawnhelper, moving all pre-exec work off to after + * the first exec, thereby reducing the vulnerable time window. + * + * 3) Since glibc >= 2.24, glibc uses clone+exec: * - * - posix_spawn(). While posix_spawn() is a fairly elaborate and - * complicated system call, it can't quite do everything that the old - * fork()/exec() combination can do, so the only feasible way to do - * this, is to use posix_spawn to launch a new helper executable - * "jprochelper", which in turn execs the target (after cleaning - * up file-descriptors etc.) The end result is the same as before, - * a child process linked to the parent in the same way, but it - * avoids the problem of duplicating the parent (VM) process - * address space temporarily, before launching the target command. + * new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, + * CLONE_VM | CLONE_VFORK | SIGCHLD, &args); + * + * This is even better than (2): + * + * CLONE_VM means we run in the parent's memory image, as with (2) + * CLONE_VFORK means parent waits until we exec, as with (2) + * + * However, error possibilities are further reduced since: + * - posix_spawn(3) passes a separate stack for the child to run on, eliminating + * the danger of trashing the forking thread's stack in the parent process. + * - posix_spawn(3) takes care to temporarily block all incoming signals to the + * child process until the first exec(2) has been called, * - * Based on the above analysis, we are currently using vfork() on - * Linux and posix_spawn() on other Unix systems. + * TL;DR + * Calling posix_spawn(3) for glibc + * (2) < 2.24 is not perfect but still better than using plain vfork(2), since + * the chance of an error happening is greatly reduced + * (3) >= 2.24 is the best option - portable, fast and as safe as possible. + * + * --- + * + * How does muslc implement posix_spawn? + * + * They always did use the clone (.. CLONE_VM | CLONE_VFORK ...) + * technique. So we are safe to use posix_spawn() here regardless of muslc + * version. + * + * + * + * + * Based on the above analysis, we are currently defaulting to posix_spawn() + * on all Unices including Linux. */ - static void setSIGCHLDHandler(JNIEnv *env) { diff -r 4964feb6d75d -r de9dd71ef18c src/java.base/unix/native/libnet/net_util_md.h --- a/src/java.base/unix/native/libnet/net_util_md.h Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.base/unix/native/libnet/net_util_md.h Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -86,7 +86,6 @@ int NET_Send(int s, void *msg, int len, unsigned int flags); int NET_SendTo(int s, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen); -int NET_Writev(int s, const struct iovec * vector, int count); int NET_Connect(int s, struct sockaddr *addr, int addrlen); int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen); int NET_SocketClose(int s); diff -r 4964feb6d75d -r de9dd71ef18c src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/OutputPropertiesFactory.java --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/OutputPropertiesFactory.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/OutputPropertiesFactory.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,15 +20,6 @@ package com.sun.org.apache.xml.internal.serializer; -import com.sun.org.apache.xml.internal.serializer.utils.MsgKey; -import com.sun.org.apache.xml.internal.serializer.utils.Utils; -import com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Enumeration; import java.util.Properties; import javax.xml.transform.OutputKeys; import jdk.xml.internal.SecuritySupport; @@ -68,18 +59,18 @@ * of the corresponding character, like this one:
quot=34
* *
  • S_USE_URL_ESCAPING - - * This non-standard property key is used to set a value of "yes" if the href values for HTML serialization should - * use %xx escaping. + * This non-standard property key is used to set a value of "yes" if the href values + * for HTML serialization should use %xx escaping. * *
  • S_OMIT_META_TAG - - * This non-standard property key is used to set a value of "yes" if the META tag should be omitted where it would - * otherwise be supplied. + * This non-standard property key is used to set a value of "yes" if the META tag + * should be omitted where it would otherwise be supplied. * * * @see SerializerFactory * @see Method * @see Serializer - * @LastModified: Oct 2017 + * @LastModified: Feb 2019 */ public final class OutputPropertiesFactory { @@ -147,14 +138,15 @@ S_BUILTIN_EXTENSIONS_UNIVERSAL + "entities"; /** - * This non-standard property key is used to set a value of "yes" if the href values for HTML serialization should - * use %xx escaping. */ + * This non-standard property key is used to set a value of "yes" if the href + * values for HTML serialization should use %xx escaping. + */ public static final String S_USE_URL_ESCAPING = S_BUILTIN_EXTENSIONS_UNIVERSAL + "use-url-escaping"; /** - * This non-standard property key is used to set a value of "yes" if the META tag should be omitted where it would - * otherwise be supplied. + * This non-standard property key is used to set a value of "yes" if the META + * tag should be omitted where it would otherwise be supplied. */ public static final String S_OMIT_META_TAG = S_BUILTIN_EXTENSIONS_UNIVERSAL + "omit-meta-tag"; @@ -174,53 +166,133 @@ S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL.length(); /** - * This non-standard, Oracle-impl only property key is used as if OutputKeys.STANDALONE is specified but - * without writing it out in the declaration; It can be used to reverse the change by Xalan patch 1495. - * Since Xalan patch 1495 can cause incompatible behavior, this property is add for application to neutralize - * the effect of Xalan patch 1495 + * This non-standard, Oracle-impl only property key is used as if + * OutputKeys.STANDALONE is specified but without writing it out in the declaration; + * It can be used to reverse the change by Xalan patch 1495. + * Since Xalan patch 1495 can cause incompatible behavior, this property is + * added for application to neutralize the effect of Xalan patch 1495 */ - /** - *

    Is Standalone

    - * - *
      - *
    • - * yes to indicate the output is intended to be used as standalone - *
    • - *
    • - * no has no effect. - *
    • - *
    - */ + /** + *

    Is Standalone

    + * + *
      + *
    • + * yes to indicate the output is intended to be used as standalone + *
    • + *
    • + * no has no effect. + *
    • + *
    + */ public static final String ORACLE_IS_STANDALONE = "http://www.oracle.com/xml/is-standalone"; //************************************************************ //* PRIVATE CONSTANTS //************************************************************ - private static final String S_XSLT_PREFIX = "xslt.output."; - private static final int S_XSLT_PREFIX_LEN = S_XSLT_PREFIX.length(); - private static final String S_XALAN_PREFIX = "org.apache.xslt."; - private static final int S_XALAN_PREFIX_LEN = S_XALAN_PREFIX.length(); + /* + * XSLT properties do not need namespace qualification. + * + * Xalan-specific output properties can be overridden in the stylesheet + * assigning a xalan namespace. For example: + * + * + * ... + */ + private static final String[] PROP_XML = { + "method", + "version", + "encoding", + "indent", + "omit-xml-declaration", + "standalone", + "media-type", + "{http://xml.apache.org/xalan}indent-amount", + "{http://xml.apache.org/xalan}content-handler", + "{http://xml.apache.org/xalan}entities" + }; - /** Synchronization object for lazy initialization of the above tables. */ - private static final Object m_synch_object = new Object(); + private static final String[] PROP_XML_VALUE = { + "xml", + "1.0", + "UTF-8", + "no", + "no", + "no", + "text/xml", + "0", + "com.sun.org.apache.xml.internal.serializer.ToXMLStream", + "com/sun/org/apache/xml/internal/serializer/XMLEntities" + }; - /** the directory in which the various method property files are located */ - private static final String PROP_DIR = "com/sun/org/apache/xml/internal/serializer/"; - /** property file for default XML properties */ - private static final String PROP_FILE_XML = "output_xml.properties"; - /** property file for default TEXT properties */ - private static final String PROP_FILE_TEXT = "output_text.properties"; - /** property file for default HTML properties */ - private static final String PROP_FILE_HTML = "output_html.properties"; - /** property file for default UNKNOWN (Either XML or HTML, to be determined later) properties */ - private static final String PROP_FILE_UNKNOWN = "output_unknown.properties"; + private static final String[] PROP_HTML = { + "method", + "indent", + "media", + "version", + "{http://xml.apache.org/xalan}indent-amount", + "{http://xml.apache.org/xalan}content-handler", + "{http://xml.apache.org/xalan}entities", + "{http://xml.apache.org/xalan}use-url-escaping", + "{http://xml.apache.org/xalan}omit-meta-tag" + }; + + private static final String[] PROP_HTML_VALUE = { + "html", + "yes", + "text/html", + "4.0", + "4", + "com.sun.org.apache.xml.internal.serializer.ToHTMLStream", + "com/sun/org/apache/xml/internal/serializer/HTMLEntities", + "yes", + "no" + }; + + private static final String[] PROP_TEXT = { + "method", + "media-type", + "{http://xml.apache.org/xalan}content-handler" + }; + + private static final String[] PROP_TEXT_VALUE = { + "text", + "text/plain", + "com.sun.org.apache.xml.internal.serializer.ToTextStream" + }; + + private static final String[] PROP_UNKNOWN = { + "method", + "version", + "encoding", + "indent", + "omit-xml-declaration", + "standalone", + "media-type", + "{http://xml.apache.org/xalan}indent-amount", + "{http://xml.apache.org/xalan}content-handler" + }; + + private static final String[] PROP_UNKNOWN_VALUE = { + "xml", + "1.0", + "UTF-8", + "no", + "no", + "no", + "text/xml", + "0", + "com.sun.org.apache.xml.internal.serializer.ToUnknownStream", + }; //************************************************************ //* PRIVATE STATIC FIELDS //************************************************************ - /** The default properties of all output files. */ + /** The default properties for all other than html and text. */ private static Properties m_xml_properties = null; /** The default properties when method="html". */ @@ -232,38 +304,8 @@ /** The properties when method="" for the "unknown" wrapper */ private static Properties m_unknown_properties = null; - private static final Class - ACCESS_CONTROLLER_CLASS = findAccessControllerClass(); - - private static Class findAccessControllerClass() { - try - { - // This Class was introduced in JDK 1.2. With the re-architecture of - // security mechanism ( starting in JDK 1.2 ), we have option of - // giving privileges to certain part of code using doPrivileged block. - // In JDK1.1.X applications won't be having security manager and if - // there is security manager ( in applets ), code need to be signed - // and trusted for having access to resources. - - return Class.forName("java.security.AccessController"); - } - catch (Exception e) - { - //User may be using older JDK ( JDK <1.2 ). Allow him/her to use it. - // But don't try to use doPrivileged - } - - return null; - } - /** - * Creates an empty OutputProperties with the property key/value defaults specified by - * a property file. The method argument is used to construct a string of - * the form output_[method].properties (for instance, output_html.properties). - * The output_xml.properties file is always used as the base. - * - *

    Anything other than 'text', 'xml', and 'html', will - * use the output_xml.properties file.

    + * Returns a Properties based on the specified method. The default is xml. * * @param method non-null reference to method name. * @@ -271,265 +313,71 @@ */ static public final Properties getDefaultMethodProperties(String method) { - String fileName = null; Properties defaultProperties = null; - // According to this article : Double-check locking does not work - // http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-toolbox.html - try - { - synchronized (m_synch_object) - { - if (null == m_xml_properties) // double check - { - fileName = PROP_FILE_XML; - m_xml_properties = loadPropertiesFile(fileName, null); - } - } - if (method.equals(Method.XML)) - { + if (null == m_xml_properties) { + m_xml_properties = initProperties(PROP_XML, PROP_XML_VALUE, null); + } + + + switch (method) { + case Method.XML: defaultProperties = m_xml_properties; - } - else if (method.equals(Method.HTML)) - { - if (null == m_html_properties) // double check - { - fileName = PROP_FILE_HTML; - m_html_properties = - loadPropertiesFile(fileName, m_xml_properties); + break; + case Method.HTML: + if (null == m_html_properties) { + m_html_properties = initProperties( + PROP_HTML, PROP_HTML_VALUE, m_xml_properties); } - defaultProperties = m_html_properties; - } - else if (method.equals(Method.TEXT)) - { - if (null == m_text_properties) // double check - { - fileName = PROP_FILE_TEXT; - m_text_properties = - loadPropertiesFile(fileName, m_xml_properties); - if (null - == m_text_properties.getProperty(OutputKeys.ENCODING)) + break; + case Method.TEXT: + if (null == m_text_properties) { + m_text_properties = initProperties( + PROP_TEXT, PROP_TEXT_VALUE, m_xml_properties); + + if (null == m_text_properties.getProperty(OutputKeys.ENCODING)) { String mimeEncoding = Encodings.getMimeEncoding(null); - m_text_properties.put( - OutputKeys.ENCODING, - mimeEncoding); + m_text_properties.put(OutputKeys.ENCODING, mimeEncoding); } } - defaultProperties = m_text_properties; - } - else if (method.equals(com.sun.org.apache.xml.internal.serializer.Method.UNKNOWN)) - { - if (null == m_unknown_properties) // double check - { - fileName = PROP_FILE_UNKNOWN; - m_unknown_properties = - loadPropertiesFile(fileName, m_xml_properties); + break; + case com.sun.org.apache.xml.internal.serializer.Method.UNKNOWN: + if (null == m_unknown_properties) { + m_unknown_properties = initProperties( + PROP_UNKNOWN, PROP_UNKNOWN_VALUE, m_xml_properties); } - defaultProperties = m_unknown_properties; - } - else - { - // TODO: Calculate res file from name. + break; + default: defaultProperties = m_xml_properties; - } + break; } - catch (IOException ioe) - { - throw new WrappedRuntimeException( - Utils.messages.createMessage( - MsgKey.ER_COULD_NOT_LOAD_METHOD_PROPERTY, - new Object[] { fileName, method }), - ioe); - } + // wrap these cached defaultProperties in a new Property object just so // that the caller of this method can't modify the default values return new Properties(defaultProperties); } /** - * Load the properties file from a resource stream. If a - * key name such as "org.apache.xslt.xxx", fix up the start of - * string to be a curly namespace. If a key name starts with - * "xslt.output.xxx", clip off "xslt.output.". If a key name *or* a - * key value is discovered, check for \u003a in the text, and - * fix it up to be ":", since earlier versions of the JDK do not - * handle the escape sequence (at least in key names). + * Initiates the properties * - * @param resourceName non-null reference to resource name. + * @param keys an array of keys + * @param values values corresponding to the keys * @param defaults Default properties, which may be null. */ - static private Properties loadPropertiesFile( - final String resourceName, - Properties defaults) - throws IOException + static private Properties initProperties(String[] keys, String[] values, Properties defaults) { - - // This static method should eventually be moved to a thread-specific class - // so that we can cache the ContextClassLoader and bottleneck all properties file - // loading throughout Xalan. - Properties props = new Properties(defaults); - InputStream is = null; - BufferedInputStream bis = null; - - try - { - if (ACCESS_CONTROLLER_CLASS != null) - { - is = AccessController.doPrivileged(new PrivilegedAction() { - public InputStream run() - { - return OutputPropertiesFactory.class - .getResourceAsStream(resourceName); - } - }); - } - else - { - // User may be using older JDK ( JDK < 1.2 ) - is = OutputPropertiesFactory.class - .getResourceAsStream(resourceName); - } - - bis = new BufferedInputStream(is); - props.load(bis); - } - catch (IOException ioe) - { - if (defaults == null) - { - throw ioe; - } - else - { - throw new WrappedRuntimeException( - Utils.messages.createMessage( - MsgKey.ER_COULD_NOT_LOAD_RESOURCE, - new Object[] { resourceName }), - ioe); - //"Could not load '"+resourceName+"' (check CLASSPATH), now using just the defaults ", ioe); - } - } - catch (SecurityException se) - { - // Repeat IOException handling for sandbox/applet case -sc - if (defaults == null) - { - throw se; - } - else - { - throw new WrappedRuntimeException( - Utils.messages.createMessage( - MsgKey.ER_COULD_NOT_LOAD_RESOURCE, - new Object[] { resourceName }), - se); - //"Could not load '"+resourceName+"' (check CLASSPATH, applet security), now using just the defaults ", se); - } - } - finally - { - if (bis != null) - { - bis.close(); - } - if (is != null) - { - is.close(); - } - } - - // Note that we're working at the HashTable level here, - // and not at the Properties level! This is important - // because we don't want to modify the default properties. - // NB: If fixupPropertyString ends up changing the property - // name or value, we need to remove the old key and re-add - // with the new key and value. However, then our Enumeration - // could lose its place in the HashTable. So, we first - // clone the HashTable and enumerate over that since the - // clone will not change. When we migrate to Collections, - // this code should be revisited and cleaned up to use - // an Iterator which may (or may not) alleviate the need for - // the clone. Many thanks to Padraig O'hIceadha - // for finding this problem. Bugzilla 2000. - - Enumeration keys = ((Properties) props.clone()).keys(); - while (keys.hasMoreElements()) - { - String key = (String) keys.nextElement(); - // Now check if the given key was specified as a - // System property. If so, the system property - // overides the default value in the propery file. - String value = null; - try - { - value = SecuritySupport.getSystemProperty(key); - } - catch (SecurityException se) - { - // No-op for sandbox/applet case, leave null -sc - } - if (value == null) - value = (String) props.get(key); - - String newKey = fixupPropertyString(key, true); - String newValue = null; - try - { - newValue = SecuritySupport.getSystemProperty(newKey); - } - catch (SecurityException se) - { - // No-op for sandbox/applet case, leave null -sc - } - if (newValue == null) - newValue = fixupPropertyString(value, false); - else - newValue = fixupPropertyString(newValue, false); - - if (key != newKey || value != newValue) - { - props.remove(key); - props.put(newKey, newValue); - } - + for (int i = 0; i < keys.length; i++) { + // check System Property. This is kept as is for binary compatibility + String sys = SecuritySupport.getSystemProperty(keys[i]); + props.put(keys[i], (sys == null) ? values[i] : sys); } return props; } - - /** - * Fix up a string in an output properties file according to - * the rules of {@link #loadPropertiesFile}. - * - * @param s non-null reference to string that may need to be fixed up. - * @return A new string if fixup occured, otherwise the s argument. - */ - static private String fixupPropertyString(String s, boolean doClipping) - { - int index; - if (doClipping && s.startsWith(S_XSLT_PREFIX)) - { - s = s.substring(S_XSLT_PREFIX_LEN); - } - if (s.startsWith(S_XALAN_PREFIX)) - { - s = - S_BUILTIN_EXTENSIONS_UNIVERSAL - + s.substring(S_XALAN_PREFIX_LEN); - } - if ((index = s.indexOf("\\u003a")) > 0) - { - String temp = s.substring(index + 6); - s = s.substring(0, index) + ":" + temp; - - } - return s; - } - } diff -r 4964feb6d75d -r de9dd71ef18c src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_html.properties --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_html.properties Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -########################################################################### -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -########################################################################### -## -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with 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. -## -# -# Specify defaults when method="html". These defaults use output_xml.properties -# as a base. -# - -# XSLT properties do not need namespace qualification. -method=html -indent=yes -media-type=text/html -version=4.0 - -# Xalan-specific output properties. These can be overridden in the stylesheet -# assigning a xalan namespace. For example: -# -# -# ... -# Note that the colon after the protocol needs to be escaped. -{http\u003a//xml.apache.org/xalan}indent-amount=4 -{http\u003a//xml.apache.org/xalan}content-handler=com.sun.org.apache.xml.internal.serializer.ToHTMLStream -{http\u003a//xml.apache.org/xalan}entities=com/sun/org/apache/xml/internal/serializer/HTMLEntities -{http\u003a//xml.apache.org/xalan}use-url-escaping=yes -{http\u003a//xml.apache.org/xalan}omit-meta-tag=no diff -r 4964feb6d75d -r de9dd71ef18c src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_text.properties --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_text.properties Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -########################################################################### -# reserved comment block -# DO NOT REMOVE OR ALTER! -########################################################################### -########################################################################## -# Copyright 2003-2004 The Apache Software Foundation. -# -# Licensed 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. -########################################################################## -# -# $Id: output_text.properties,v 1.3 2005/09/28 13:49:10 pvedula Exp $ -# -# Specify defaults when method="text". -# - -# XSLT properties do not need namespace qualification. -method=text -media-type=text/plain - -# Xalan-specific output properties. These can be overridden in the stylesheet -# assigning a xalan namespace. For example: -# -# -# ... -# Note that the colon after the protocol needs to be escaped. -{http\u003a//xml.apache.org/xalan}content-handler=com.sun.org.apache.xml.internal.serializer.ToTextStream diff -r 4964feb6d75d -r de9dd71ef18c src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_unknown.properties --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_unknown.properties Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -########################################################################### -# reserved comment block -# DO NOT REMOVE OR ALTER! -########################################################################### -########################################################################### -# Copyright 2003-2004 The Apache Software Foundation. -# -# Licensed 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. -########################################################################## -# -# $Id: output_unknown.properties,v 1.2.4.1 2005/09/15 08:15:33 suresh_emailid Exp $ -# -# Specify defaults when no method="..." is specified. -# This type of output will quickly switch to "xml" or "html" -# depending on the first element name. -# - -# XSLT properties do not need namespace qualification. -method=xml -version=1.0 -encoding=UTF-8 -indent=no -omit-xml-declaration=no -standalone=no -media-type=text/xml - -# Xalan-specific output properties. These can be overridden in the stylesheet -# assigning a xalan namespace. For example: -# -# -# ... -# Note that the colon after the protocol needs to be escaped. -{http\u003a//xml.apache.org/xalan}indent-amount=0 -{http\u003a//xml.apache.org/xalan}content-handler=com.sun.org.apache.xml.internal.serializer.ToUnknownStream - diff -r 4964feb6d75d -r de9dd71ef18c src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_xml.properties --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/output_xml.properties Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -########################################################################### -# reserved comment block -# DO NOT REMOVE OR ALTER! -########################################################################### -########################################################################### -# Copyright 2003-2004 The Apache Software Foundation. -# -# Licensed 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. -########################################################################## -# -# $Id: output_xml.properties,v 1.2.4.1 2005/09/15 08:15:33 suresh_emailid Exp $ -# -# Specify defaults when method="xml". These defaults serve as a base for -# other defaults, such as output_html and output_text. -# - -# XSLT properties do not need namespace qualification. -method=xml -version=1.0 -encoding=UTF-8 -indent=no -omit-xml-declaration=no -standalone=no -media-type=text/xml - -# Xalan-specific output properties. These can be overridden in the stylesheet -# assigning a xalan namespace. For example: -# -# -# ... -# Note that the colon after the protocol needs to be escaped. -{http\u003a//xml.apache.org/xalan}indent-amount=0 -{http\u003a//xml.apache.org/xalan}content-handler=com.sun.org.apache.xml.internal.serializer.ToXMLStream -{http\u003a//xml.apache.org/xalan}entities=com/sun/org/apache/xml/internal/serializer/XMLEntities - diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Sun Feb 17 12:21:11 2019 +0000 @@ -1152,7 +1152,7 @@ try { switch (kind) { case ERROR: - log.error(DiagnosticFlag.MULTIPLE, pos, Errors.ProcMessager(msg.toString())); + log.error(DiagnosticFlag.API, pos, Errors.ProcMessager(msg.toString())); break; case WARNING: diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Sun Feb 17 12:21:11 2019 +0000 @@ -1014,7 +1014,11 @@ * Parses a list of files. */ public List parseFiles(Iterable fileObjects) { - if (shouldStop(CompileState.PARSE)) + return parseFiles(fileObjects, false); + } + + public List parseFiles(Iterable fileObjects, boolean force) { + if (!force && shouldStop(CompileState.PARSE)) return List.nil(); //parse all files diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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.io.PrintWriter; import java.lang.module.ModuleDescriptor; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; import java.text.Collator; @@ -752,14 +753,18 @@ @Override public void process(OptionHelper helper, String option) throws InvalidValueException { if (option.endsWith(".java") ) { - Path p = Paths.get(option); - if (!Files.exists(p)) { - throw helper.newInvalidValueException(Errors.FileNotFound(p.toString())); + try { + Path p = Paths.get(option); + if (!Files.exists(p)) { + throw helper.newInvalidValueException(Errors.FileNotFound(p.toString())); + } + if (!Files.isRegularFile(p)) { + throw helper.newInvalidValueException(Errors.FileNotFile(p)); + } + helper.addFile(p); + } catch (InvalidPathException ex) { + throw helper.newInvalidValueException(Errors.InvalidPath(option)); } - if (!Files.isRegularFile(p)) { - throw helper.newInvalidValueException(Errors.FileNotFile(p)); - } - helper.addFile(p); } else { helper.addClassName(option); } diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacMessager.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacMessager.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacMessager.java Sun Feb 17 12:21:11 2019 +0000 @@ -34,6 +34,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; +import java.util.Set; import javax.lang.model.element.*; import javax.tools.JavaFileObject; import javax.tools.Diagnostic; @@ -117,7 +118,7 @@ switch (kind) { case ERROR: errorCount++; - log.error(DiagnosticFlag.MULTIPLE, pos, Errors.ProcMessager(msg.toString())); + log.error(DiagnosticFlag.API, pos, Errors.ProcMessager(msg.toString())); break; case WARNING: diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Sun Feb 17 12:21:11 2019 +0000 @@ -35,6 +35,7 @@ import java.nio.file.Path; import java.util.*; import java.util.Map.Entry; +import java.util.function.Predicate; import java.util.regex.*; import java.util.stream.Collectors; @@ -83,6 +84,7 @@ import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.Iterators; import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Log; @@ -1066,7 +1068,9 @@ prev.newRound(); this.genClassFiles = prev.genClassFiles; - List parsedFiles = compiler.parseFiles(newSourceFiles); + //parse the generated files even despite errors reported so far, to eliminate + //recoverable errors related to the type declared in the generated files: + List parsedFiles = compiler.parseFiles(newSourceFiles, true); roots = prev.roots.appendList(parsedFiles); // Check for errors after parsing @@ -1233,15 +1237,17 @@ } void showDiagnostics(boolean showAll) { - Set kinds = EnumSet.allOf(JCDiagnostic.Kind.class); - if (!showAll) { - // suppress errors, which are all presumed to be transient resolve errors - kinds.remove(JCDiagnostic.Kind.ERROR); - } - deferredDiagnosticHandler.reportDeferredDiagnostics(kinds); + deferredDiagnosticHandler.reportDeferredDiagnostics(showAll ? ACCEPT_ALL + : ACCEPT_NON_RECOVERABLE); log.popDiagnosticHandler(deferredDiagnosticHandler); compiler.setDeferredDiagnosticHandler(null); } + //where: + private final Predicate ACCEPT_NON_RECOVERABLE = + d -> d.getKind() != JCDiagnostic.Kind.ERROR || + !d.isFlagSet(DiagnosticFlag.RECOVERABLE) || + d.isFlagSet(DiagnosticFlag.API); + private final Predicate ACCEPT_ALL = d -> true; /** Print info about this round. */ private void printRoundInfo(boolean lastRound) { @@ -1335,7 +1341,7 @@ errorStatus = round.unrecoverableError(); moreToDo = moreToDo(); - round.showDiagnostics(errorStatus || showResolveErrors); + round.showDiagnostics(showResolveErrors); // Set up next round. // Copy mutable collections returned from filer. diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Sun Feb 17 12:21:11 2019 +0000 @@ -1977,6 +1977,11 @@ compiler.warn.invalid.path=\ Invalid filename: {0} +# 0: string +compiler.err.invalid.path=\ + Invalid filename: {0} + + # 0: path compiler.warn.invalid.archive.file=\ Unexpected file on path: {0} diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Sun Feb 17 12:21:11 2019 +0000 @@ -429,9 +429,9 @@ RECOVERABLE, NON_DEFERRABLE, COMPRESSED, - /** Print multiple errors for same source locations. + /** Flag for diagnostics that were reported through API methods. */ - MULTIPLE, + API, /** Flag for not-supported-in-source-X errors. */ SOURCE_LEVEL; diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Sun Feb 17 12:21:11 2019 +0000 @@ -33,6 +33,7 @@ import java.util.Map; import java.util.Queue; import java.util.Set; +import java.util.function.Predicate; import javax.tools.DiagnosticListener; import javax.tools.JavaFileObject; @@ -158,14 +159,14 @@ /** Report all deferred diagnostics. */ public void reportDeferredDiagnostics() { - reportDeferredDiagnostics(EnumSet.allOf(JCDiagnostic.Kind.class)); + reportDeferredDiagnostics(d -> true); } /** Report selected deferred diagnostics. */ - public void reportDeferredDiagnostics(Set kinds) { + public void reportDeferredDiagnostics(Predicate accepter) { JCDiagnostic d; while ((d = deferred.poll()) != null) { - if (kinds.contains(d.getKind())) + if (accepter.test(d)) prev.report(d); } deferred = null; // prevent accidental ongoing use @@ -713,7 +714,7 @@ case ERROR: if (nerrors < MaxErrors && - (diagnostic.isFlagSet(DiagnosticFlag.MULTIPLE) || + (diagnostic.isFlagSet(DiagnosticFlag.API) || shouldReport(diagnostic))) { writeDiagnostic(diagnostic); nerrors++; diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -171,6 +171,13 @@ * this is set to the appropriate value depending on the response length parameter. *

    * This method must be called prior to calling {@link #getResponseBody()}. + * + * @implNote This implementation allows the caller to instruct the + * server to force a connection close after the exchange terminates, by + * supplying a {@code Connection: close} header to the {@linkplain + * #getResponseHeaders() response headers} before {@code sendResponseHeaders} + * is called. + * * @param rCode the response code to send * @param responseLength if {@literal > 0}, specifies a fixed response * body length and that exact number of bytes must be written diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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,6 +32,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.text.*; +import java.util.stream.Stream; import com.sun.net.httpserver.*; class ExchangeImpl { @@ -261,6 +262,22 @@ o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen)); } } + + // A custom handler can request that the connection be + // closed after the exchange by supplying Connection: close + // to the response header. Nothing to do if the exchange is + // already set up to be closed. + if (!close) { + Stream conheader = + Optional.ofNullable(rspHdrs.get("Connection")) + .map(List::stream).orElse(Stream.empty()); + if (conheader.anyMatch("close"::equalsIgnoreCase)) { + Logger logger = server.getLogger(); + logger.log (Level.DEBUG, "Connection: close requested by handler"); + close = true; + } + } + write (rspHdrs, tmpout); this.rspContentLen = contentLen; tmpout.flush() ; diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -21,22 +21,23 @@ * questions. */ - package org.graalvm.compiler.hotspot.test; +import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.util.Random; import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; import org.graalvm.compiler.runtime.RuntimeProvider; import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.meta.ResolvedJavaMethod; /* @@ -52,7 +53,7 @@ * is not tested per se (only execution based on admissible intrinsics). * */ -public final class BigIntegerIntrinsicsTest extends MethodSubstitutionTest { +public final class BigIntegerIntrinsicsTest extends GraalCompilerTest { static final int N = 100; @@ -149,8 +150,8 @@ assertDeepEquals(res1, res2); - // Invoke BigInteger testMontgomeryAux(BigInteger, BigExp, BigInteger) through code - // handle. + // Invoke BigInteger testMontgomeryAux(BigInteger, BigExp, BigInteger) + // through code handle. BigInteger res3 = (BigInteger) tin.invokeCode(big1, bigTwo, big2); assertDeepEquals(res1, res3); @@ -168,7 +169,6 @@ private class TestIntrinsic { TestIntrinsic(String testmname, Class javaclass, String javamname, Class... params) { - javamethod = getResolvedJavaMethod(javaclass, javamname, params); testmethod = getResolvedJavaMethod(testmname); @@ -179,21 +179,39 @@ testcode = getCode(testmethod); assert testcode != null; + assert testcode.isValid(); } Object invokeJava(BigInteger big, Object... args) { - return invokeSafe(javamethod, big, args); } Object invokeTest(Object... args) { - return invokeSafe(testmethod, null, args); } Object invokeCode(Object... args) { + try { + return testcode.executeVarargs(args); + } + catch (InvalidInstalledCodeException e) { + // Ensure the installed code is valid, possibly recompiled. + testcode = getCode(testmethod); - return executeVarargsSafe(testcode, args); + assert testcode != null; + assert testcode.isValid(); + + return invokeCode(args); + } + } + + private Object invokeSafe(ResolvedJavaMethod method, Object receiver, Object... args) { + try { + return invoke(method, receiver, args); + } catch (IllegalAccessException | InvocationTargetException | + IllegalArgumentException | InstantiationException e) { + throw new RuntimeException(e); + } } // Private data section: @@ -202,7 +220,8 @@ private InstalledCode testcode; } - private static GraalHotSpotVMConfig config = ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig(); + private static GraalHotSpotVMConfig config = + ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig(); private static BigInteger bigTwo = BigInteger.valueOf(2); private static Random rnd = new Random(17); diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -299,7 +299,7 @@ TestMethods(String testmname, Class javaclass, Class intrinsicClass, String javamname, Class... params) { javamethod = getResolvedJavaMethod(javaclass, javamname, params); testmethod = getResolvedJavaMethod(testmname); - testgraph = testGraph(testmname, javamname); + testgraph = getReplacements().getIntrinsicGraph(javamethod, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext()); assertInGraph(testgraph, intrinsicClass); assert javamethod != null; diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jcmd/linux/classes/sun/tools/ProcessHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jcmd/linux/classes/sun/tools/ProcessHelper.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,155 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.tools; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.stream.Stream; + +/** + * A helper class that retrieves the main class name for + * a running Java process using the proc filesystem (procfs) + */ +public class ProcessHelper implements sun.tools.common.ProcessHelper { + + + private static final String CMD_PREFIX = "cmd:"; + private static final ProcessHelper INSTANCE = new ProcessHelper(); + + public static ProcessHelper getInstance() { + return INSTANCE; + } + + /** + * Gets the main class name for the given Java process by parsing the + * process command line. + * @param pid - process ID (pid) + * @return main class name or null if the process no longer exists or + * was started with a native launcher (e.g. jcmd etc) + */ + + public String getMainClass(String pid) { + String cmdLine = getCommandLine(pid); + if (cmdLine == null) { + return null; + } + if (cmdLine.startsWith(CMD_PREFIX)) { + cmdLine = cmdLine.substring(CMD_PREFIX.length()); + } + String[] parts = cmdLine.split(" "); + String mainClass = null; + + if(parts.length == 0) { + return null; + } + + // Check the executable + String[] executablePath = parts[0].split("/"); + if (executablePath.length > 0) { + String binaryName = executablePath[executablePath.length - 1]; + if (!"java".equals(binaryName)) { + // Skip the process if it is not started with java launcher + return null; + } + } + + // If -jar option is used then read the main class name from the manifest file. + // Otherwise, the main class name is either specified in -m or --module options or it + // is the first part that is not a Java option (doesn't start with '-' and is not a + // classpath or a module path). + + for (int i = 1; i < parts.length && mainClass == null; i++) { + if (i < parts.length - 1) { + // Check if the module is executed with explicitly specified main class + if ((parts[i].equals("-m") || parts[i].equals("--module"))) { + return getMainClassFromModuleArg(parts[i + 1]); + } + // Check if the main class needs to be read from the manifest.mf in a JAR file + if (parts[i].equals("-jar")) { + return getMainClassFromJar(parts[i + 1], pid); + } + } + // If this is a classpath or a module path option then skip the next part + // (the classpath or the module path itself) + if (parts[i].equals("-cp") || parts[i].equals("-classpath") || parts[i].equals("--class-path") || + parts[i].equals("-p") || parts[i].equals("--module-path")) { + i++; + continue; + } + // Skip all other Java options + if (parts[i].startsWith("-")) { + continue; + } + mainClass = parts[i]; + } + return mainClass; + + } + + private String getMainClassFromModuleArg(String moduleArg) { + int pos = moduleArg.lastIndexOf("/"); + return (pos > 0 && pos < moduleArg.length()-1) ? moduleArg.substring(pos + 1) : null; + } + + private String getMainClassFromJar(String jar, String pid) { + if (!jar.startsWith("/")) { + String cwd = getCurrentWorkingDir(pid); + if (cwd != null) { + jar = cwd + "/" + jar; + } + } + try (JarFile jarFile = new JarFile(jar)) { + Manifest mf = jarFile.getManifest(); + if (mf != null) { + Attributes mainAttributes = mf.getMainAttributes(); + return mainAttributes.getValue("Main-Class"); + } + } catch (IOException e) { + return null; + } + return null; + } + + private static String getCurrentWorkingDir(String pid) { + return ("/proc/" + pid + "/cwd"); + } + + private static String getCommandLine(String pid) { + try (Stream lines = + Files.lines(Paths.get("/proc/" + pid + "/cmdline"))) { + return lines.map(x -> x.replaceAll("\0", " ")).findFirst().orElse(null); + } catch (IOException | UncheckedIOException e) { + return null; + } + } +} + + diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java --- a/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 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 @@ -78,25 +78,37 @@ } private static boolean check(VirtualMachineDescriptor vmd, String excludeClass, String partialMatch) { + String mainClass = null; - try { - VmIdentifier vmId = new VmIdentifier(vmd.id()); - MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId); - MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1); - mainClass = MonitoredVmUtil.mainClass(monitoredVm, true); - monitoredHost.detach(monitoredVm); - } catch (NullPointerException npe) { - // There is a potential race, where a running java app is being - // queried, unfortunately the java app has shutdown after this - // method is started but before getMonitoredVM is called. - // If this is the case, then the /tmp/hsperfdata_xxx/pid file - // will have disappeared and we will get a NullPointerException. - // Handle this gracefully.... - return false; - } catch (MonitorException | URISyntaxException e) { - return false; + + // Get the main class name using platform specific helper + ProcessHelper helper = ProcessHelper.platformProcessHelper(); + if (helper != null) { + mainClass = helper.getMainClass(vmd.id()); } + // If the main class name is still unset then retrieve it with the attach mechanism + if (mainClass == null) { + try { + VmIdentifier vmId = new VmIdentifier(vmd.id()); + MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId); + MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1); + mainClass = MonitoredVmUtil.mainClass(monitoredVm, true); + monitoredHost.detach(monitoredVm); + } catch (NullPointerException npe) { + // There is a potential race, where a running java app is being + // queried, unfortunately the java app has shutdown after this + // method is started but before getMonitoredVM is called. + // If this is the case, then the /tmp/hsperfdata_xxx/pid file + // will have disappeared and we will get a NullPointerException. + // Handle this gracefully.... + return false; + } catch (MonitorException | URISyntaxException e) { + return false; + } + } + + if (excludeClass != null && mainClass.equals(excludeClass)) { return false; } diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jcmd/share/classes/sun/tools/common/ProcessHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jcmd/share/classes/sun/tools/common/ProcessHelper.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,64 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.tools.common; + +import java.lang.reflect.Method; + +/** + * A helper class to retrieve the main class name for a running + * Java process. + */ + +public interface ProcessHelper { + + /** + * Returns an instance of the ProcessHelper class. + * + * @return ProcessHelper object or null if not supported on this platform. + */ + public static ProcessHelper platformProcessHelper() { + try { + Class c = Class.forName("sun.tools.ProcessHelper"); + @SuppressWarnings("unchecked") + Method m = c.getMethod("getInstance"); + return (ProcessHelper) m.invoke(null); + } catch (ClassNotFoundException e) { + return null; + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } + } + + + /** + * Returns the main class name for the given Java process + * + * @param pid - process ID (pid) + * @return main class name or null if the main class could not be retrieved + */ + + String getMainClass(String pid); +} diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, 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 @@ -1128,6 +1128,22 @@ } } + void commandDbgTrace(StringTokenizer t) { + int traceFlags; + if (t.hasMoreTokens()) { + String flagStr = t.nextToken(); + try { + traceFlags = Integer.decode(flagStr).intValue(); + } catch (NumberFormatException nfe) { + MessageOutput.println("dbgtrace command value must be an integer:", flagStr); + return; + } + } else { + traceFlags = VirtualMachine.TRACE_ALL; + } + Env.setTraceFlags(traceFlags); + } + void commandStop(StringTokenizer t) { String atIn; byte suspendPolicy = EventRequest.SUSPEND_ALL; diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Env.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -64,6 +64,10 @@ } } + static void setTraceFlags(int flags) { + connection.setTraceFlags(flags); + } + static VMConnection connection() { return connection; } diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -304,6 +304,7 @@ {"clear", "y", "n"}, {"connectors", "y", "y"}, {"cont", "n", "n"}, + {"dbgtrace", "y", "y"}, {"disablegc", "n", "n"}, {"down", "n", "y"}, {"dump", "n", "y"}, @@ -587,6 +588,8 @@ evaluator.commandExclude(t); } else if (cmd.equals("read")) { readCommand(t); + } else if (cmd.equals("dbgtrace")) { + evaluator.commandDbgTrace(t); } else if (cmd.equals("help") || cmd.equals("?")) { help(); } else if (cmd.equals("version")) { diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -107,6 +107,7 @@ {"Current thread isnt suspended.", "Current thread isn't suspended."}, {"Current thread not set.", "Current thread not set."}, {"dbgtrace flag value must be an integer:", "dbgtrace flag value must be an integer: {0}"}, + {"dbgtrace command value must be an integer:", "dbgtrace command value must be an integer: {0}"}, {"Deferring.", "Deferring {0}.\nIt will be set after the class is loaded."}, {"End of stack.", "End of stack."}, {"Error popping frame", "Error popping frame - {0}"}, @@ -411,6 +412,7 @@ " -- repeat command n times\n" + "# -- discard (no-op)\n" + "help (or ?) -- list commands\n" + + "dbgtrace [flag] -- same as dbgtrace command line option" + "version -- print version information\n" + "exit (or quit) -- exit debugger\n" + "\n" + diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, 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 @@ -52,7 +52,7 @@ private final Connector connector; private final Map connectorArgs; - private final int traceFlags; + private int traceFlags; synchronized void notifyOutputComplete() { outputCompleteCount++; @@ -321,6 +321,17 @@ this.traceFlags = traceFlags; } + public void setTraceFlags(int flags) { + this.traceFlags = flags; + /* + * If vm is not connected now, then vm.setDebugTraceMode() will + * be called when it is connected. + */ + if (vm != null) { + vm.setDebugTraceMode(flags); + } + } + synchronized VirtualMachine open() { if (connector instanceof LaunchingConnector) { vm = launchTarget(); diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java --- a/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -663,11 +663,7 @@ System.err.print(getText("agent.err.error") + ": " + keyText); if (params != null && params.length != 0) { - StringBuffer message = new StringBuffer(params[0]); - for (int i = 1; i < params.length; i++) { - message.append(" " + params[i]); - } - System.err.println(": " + message); + System.err.println(": " + String.join(" ", params)); } e.printStackTrace(); throw new RuntimeException(e); diff -r 4964feb6d75d -r de9dd71ef18c src/jdk.zipfs/share/classes/module-info.java --- a/src/jdk.zipfs/share/classes/module-info.java Sun Feb 17 12:20:37 2019 +0000 +++ b/src/jdk.zipfs/share/classes/module-info.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 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 @@ -24,14 +24,89 @@ */ /** - * Provides the implementation of the zip file system provider. + * Provides the implementation of the Zip file system provider. + * The Zip file system provider treats the contents of a Zip or JAR file as a file system. + *

    + * + *

    Accessing a Zip File System

    + * + * The {@linkplain java.nio.file.FileSystems FileSystems} {@code newFileSystem} + * static factory methods can be used to: + *
      + *
    • Create a Zip file system
    • + *
    • Open an existing file as a Zip file system
    • + *
    + * + *

    URI Scheme Used to Identify the Zip File System

    + * + * The URI {@link java.net.URI#getScheme scheme} that identifies the ZIP file system is {@code jar}. + * + *

    Zip File System Properties

    + * + * The following properties may be specified when creating a Zip + * file system: + *

    + * + * + * + * + * + * + * + * + * + * * - *

    The zip file system provider treats a zip or JAR file as a file system - * and provides the ability to manipulate the contents of the file. - * The zip file system provider can be created by - * {@link java.nio.file.FileSystems#newFileSystem - * FileSystems.newFileSystem} if installed. + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    + * Configurable properties that may be specified when creating + * a new Zip file system + *
    Property NameData TypeDefault ValueDescription
    createjava.lang.Stringfalse + * If the value is {@code true}, the Zip file system provider + * creates a new Zip or JAR file if it does not exist. + *
    encodingjava.lang.StringUTF-8 + * The value indicates the encoding scheme for the + * names of the entries in the Zip or JAR file. + *
    + * + *

    Examples:

    * + * Construct a new Zip file system that is identified by a URI. If the Zip file does not exist, + * it will be created: + *
    + * {@code
    + *
    + *     URI uri = URI.create("jar:file:/home/luckydog/tennisTeam.zip");
    + *     Map env = Map.of("create", "true");
    + *     FileSystem zipfs = FileSystems.newFileSystem(uri, env);
    + * }
    + * 
    + * + * Construct a new Zip file system that is identified by specifying a path + * and using automatic file type detection. Iterate from the root of the JAR displaying each + * found entry: + *
    + * {@code
    + *
    + *     FileSystem zipfs = FileSystems.newFileSystem(Path.of("helloworld.jar"), null);
    + *     Path rootDir = zipfs.getPath("/");
    + *     Files.walk(rootDir)
    + *            .forEach(System.out::println);
    + * }
    + * 
    * @provides java.nio.file.spi.FileSystemProvider * @moduleGraph * @since 9 diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/gtest/unittest.hpp --- a/test/hotspot/gtest/unittest.hpp Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/gtest/unittest.hpp Sun Feb 17 12:21:11 2019 +0000 @@ -105,7 +105,7 @@ TEST(category, CONCAT(name, _vm_assert)) { \ ASSERT_EXIT(child_ ## category ## _ ## name ## _(), \ ::testing::ExitedWithCode(1), \ - "assert failed: " msg); \ + "^assert failed: " msg); \ } \ \ void test_ ## category ## _ ## name ## _() diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/ProblemList-graal.txt --- a/test/hotspot/jtreg/ProblemList-graal.txt Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/ProblemList-graal.txt Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -195,6 +195,26 @@ compiler/stable/TestStableUByte.java 8204347 generic-all compiler/stable/TestStableUShort.java 8204347 generic-all +gc/g1/mixedgc/TestOldGenCollectionUsage.java 8196611 generic-all +gc/g1/TestPeriodicCollection.java 8196611 generic-all +gc/parallel/TestPrintGCDetailsVerbose.java 8196611 generic-all +vm/gc/InfiniteList.java 8196611 generic-all +vmTestbase/nsk/stress/except/except007.java 8196611 generic-all +vmTestbase/nsk/stress/except/except008.java 8196611 generic-all +serviceability/tmtools/jstat/GcTest02.java 8196611 generic-all +serviceability/tmtools/jstat/GcCapacityTest.java 8196611 generic-all +serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorMultiArrayTest.java 8196611 generic-all + +runtime/RedefineObject/TestRedefineObject.java 8218399 generic-all + +vmTestbase/nsk/jvmti/scenarios/sampling/SP06/sp06t003/TestDescription.java 8218167 generic-all + +vmTestbase/gc/lock/jvmti/alloc/jvmtialloclock02/TestDescription.java 8218700 generic-all + +vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java 8218701 generic-all + +vmTestbase/nsk/jdb/clear/clear003/clear003.java 8218701 generic-all + # Graal unit tests org.graalvm.compiler.core.test.CheckGraalInvariants 8205081 org.graalvm.compiler.core.test.OptionsVerifierTest 8205081 @@ -206,4 +226,4 @@ org.graalvm.compiler.hotspot.test.ReservedStackAccessTest 8213567 windows-all -org.graalvm.compiler.replacements.test.StringCompressInflateTest 8214947 +org.graalvm.compiler.hotspot.test.CheckGraalIntrinsics 8218698 diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/ProblemList.txt --- a/test/hotspot/jtreg/ProblemList.txt Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/ProblemList.txt Sun Feb 17 12:21:11 2019 +0000 @@ -82,7 +82,6 @@ runtime/handshake/HandshakeWalkSuspendExitTest.java 8214174 generic-all runtime/SharedArchiveFile/SASymbolTableTest.java 8193639 solaris-all -runtime/CompressedOops/UseCompressedOops.java 8079353 windows-all ############################################################################# @@ -164,7 +163,6 @@ vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java 8066993 generic-all vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java 8065773 generic-all vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java 8065773 generic-all -vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java 8068225 generic-all vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/compiler/c2/TestUseOptoBiasInliningWithoutEliminateLocks.java --- a/test/hotspot/jtreg/compiler/c2/TestUseOptoBiasInliningWithoutEliminateLocks.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/compiler/c2/TestUseOptoBiasInliningWithoutEliminateLocks.java Sun Feb 17 12:21:11 2019 +0000 @@ -40,7 +40,7 @@ * -XX:CompileCommand=compileonly,*.TestUseOptoBiasInliningWithoutEliminateLocks::dontinline_testMethod * -XX:CompileCommand=dontinline,*::dontinline_* * -XX:-EliminateLocks - * -XX:+WhiteBoxAPI -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -Xbatch * -XX:-TieredCompilation * compiler.c2.TestUseOptoBiasInliningWithoutEliminateLocks diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java --- a/test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java Sun Feb 17 12:21:11 2019 +0000 @@ -53,6 +53,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.vm.annotation.DontInline; import sun.hotspot.WhiteBox; +import sun.hotspot.code.NMethod; import java.io.IOException; import java.lang.annotation.Retention; @@ -695,10 +696,6 @@ public static final Unsafe U = Unsafe.getUnsafe(); interface Test { - boolean isCompiled(); - void assertNotCompiled(); - void assertCompiled(); - void call(T o); T receiver(int id); @@ -733,14 +730,6 @@ }; } - default void compile(Runnable r) { - assertNotCompiled(); - while(!isCompiled()) { - r.run(); - } - assertCompiled(); - } - default void initialize(Class... cs) { for (Class c : cs) { U.ensureClassInitialized(c); @@ -789,14 +778,31 @@ })); } - @Override - public boolean isCompiled() { return WB.isMethodCompiled(TEST); } + + public void compile(Runnable r) { + while (!WB.isMethodCompiled(TEST)) { + for (int i = 0; i < 100; i++) { + r.run(); + } + } + assertCompiled(); // record nmethod info + } + + private NMethod prevNM = null; - @Override - public void assertNotCompiled() { assertFalse(isCompiled()); } + public void assertNotCompiled() { + NMethod curNM = NMethod.get(TEST, false); + assertTrue(prevNM != null); // was previously compiled + assertTrue(curNM == null || prevNM.compile_id != curNM.compile_id); // either no nmethod present or recompiled + prevNM = curNM; // update nmethod info + } - @Override - public void assertCompiled() { assertTrue(isCompiled()); } + public void assertCompiled() { + NMethod curNM = NMethod.get(TEST, false); + assertTrue(curNM != null); // nmethod is present + assertTrue(prevNM == null || prevNM.compile_id == curNM.compile_id); // no recompilations if nmethod present + prevNM = curNM; // update nmethod info + } @Override public void call(T i) { diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template --- a/test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/compiler/unsafe/X-UnsafeAccessTest.java.template Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -156,15 +156,15 @@ static void testAccess(Object base, long offset) { // Plain { - UNSAFE.put$Type$(base, offset, $value1$); - $type$ x = UNSAFE.get$Type$(base, offset); + UNSAFE.put$MethodAffix$(base, offset, $value1$); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "set $type$ value"); } // Volatile { - UNSAFE.put$Type$Volatile(base, offset, $value2$); - $type$ x = UNSAFE.get$Type$Volatile(base, offset); + UNSAFE.put$MethodAffix$Volatile(base, offset, $value2$); + $type$ x = UNSAFE.get$MethodAffix$Volatile(base, offset); assertEquals(x, $value2$, "putVolatile $type$ value"); } @@ -172,8 +172,8 @@ #if[Ordered] // Lazy { - UNSAFE.putOrdered$Type$(base, offset, $value1$); - $type$ x = UNSAFE.get$Type$Volatile(base, offset); + UNSAFE.putOrdered$MethodAffix$(base, offset, $value1$); + $type$ x = UNSAFE.get$MethodAffix$Volatile(base, offset); assertEquals(x, $value1$, "putRelease $type$ value"); } #end[Ordered] @@ -182,15 +182,15 @@ #if[JdkInternalMisc] // Lazy { - UNSAFE.put$Type$Release(base, offset, $value1$); - $type$ x = UNSAFE.get$Type$Acquire(base, offset); + UNSAFE.put$MethodAffix$Release(base, offset, $value1$); + $type$ x = UNSAFE.get$MethodAffix$Acquire(base, offset); assertEquals(x, $value1$, "putRelease $type$ value"); } // Opaque { - UNSAFE.put$Type$Opaque(base, offset, $value2$); - $type$ x = UNSAFE.get$Type$Opaque(base, offset); + UNSAFE.put$MethodAffix$Opaque(base, offset, $value2$); + $type$ x = UNSAFE.get$MethodAffix$Opaque(base, offset); assertEquals(x, $value2$, "putOpaque $type$ value"); } #end[JdkInternalMisc] @@ -199,38 +199,38 @@ #if[Unaligned] // Unaligned { - UNSAFE.put$Type$Unaligned(base, offset, $value2$); - $type$ x = UNSAFE.get$Type$Unaligned(base, offset); + UNSAFE.put$MethodAffix$Unaligned(base, offset, $value2$); + $type$ x = UNSAFE.get$MethodAffix$Unaligned(base, offset); assertEquals(x, $value2$, "putUnaligned $type$ value"); } { - UNSAFE.put$Type$Unaligned(base, offset, $value1$, true); - $type$ x = UNSAFE.get$Type$Unaligned(base, offset, true); + UNSAFE.put$MethodAffix$Unaligned(base, offset, $value1$, true); + $type$ x = UNSAFE.get$MethodAffix$Unaligned(base, offset, true); assertEquals(x, $value1$, "putUnaligned big endian $type$ value"); } { - UNSAFE.put$Type$Unaligned(base, offset, $value2$, false); - $type$ x = UNSAFE.get$Type$Unaligned(base, offset, false); + UNSAFE.put$MethodAffix$Unaligned(base, offset, $value2$, false); + $type$ x = UNSAFE.get$MethodAffix$Unaligned(base, offset, false); assertEquals(x, $value2$, "putUnaligned little endian $type$ value"); } #end[Unaligned] #end[JdkInternalMisc] #if[CAS] - UNSAFE.put$Type$(base, offset, $value1$); + UNSAFE.put$MethodAffix$(base, offset, $value1$); // Compare { #if[JdkInternalMisc] - boolean r = UNSAFE.compareAndSet$Type$(base, offset, $value1$, $value2$); + boolean r = UNSAFE.compareAndSet$MethodAffix$(base, offset, $value1$, $value2$); assertEquals(r, true, "success compareAndSet $type$"); #else[JdkInternalMisc] - boolean r = UNSAFE.compareAndSwap$Type$(base, offset, $value1$, $value2$); + boolean r = UNSAFE.compareAndSwap$MethodAffix$(base, offset, $value1$, $value2$); assertEquals(r, true, "success compareAndSwap $type$"); #end[JdkInternalMisc] - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); #if[JdkInternalMisc] assertEquals(x, $value2$, "success compareAndSet $type$ value"); #else[JdkInternalMisc] @@ -240,13 +240,13 @@ { #if[JdkInternalMisc] - boolean r = UNSAFE.compareAndSet$Type$(base, offset, $value1$, $value3$); + boolean r = UNSAFE.compareAndSet$MethodAffix$(base, offset, $value1$, $value3$); assertEquals(r, false, "failing compareAndSet $type$"); #else[JdkInternalMisc] - boolean r = UNSAFE.compareAndSwap$Type$(base, offset, $value1$, $value3$); + boolean r = UNSAFE.compareAndSwap$MethodAffix$(base, offset, $value1$, $value3$); assertEquals(r, false, "failing compareAndSwap $type$"); #end[JdkInternalMisc] - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); #if[JdkInternalMisc] assertEquals(x, $value2$, "failing compareAndSet $type$ value"); #else[JdkInternalMisc] @@ -257,107 +257,107 @@ #if[JdkInternalMisc] // Advanced compare { - $type$ r = UNSAFE.compareAndExchange$Type$(base, offset, $value2$, $value1$); + $type$ r = UNSAFE.compareAndExchange$MethodAffix$(base, offset, $value2$, $value1$); assertEquals(r, $value2$, "success compareAndExchange $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "success compareAndExchange $type$ value"); } { - $type$ r = UNSAFE.compareAndExchange$Type$(base, offset, $value2$, $value3$); + $type$ r = UNSAFE.compareAndExchange$MethodAffix$(base, offset, $value2$, $value3$); assertEquals(r, $value1$, "failing compareAndExchange $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "failing compareAndExchange $type$ value"); } { - $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value2$); + $type$ r = UNSAFE.compareAndExchange$MethodAffix$Acquire(base, offset, $value1$, $value2$); assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value"); } { - $type$ r = UNSAFE.compareAndExchange$Type$Acquire(base, offset, $value1$, $value3$); + $type$ r = UNSAFE.compareAndExchange$MethodAffix$Acquire(base, offset, $value1$, $value3$); assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value"); } { - $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value1$); + $type$ r = UNSAFE.compareAndExchange$MethodAffix$Release(base, offset, $value2$, $value1$); assertEquals(r, $value2$, "success compareAndExchangeRelease $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value"); } { - $type$ r = UNSAFE.compareAndExchange$Type$Release(base, offset, $value2$, $value3$); + $type$ r = UNSAFE.compareAndExchange$MethodAffix$Release(base, offset, $value2$, $value3$); assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value"); } { boolean success = false; for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = UNSAFE.weakCompareAndSet$Type$Plain(base, offset, $value1$, $value2$); + success = UNSAFE.weakCompareAndSet$MethodAffix$Plain(base, offset, $value1$, $value2$); } assertEquals(success, true, "weakCompareAndSetPlain $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value"); } { boolean success = false; for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = UNSAFE.weakCompareAndSet$Type$Acquire(base, offset, $value2$, $value1$); + success = UNSAFE.weakCompareAndSet$MethodAffix$Acquire(base, offset, $value2$, $value1$); } assertEquals(success, true, "weakCompareAndSetAcquire $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { boolean success = false; for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = UNSAFE.weakCompareAndSet$Type$Release(base, offset, $value1$, $value2$); + success = UNSAFE.weakCompareAndSet$MethodAffix$Release(base, offset, $value1$, $value2$); } assertEquals(success, true, "weakCompareAndSetRelease $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } { boolean success = false; for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { - success = UNSAFE.weakCompareAndSet$Type$(base, offset, $value2$, $value1$); + success = UNSAFE.weakCompareAndSet$MethodAffix$(base, offset, $value2$, $value1$); } assertEquals(success, true, "weakCompareAndSet $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "weakCompareAndSet $type$"); } #end[JdkInternalMisc] - UNSAFE.put$Type$(base, offset, $value2$); + UNSAFE.put$MethodAffix$(base, offset, $value2$); // Compare set and get { - $type$ o = UNSAFE.getAndSet$Type$(base, offset, $value1$); + $type$ o = UNSAFE.getAndSet$MethodAffix$(base, offset, $value1$); assertEquals(o, $value2$, "getAndSet $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, $value1$, "getAndSet $type$ value"); } #end[CAS] #if[AtomicAdd] - UNSAFE.put$Type$(base, offset, $value1$); + UNSAFE.put$MethodAffix$(base, offset, $value1$); // get and add, add and get { - $type$ o = UNSAFE.getAndAdd$Type$(base, offset, $value2$); + $type$ o = UNSAFE.getAndAdd$MethodAffix$(base, offset, $value2$); assertEquals(o, $value1$, "getAndAdd $type$"); - $type$ x = UNSAFE.get$Type$(base, offset); + $type$ x = UNSAFE.get$MethodAffix$(base, offset); assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$"); } #end[AtomicAdd] @@ -368,8 +368,8 @@ static void testAccess(long address) { // Plain { - UNSAFE.put$Type$(address, $value1$); - $type$ x = UNSAFE.get$Type$(address); + UNSAFE.put$MethodAffix$(address, $value1$); + $type$ x = UNSAFE.get$MethodAffix$(address); assertEquals(x, $value1$, "set $type$ value"); } } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh --- a/test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/compiler/unsafe/generate-unsafe-access-tests.sh Sun Feb 17 12:21:11 2019 +0000 @@ -1,7 +1,7 @@ #!/bin/bash # -# Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../jdk/make/src/classes/build/tools/spp/Spp.java +javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java SPP=build.tools.spp.Spp @@ -41,6 +41,12 @@ Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}" args="-K$type -Dtype=$type -DType=$Type" + if [ "$Type" == "Object" -a "$package" == "jdk.internal.misc" ]; then + args="$args -DMethodAffix=Reference" + else + args="$args -DMethodAffix=$Type" + fi + case $type in Object|int|long) args="$args -KCAS -KOrdered" @@ -123,8 +129,10 @@ args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3" echo $args + out=${Qualifier}UnsafeAccessTest${Type}.java + rm -rf "$out" java $SPP -nel -K$Qualifier -Dpackage=$package -DQualifier=$Qualifier -Dmodule=$module \ - $args < X-UnsafeAccessTest.java.template > ${Qualifier}UnsafeAccessTest${Type}.java + $args -iX-UnsafeAccessTest.java.template -o$out done } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/compiler/whitebox/GetCodeHeapEntriesTest.java --- a/test/hotspot/jtreg/compiler/whitebox/GetCodeHeapEntriesTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/compiler/whitebox/GetCodeHeapEntriesTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, 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 @@ -77,7 +77,7 @@ CodeBlob blob = Arrays.stream(blobs) .filter(GetCodeHeapEntriesTest::filter) .findAny() - .get(); + .orElse(null); Asserts.assertNotNull(blob); Asserts.assertEQ(blob.code_blob_type, type); Asserts.assertGTE(blob.size, SIZE); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java --- a/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, 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 @@ -45,7 +45,9 @@ public static void main(String[] args) throws Exception { testCompressedOopsModesGCs(); - testCompressedOopsModesGCs("-XX:+UseLargePages"); + if (!Platform.isOSX() && !Platform.isAix()) { + testCompressedOopsModesGCs("-XX:+UseLargePages"); + } } public static void testCompressedOopsModesGCs(String... flags) throws Exception { @@ -73,7 +75,7 @@ Collections.addAll(args, flags2); if (Platform.is64bit()) { - // Explicitly turn of compressed oops + // Explicitly turn off compressed oops testCompressedOops(args, "-XX:-UseCompressedOops", "-Xmx32m") .shouldNotContain("Compressed Oops") .shouldHaveExitValue(0); @@ -88,11 +90,13 @@ .shouldContain("Compressed Oops mode") .shouldHaveExitValue(0); - // Skip the following three test cases if we're on OSX or Solaris. + // Skip the following seven test cases if we're on OSX, Windows, or Solaris. // - // OSX doesn't seem to care about HeapBaseMinAddress and Solaris - // puts the heap way up, forcing different behaviour. - if (!Platform.isOSX() && !Platform.isSolaris()) { + // OSX doesn't seem to care about HeapBaseMinAddress. Windows memory + // locations are affected by ASLR. Solaris puts the heap way up, + // forcing different behaviour. + if (!Platform.isOSX() && !Platform.isWindows() && !Platform.isSolaris()) { + // Larger than 4gb heap should result in zero based with shift 3 testCompressedOops(args, "-XX:+UseCompressedOops", "-Xmx5g") .shouldContain("Zero based") @@ -179,8 +183,8 @@ private static OutputAnalyzer testCompressedOops(ArrayList flags1, String... flags2) throws Exception { ArrayList args = new ArrayList<>(); - // Always run with these three: - args.add("-XX:+PrintCompressedOopsMode"); + // Always run with these two: + args.add("-Xlog:gc+heap+coops=trace"); args.add("-Xms32m"); // Add the extra flags diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * 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 MallocSiteTypeChange + * @bug 8200109 + * @key nmt jcmd + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteTypeChange + */ + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class MallocSiteTypeChange { + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Long.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + int pc = 1; + long addr = wb.NMTMallocWithPseudoStack(4 * 1024, pc); + + // Verify that current tracking level is "detail" + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=4KB, committed=4KB)"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Baseline succeeded"); + + wb.NMTFree(addr); + addr = wb.NMTMallocWithPseudoStackAndType(2 * 1024, pc, 7 /* mtInternal */ ); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("(malloc=0KB type=Test -4KB)"); + output.shouldContain("(malloc=2KB type=Internal +2KB #1 +1)"); + output.shouldHaveExitValue(0); + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/classFileParserBug/TestBadClassName.java --- a/test/hotspot/jtreg/runtime/classFileParserBug/TestBadClassName.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/runtime/classFileParserBug/TestBadClassName.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8158297 + * @bug 8158297 8218939 * @summary Constant pool utf8 entry for class name cannot have empty qualified name '//' * @compile p1/BadInterface1.jcod * @compile p1/BadInterface2.jcod @@ -37,20 +37,32 @@ System.out.println("Regression test for bug 8042660"); - // Test class name with p1//BadInterface2 + // Test class name with p1//BadInterface1 + String expected = "Illegal class name \"p1//BadInterface1\" in class file UseBadInterface1"; try { Class newClass = Class.forName("UseBadInterface1"); throw new RuntimeException("Expected ClassFormatError exception not thrown"); } catch (java.lang.ClassFormatError e) { + check(e, expected); System.out.println("Test UseBadInterface1 passed test case with illegal class name"); } // Test class name with p1/BadInterface2/ + expected = "Illegal class name \"p1/BadInterface2/\" in class file UseBadInterface2"; try { Class newClass = Class.forName("UseBadInterface2"); throw new RuntimeException("Expected ClassFormatError exception not thrown"); } catch (java.lang.ClassFormatError e) { - System.out.println("Test UseBadInterface1 passed test case with illegal class name"); + check(e, expected); + System.out.println("Test UseBadInterface2 passed test case with illegal class name"); + } + } + + static void check(ClassFormatError c, String expected) { + if (!c.getMessage().equals(expected)) { + throw new RuntimeException("Wrong ClassFormatError - expected: \"" + + expected + "\", got \"" + + c.getMessage() + "\""); } } } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/containers/docker/TestCPUAwareness.java --- a/test/hotspot/jtreg/runtime/containers/docker/TestCPUAwareness.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/runtime/containers/docker/TestCPUAwareness.java Sun Feb 17 12:21:11 2019 +0000 @@ -175,7 +175,7 @@ System.out.println("cpuset = " + cpuset); System.out.println("quota = " + quota); System.out.println("period = " + period); - System.out.println("shares = " + period); + System.out.println("shares = " + shares); System.out.println("usePreferContainerQuotaForCPUCount = " + usePreferContainerQuotaForCPUCount); System.out.println("expectedAPC = " + expectedAPC); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/defineAnonClass/AnonSymbolLeak.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/defineAnonClass/AnonSymbolLeak.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,75 @@ +/* + * 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. + */ + +// This is copied from DefineAnon to test Symbol Refcounting for the package prepended name. + +package p1; + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.misc.Unsafe; + + +class T { + static protected void test0() { System.out.println("test0 (public)"); } + static protected void test1() { System.out.println("test1 (protected)"); } + static /*package-private*/ void test2() { System.out.println("test2 (package)"); } + static private void test3() { System.out.println("test3 (private)"); } +} + +public class AnonSymbolLeak { + + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + static Class getAnonClass(Class hostClass, final String className) { + final String superName = "java/lang/Object"; + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, "test", "()V", null, null); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test0", "()V", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test1", "()V", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test2", "()V", false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "p1/T", "test3", "()V", false); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + final byte[] classBytes = cw.toByteArray(); + Class invokerClass = UNSAFE.defineAnonymousClass(hostClass, classBytes, new Object[0]); + UNSAFE.ensureClassInitialized(invokerClass); + return invokerClass; + } + + public static void test() throws Throwable { + // AnonClass is injected into package p1. + System.out.println("Injecting from the same package (p1):"); + Class p1cls = getAnonClass(T.class, "AnonClass"); + p1cls.getMethod("test").invoke(null); + } + + public static void main(java.lang.String[] unused) throws Throwable { + test(); + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/defineAnonClass/DefineAnon.java --- a/test/hotspot/jtreg/runtime/defineAnonClass/DefineAnon.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/runtime/defineAnonClass/DefineAnon.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 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 @@ -27,6 +27,7 @@ * @library /testlibrary * @modules java.base/jdk.internal.org.objectweb.asm * java.management + * java.base/jdk.internal.misc * @compile -XDignore.symbol.file=true DefineAnon.java * @run main/othervm p1.DefineAnon */ @@ -36,7 +37,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; class T { @@ -48,17 +49,7 @@ public class DefineAnon { - private static Unsafe getUnsafe() { - try { - java.lang.reflect.Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe"); - singleoneInstanceField.setAccessible(true); - return (Unsafe) singleoneInstanceField.get(null); - } catch (Throwable ex) { - throw new RuntimeException("Was unable to get Unsafe instance."); - } - } - - static Unsafe UNSAFE = DefineAnon.getUnsafe(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); static Class getAnonClass(Class hostClass, final String className) { final String superName = "java/lang/Object"; diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/defineAnonClass/TestAnonSymbolLeak.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/runtime/defineAnonClass/TestAnonSymbolLeak.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,77 @@ +/* + * 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 TestAnonSymbolLeak + * @bug 8218755 + * @requires vm.opt.final.ClassUnloading + * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.org.objectweb.asm + * java.management + * @library /test/lib /runtime/testlibrary + * @build p1.AnonSymbolLeak + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -Xlog:class+unload -XX:+WhiteBoxAPI TestAnonSymbolLeak + */ + +import java.lang.reflect.Method; +import sun.hotspot.WhiteBox; +import jdk.test.lib.Asserts; + +public class TestAnonSymbolLeak { + static String className = "p1.AnonSymbolLeak"; + + private static class ClassUnloadTestMain { + public static void test() throws Exception { + // Load the AnonSymbolLeak class in a new class loader, run it, which loads + // an unsafe anonymous class in the same package p1. Then unload it. + // Then test that the refcount of the symbol created for the prepended name doesn't leak. + ClassLoader cl = ClassUnloadCommon.newClassLoader(); + Class c = cl.loadClass(className); + c.getMethod("test").invoke(null); + cl = null; c = null; + ClassUnloadCommon.triggerUnloading(); + } + } + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String oldName = "AnonClass"; + String prependedName = "p1/AnonClass"; + ClassUnloadCommon.failIf(wb.isClassAlive(className), "should not be loaded"); + int countBeforeOld = wb.getSymbolRefcount(oldName); + int countBefore = wb.getSymbolRefcount(prependedName); + ClassUnloadTestMain.test(); + ClassUnloadCommon.failIf(wb.isClassAlive(className), "should be unloaded"); + int countAfterOld = wb.getSymbolRefcount(oldName); + int countAfter = wb.getSymbolRefcount(prependedName); + Asserts.assertEquals(countBeforeOld, countAfterOld); // no leaks to the old name + System.out.println("count before and after " + countBeforeOld + " " + countAfterOld); + Asserts.assertEquals(countBefore, countAfter); // no leaks to the prepended name + System.out.println("count before and after " + countBefore + " " + countAfter); + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/defineAnonClass/UnsafeDefMeths.java --- a/test/hotspot/jtreg/runtime/defineAnonClass/UnsafeDefMeths.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/runtime/defineAnonClass/UnsafeDefMeths.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -28,6 +28,7 @@ * @library /testlibrary * @modules java.base/jdk.internal.org.objectweb.asm * java.management + * java.base/jdk.internal.misc * @compile -XDignore.symbol.file=true UnsafeDefMeths.java * @run main UnsafeDefMeths */ @@ -35,7 +36,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Type; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.lang.invoke.MethodType; import java.lang.reflect.Field; @@ -57,18 +58,7 @@ public class UnsafeDefMeths { - static final Unsafe UNSAFE; - - static { - try { - Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - UNSAFE = (Unsafe) unsafeField.get(null); - } - catch (Exception e) { - throw new InternalError(e); - } - } + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); interface Resource { Pointer ptr(); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/runtime/logging/SafepointTest.java --- a/test/hotspot/jtreg/runtime/logging/SafepointTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/runtime/logging/SafepointTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, 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 @@ -40,10 +40,9 @@ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:safepoint=trace", InnerClass.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("Safepoint synchronization initiated. ("); + output.shouldContain("Safepoint synchronization initiated"); output.shouldContain("Entering safepoint region: "); output.shouldContain("Leaving safepoint region"); - output.shouldContain("_at_poll_safepoint"); output.shouldHaveExitValue(0); } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/serviceability/dcmd/framework/HelpTest.java --- a/test/hotspot/jtreg/serviceability/dcmd/framework/HelpTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/HelpTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -33,6 +33,7 @@ * @test * @summary Test of diagnostic command help (tests all DCMD executors) * @library /test/lib + * /vmTestbase * @modules java.base/jdk.internal.misc * java.compiler * java.management @@ -55,7 +56,13 @@ @Test public void mainClass() { - run(new MainClassJcmdExecutor()); + TestProcessLauncher t = new TestProcessLauncher(Process.class.getName()); + try { + t.launch(); + run(new MainClassJcmdExecutor(Process.class.getName())); + } finally { + t.quit(); + } } @Test @@ -68,4 +75,6 @@ run(new JMXExecutor()); } + private static class Process extends TestJavaProcess { + } } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/serviceability/dcmd/framework/InvalidCommandTest.java --- a/test/hotspot/jtreg/serviceability/dcmd/framework/InvalidCommandTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/InvalidCommandTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -33,6 +33,7 @@ * @test * @summary Test of invalid diagnostic command (tests all DCMD executors) * @library /test/lib + * /vmTestbase * @modules java.base/jdk.internal.misc * java.compiler * java.management @@ -53,7 +54,13 @@ @Test public void mainClass() { - run(new MainClassJcmdExecutor()); + TestProcessLauncher t = new TestProcessLauncher(Process.class.getName()); + try { + t.launch(); + run(new MainClassJcmdExecutor(Process.class.getName())); + } finally { + t.quit(); + } } @Test @@ -65,4 +72,7 @@ public void jmx() { run(new JMXExecutor()); } + + private static class Process extends TestJavaProcess { + } } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/serviceability/dcmd/framework/TEST.properties --- a/test/hotspot/jtreg/serviceability/dcmd/framework/TEST.properties Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -exclusiveAccess.dirs=. - diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/serviceability/dcmd/framework/TestJavaProcess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestJavaProcess.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,61 @@ +/* + * 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. + */ + +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * A simple process that connects to a pipe and waits for command "quit" to + * be received. + * + * Usage: java TestJavaProcess -pipe.port + */ + +public class TestJavaProcess { + + static final int PASSED = 0; + static final int FAILED = 2; + + public static void main(String argv[]) { + + log("Test Java process started!"); + + ArgumentHandler argHandler = new ArgumentHandler(argv); + IOPipe pipe = argHandler.createDebugeeIOPipe(); + pipe.println("ready"); + log("Waiting for the quit command from the test ..."); + String cmd = pipe.readln(); + int exitCode = PASSED; + if (cmd.equals("quit")) { + log("'quit' received"); + } else { + log("Invalid command received " + cmd); + exitCode = FAILED; + } + System.exit(exitCode); + } + + private static void log(String message) { + System.out.println(message); + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,78 @@ + +/* + * 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. + */ + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdi.*; + +/** + * Launches a new Java process that uses a communication pipe to interact + * with the test. + */ + +public class TestProcessLauncher { + + private final String className; + private final ArgumentHandler argHandler; + + private IOPipe pipe; + + public TestProcessLauncher(String className, ArgumentHandler argHandler) { + this.className = className; + this.argHandler = argHandler; + } + + public TestProcessLauncher(String className) { + this(className, new ArgumentHandler(new String[0])); + } + + public Process launch() { + + String java = argHandler.getLaunchExecPath(); + + Log log = new Log(System.out, argHandler); + Binder binder = new Binder(argHandler, log); + binder.prepareForPipeConnection(argHandler); + + String cmd = java + " " + className + " -pipe.port=" + argHandler.getPipePort(); + + Debugee debuggee = binder.startLocalDebugee(cmd); + debuggee.redirectOutput(log); + + pipe = new IOPipe(debuggee); + + String line = pipe.readln(); + if (!"ready".equals(line)) { + System.out.println("Wrong reply received:" + line); + } + return debuggee.getProcess(); + } + + public void quit() { + if (pipe != null) { + pipe.println("quit"); + } + } + +} diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/serviceability/dcmd/framework/VMVersionTest.java --- a/test/hotspot/jtreg/serviceability/dcmd/framework/VMVersionTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/VMVersionTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -27,6 +27,7 @@ import jdk.test.lib.dcmd.MainClassJcmdExecutor; import jdk.test.lib.dcmd.FileJcmdExecutor; import jdk.test.lib.dcmd.JMXExecutor; +import nsk.share.jdi.ArgumentHandler; import org.testng.annotations.Test; @@ -34,6 +35,8 @@ * @test * @summary Test of diagnostic command VM.version (tests all DCMD executors) * @library /test/lib + * /vmTestbase + * @build TestJavaProcess * @modules java.base/jdk.internal.misc * java.compiler * java.management @@ -53,7 +56,13 @@ @Test public void mainClass() { - run(new MainClassJcmdExecutor()); + TestProcessLauncher t = new TestProcessLauncher(Process.class.getName()); + try { + t.launch(); + run(new MainClassJcmdExecutor(Process.class.getName())); + } finally { + t.quit(); + } } @Test @@ -65,4 +74,6 @@ public void jmx() { run(new JMXExecutor()); } + + private static class Process extends TestJavaProcess{} } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod008.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -192,11 +192,11 @@ try { retValue = testedClass.invokeMethod(thread, method, params, 0); if ( ((PrimitiveValue )retValue).intValue() == Consts.TEST_FAILED ) { - complain("VMDisconnectException is not thrown"); + complain("VMDisconnectedException is not thrown"); exitStatus = Consts.TEST_FAILED; } } catch(VMDisconnectedException e) { - display("!!!expected VMDisconnectException"); + display("!!!expected VMDisconnectedException"); notifyVMDisconnect(); } catch(Exception e) { complain("Unexpected " + e); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/newInstance/newinstance008.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -203,11 +203,11 @@ try { retValue = testedClass.newInstance(thread, method, params, 0); if ( ((PrimitiveValue )retValue).intValue() == Consts.TEST_FAILED ) { - complain("VMDisconnectException is not thrown"); + complain("VMDisconnectedException is not thrown"); exitStatus = Consts.TEST_FAILED; } } catch(VMDisconnectedException e) { - display("!!!expected VMDisconnectException"); + display("!!!expected VMDisconnectedException"); notifyVMDisconnect(); } catch(Exception e) { complain("Unexpected " + e); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -343,7 +343,7 @@ { // to get mainThread suspended; otherwise its end results in // no suspention for breakpointRequest2 (bug or not?), end of test, - // and VMDisconnectException + // and VMDisconnectedException thread2Ref.suspend(); log2("......eventSet.resume();"); eventSet.resume(); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -346,7 +346,7 @@ { // to get mainThread suspended; otherwise its end results in // no suspention for breakpointRequest2 (bug or not?), end of test, - // and VMDisconnectException + // and VMDisconnectedException thread2Ref.suspend(); log2("......eventSet.resume();"); eventSet.resume(); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canBeModified/canbemodified001.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -78,6 +78,7 @@ exitStatus = Consts.TEST_FAILED; e.printStackTrace(); } finally { + debugee.resume(); debugee.endDebugee(); } display("Test finished. exitStatus = " + exitStatus); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose005.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -79,7 +79,7 @@ * The debugger : * clears interruption status,
    * invokes vm.dispose() that results in
    - * VMDisconnectException in the thread2
    + * VMDisconnectedException in the thread2
    * which has been suspended after invoking "runt2"
    * but after exception it is resumed and sends interruption
    * to the main thread;
    diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -557,6 +557,7 @@ * exit status code. */ public int endDebugee() { + int status = waitFor(); if (vm != null) { try { vm.dispose(); @@ -564,7 +565,7 @@ } vm = null; } - return waitFor(); + return status; } /* diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -175,7 +175,7 @@ * Make preperation for IOPipe connection before starting debugee VM process. * May change options in the passed argumentHandler. */ - protected void prepareForPipeConnection(DebugeeArgumentHandler argumentHandler) { + public void prepareForPipeConnection(DebugeeArgumentHandler argumentHandler) { if (argumentHandler.isTransportAddressDynamic()) { try { pipeServerSocket = new ServerSocket(); diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/StressClassLoadingTest.java --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/StressClassLoadingTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/anonloader/share/StressClassLoadingTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -169,7 +169,7 @@ c = CustomClassLoaders.makeClassBytesLoader(classBytes, className) .loadClass(className); } - c.newInstance(); + UnsafeAccess.unsafe.ensureClassInitialized(c); } catch (Throwable e) { Env.traceVerbose(e, "parser caught exception"); } diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/vm/mlvm/share/jdi/JDIBreakpointTest.java --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/jdi/JDIBreakpointTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/jdi/JDIBreakpointTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -45,6 +45,7 @@ import com.sun.jdi.ThreadReference; import com.sun.jdi.Value; import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; import com.sun.jdi.event.BreakpointEvent; import com.sun.jdi.event.ClassPrepareEvent; import com.sun.jdi.event.Event; @@ -358,8 +359,12 @@ } }.go(); - if (!debuggee.terminated()) - debuggee.endDebugee(); + if (!debuggee.terminated()) { + try { + debuggee.dispose(); + } catch (VMDisconnectedException ignore) { + } + } debuggee.waitFor(); return true; diff -r 4964feb6d75d -r de9dd71ef18c test/hotspot/jtreg/vmTestbase/vm/mlvm/share/mlvmJvmtiUtils.cpp --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/mlvmJvmtiUtils.cpp Sun Feb 17 12:20:37 2019 +0000 +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/share/mlvmJvmtiUtils.cpp Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -47,6 +47,23 @@ pEnv->ReleaseStringUTFChars(src, pStr); } + +/** + * Helper class to track JVMTI resources, deallocating the resource in the destructor. + */ +class JvmtiResource { +private: + jvmtiEnv* const _jvmtiEnv; + void* const _ptr; + +public: + JvmtiResource(jvmtiEnv* jvmtiEnv, void* ptr) : _jvmtiEnv(jvmtiEnv), _ptr(ptr) { } + + ~JvmtiResource() { + NSK_JVMTI_VERIFY(_jvmtiEnv->Deallocate((unsigned char*)_ptr)); + } +}; + struct MethodName * getMethodName(jvmtiEnv * pJvmtiEnv, jmethodID method) { char * szName; char * szSignature; @@ -57,22 +74,31 @@ return NULL; } + JvmtiResource szNameResource(pJvmtiEnv, szName); + if (!NSK_JVMTI_VERIFY(pJvmtiEnv->GetMethodDeclaringClass(method, &clazz))) { - NSK_JVMTI_VERIFY(pJvmtiEnv->Deallocate((unsigned char*) szName)); return NULL; } if (!NSK_JVMTI_VERIFY(pJvmtiEnv->GetClassSignature(clazz, &szSignature, NULL))) { - NSK_JVMTI_VERIFY(pJvmtiEnv->Deallocate((unsigned char*) szName)); return NULL; } + JvmtiResource szSignatureResource(pJvmtiEnv, szSignature); + + if (strlen(szName) + 1 > sizeof(mn->methodName) || + strlen(szSignature) + 1 > sizeof(mn->classSig)) { + return NULL; + } + mn = (MethodName*) malloc(sizeof(MethodNameStruct)); + if (mn == NULL) { + return NULL; + } + strncpy(mn->methodName, szName, sizeof(mn->methodName)); strncpy(mn->classSig, szSignature, sizeof(mn->classSig)); - NSK_JVMTI_VERIFY(pJvmtiEnv->Deallocate((unsigned char*) szName)); - NSK_JVMTI_VERIFY(pJvmtiEnv->Deallocate((unsigned char*) szSignature)); return mn; } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/ProblemList-graal.txt --- a/test/jdk/ProblemList-graal.txt Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/ProblemList-graal.txt Sun Feb 17 12:21:11 2019 +0000 @@ -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 @@ -92,6 +92,8 @@ com/sun/jdi/EarlyReturnTest.java 8195635 generic-all com/sun/jdi/EarlyReturnTest.java 8195635 generic-all +com/sun/jdi/RedefineCrossEvent.java 8218396 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 4964feb6d75d -r de9dd71ef18c test/jdk/com/sun/jdi/BasicJDWPConnectionTest.java --- a/test/jdk/com/sun/jdi/BasicJDWPConnectionTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/com/sun/jdi/BasicJDWPConnectionTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -33,9 +33,11 @@ import java.net.Socket; import java.net.SocketException; +import jdk.test.lib.Utils; import jdk.test.lib.apps.LingeredApp; import java.util.ArrayList; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -72,13 +74,27 @@ } private static Pattern listenRegexp = Pattern.compile("Listening for transport \\b(.+)\\b at address: \\b(\\d+)\\b"); - private static int detectPort(String s) { - Matcher m = listenRegexp.matcher(s); - if (!m.find()) { - throw new RuntimeException("Could not detect port from '" + s + "'"); + private static int detectPort(LingeredApp app) { + long maxWaitTime = System.currentTimeMillis() + + Utils.adjustTimeout(10000); // 10 seconds adjusted for TIMEOUT_FACTOR + while (true) { + String s = app.getProcessStdout(); + Matcher m = listenRegexp.matcher(s); + if (m.find()) { + // m.group(1) is transport, m.group(2) is port + return Integer.parseInt(m.group(2)); + } + if (System.currentTimeMillis() > maxWaitTime) { + throw new RuntimeException("Could not detect port from '" + s + "' (timeout)"); + } + try { + if (app.getProcess().waitFor(500, TimeUnit.MILLISECONDS)) { + throw new RuntimeException("Could not detect port from '" + s + "' (debuggee is terminated)"); + } + } catch (InterruptedException e) { + // ignore + } } - // m.group(1) is transport, m.group(2) is port - return Integer.parseInt(m.group(2)); } public static void positiveTest(String testName, String allowOpt) @@ -89,7 +105,7 @@ LingeredApp a = LingeredApp.startApp(cmd); int res; try { - res = handshake(detectPort(a.getProcessStdout())); + res = handshake(detectPort(a)); } finally { a.stopApp(); } @@ -107,7 +123,7 @@ LingeredApp a = LingeredApp.startApp(cmd); int res; try { - res = handshake(detectPort(a.getProcessStdout())); + res = handshake(detectPort(a)); } finally { a.stopApp(); } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/com/sun/jdi/RepStep.java --- a/test/jdk/com/sun/jdi/RepStep.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/com/sun/jdi/RepStep.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, 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 @@ -27,6 +27,7 @@ * @summary RepStep detects missed step events due to lack of * frame pop events (in back-end). * @author Robert Field + * @library /test/lib * * @run compile -g RepStepTarg.java * @run build VMConnection RepStep @@ -37,6 +38,7 @@ import com.sun.jdi.event.*; import com.sun.jdi.request.*; import com.sun.jdi.connect.*; +import jdk.test.lib.process.StreamPumper; import java.util.*; @@ -90,6 +92,7 @@ EventSet set = queue.remove(); for (EventIterator it = set.eventIterator(); it.hasNext(); ) { Event event = it.nextEvent(); + System.out.println("event: " + String.valueOf(event)); if (event instanceof VMStartEvent) { // get thread for setting step later thread = ((VMStartEvent)event).thread(); @@ -165,6 +168,23 @@ optionsArg.setValue(VMConnection.getDebuggeeVMOptions()); vm = launcher.launch(connectorArgs); + // redirect stdout/stderr + new StreamPumper(vm.process().getInputStream()) + .addPump(new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + System.out.println("[debugee_stdout] " + line); + } + }) + .process(); + new StreamPumper(vm.process().getErrorStream()) + .addPump(new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + System.err.println("[debugee_stderr] " + line); + } + }) + .process(); System.out.println("launched: " + TARGET); } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/com/sun/net/httpserver/bugs/HandlerConnectionClose.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/com/sun/net/httpserver/bugs/HandlerConnectionClose.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,437 @@ +/* + * 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 8218554 + * @summary test that the handler can request a connection close. + * @library /test/lib + * @build jdk.test.lib.net.SimpleSSLContext + * @run main/othervm HandlerConnectionClose + */ + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.logging.StreamHandler; +import jdk.test.lib.net.SimpleSSLContext; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; + +public class HandlerConnectionClose +{ + static final int ONEK = 1024; + static final long POST_SIZE = ONEK * 1L; + SSLContext sslContext; + Logger logger; + + void test(String[] args) throws Exception { + + HttpServer httpServer = startHttpServer("http"); + try { + testHttpURLConnection(httpServer, "http","/close/legacy/http/chunked"); + testHttpURLConnection(httpServer, "http","/close/legacy/http/fixed"); + testPlainSocket(httpServer, "http","/close/plain/http/chunked"); + testPlainSocket(httpServer, "http","/close/plain/http/fixed"); + } finally { + httpServer.stop(0); + } + sslContext = new SimpleSSLContext().get(); + HttpServer httpsServer = startHttpServer("https"); + try { + testHttpURLConnection(httpsServer, "https","/close/legacy/https/chunked"); + testHttpURLConnection(httpsServer, "https","/close/legacy/https/fixed"); + testPlainSocket(httpsServer, "https","/close/plain/https/chunked"); + testPlainSocket(httpsServer, "https","/close/plain/https/fixed"); + } finally{ + httpsServer.stop(0); + } + } + + void testHttpURLConnection(HttpServer httpServer, String protocol, String path) throws Exception { + int port = httpServer.getAddress().getPort(); + String host = httpServer.getAddress().getHostString(); + URL url = new URI(protocol, null, host, port, path, null, null).toURL(); + HttpURLConnection uc = (HttpURLConnection) url.openConnection(); + if ("https".equalsIgnoreCase(protocol)) { + ((HttpsURLConnection)uc).setSSLSocketFactory(sslContext.getSocketFactory()); + ((HttpsURLConnection)uc).setHostnameVerifier((String hostname, SSLSession session) -> true); + } + uc.setDoOutput(true); + uc.setRequestMethod("POST"); + uc.setFixedLengthStreamingMode(POST_SIZE); + OutputStream os = uc.getOutputStream(); + + /* create a 1K byte array with data to POST */ + byte[] ba = new byte[ONEK]; + for (int i = 0; i < ONEK; i++) + ba[i] = (byte) i; + + System.out.println("\n" + uc.getClass().getSimpleName() +": POST " + url + " HTTP/1.1"); + long times = POST_SIZE / ONEK; + for (int i = 0; i < times; i++) { + os.write(ba); + } + + os.close(); + InputStream is = uc.getInputStream(); + int read; + long count = 0; + while ((read = is.read(ba)) != -1) { + for (int i = 0; i < read; i++) { + byte expected = (byte) count++; + if (ba[i] != expected) { + throw new IOException("byte mismatch at " + + (count - 1) + ": expected " + expected + " got " + ba[i]); + } + } + } + if (count != POST_SIZE) { + throw new IOException("Unexpected length: " + count + " expected " + POST_SIZE); + } + is.close(); + + pass(); + } + + void testPlainSocket(HttpServer httpServer, String protocol, String path) throws Exception { + int port = httpServer.getAddress().getPort(); + String host = httpServer.getAddress().getHostString(); + URL url = new URI(protocol, null, host, port, path, null, null).toURL(); + Socket socket; + if ("https".equalsIgnoreCase(protocol)) { + socket = sslContext.getSocketFactory().createSocket(host, port); + } else { + socket = new Socket(host, port); + } + try (Socket sock = socket) { + OutputStream os = socket.getOutputStream(); + + // send request headers + String request = new StringBuilder() + .append("POST ").append(path).append(" HTTP/1.1").append("\r\n") + .append("host: ").append(host).append(':').append(port).append("\r\n") + .append("Content-Length: ").append(POST_SIZE).append("\r\n") + .append("\r\n") + .toString(); + os.write(request.getBytes(StandardCharsets.US_ASCII)); + + /* create a 1K byte array with data to POST */ + byte[] ba = new byte[ONEK]; + for (int i = 0; i < ONEK; i++) + ba[i] = (byte) i; + + // send request data + long times = POST_SIZE / ONEK; + for (int i = 0; i < times; i++) { + os.write(ba); + } + os.flush(); + + InputStream is = socket.getInputStream(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + // read all response headers + int c; + int crlf = 0; + while ((c = is.read()) != -1) { + if (c == '\r') continue; + if (c == '\n') crlf++; + else crlf = 0; + bos.write(c); + if (crlf == 2) break; + } + String responseHeadersStr = bos.toString(StandardCharsets.US_ASCII); + List responseHeaders = List.of(responseHeadersStr.split("\n")); + System.out.println("\nPOST " + url + " HTTP/1.1"); + responseHeaders.stream().forEach(s -> System.out.println("[reply]\t" + s)); + String statusLine = responseHeaders.get(0); + if (!statusLine.startsWith("HTTP/1.1 200 ")) + throw new IOException("Unexpected status: " + statusLine); + String cl = responseHeaders.stream() + .map(s -> s.toLowerCase(Locale.ROOT)) + .filter(s -> s.startsWith("content-length: ")) + .findFirst() + .orElse(null); + String te = responseHeaders.stream() + .map(s -> s.toLowerCase(Locale.ROOT)) + .filter(s -> s.startsWith("transfer-encoding: ")) + .findFirst() + .orElse(null); + + // check content-length and transfer-encoding are as expected + int read = 0; + long count = 0; + if (path.endsWith("/fixed")) { + if (!("content-length: " + POST_SIZE).equalsIgnoreCase(cl)) { + throw new IOException("Unexpected Content-Length: [" + cl + "]"); + } + if (te != null) { + throw new IOException("Unexpected Transfer-Encoding: [" + te + "]"); + } + // Got expected Content-Length: 1024 - read response data + while ((read = is.read()) != -1) { + int expected = (int) (count & 0xFF); + if ((read & 0xFF) != expected) { + throw new IOException("byte mismatch at " + + (count - 1) + ": expected " + expected + " got " + read); + } + if (++count == POST_SIZE) break; + } + } else if (cl != null) { + throw new IOException("Unexpected Content-Length: [" + cl + "]"); + } else { + if (!("transfer-encoding: chunked").equalsIgnoreCase(te)) { + throw new IOException("Unexpected Transfer-Encoding: [" + te + "]"); + } + // This is a quick & dirty implementation of + // chunk decoding - no trailers - no extensions + StringBuilder chunks = new StringBuilder(); + int cs = -1; + while (cs != 0) { + cs = 0; + chunks.setLength(0); + + // read next chunk length + while ((read = is.read()) != -1) { + if (read == '\r') continue; + if (read == '\n') break; + chunks.append((char) read); + } + cs = Integer.parseInt(chunks.toString().trim(), 16); + System.out.println("Got chunk length: " + cs); + + // If chunk size is 0, then we have read the last chunk. + if (cs == 0) break; + + // Read the chunk data + while (--cs >= 0) { + read = is.read(); + if (read == -1) break; // EOF + int expected = (int) (count & 0xFF); + if ((read & 0xFF) != expected) { + throw new IOException("byte mismatch at " + + (count - 1) + ": expected " + expected + " got " + read); + } + // This is cheating: we know the size :-) + if (++count == POST_SIZE) break; + } + + if (read == -1) { + throw new IOException("Unexpected EOF after " + count + " data bytes"); + } + + // read CRLF + if ((read = is.read()) != '\r') { + throw new IOException("Expected CR at " + count + "after chunk data - got " + read); + } + if ((read = is.read()) != '\n') { + throw new IOException("Expected LF at " + count + "after chunk data - got " + read); + } + + if (cs == 0 && count == POST_SIZE) { + cs = -1; + } + + if (cs != -1) { + // count == POST_SIZE, but some chunk data still to be read? + throw new IOException("Unexpected chunk size, " + + cs + " bytes still to read after " + count + + " data bytes received."); + } + } + // Last CRLF? + for (int i = 0; i < 2; i++) { + if ((read = is.read()) == -1) break; + } + } + + if (count != POST_SIZE) { + throw new IOException("Unexpected length: " + count + " expected " + POST_SIZE); + } + + if (!sock.isClosed()) { + try { + // We send an end request to the server to verify that the + // connection is closed. If the server has not closed the + // connection, it will reply. If we receive a response, + // we should fail... + String endrequest = new StringBuilder() + .append("GET ").append("/close/end").append(" HTTP/1.1").append("\r\n") + .append("host: ").append(host).append(':').append(port).append("\r\n") + .append("Content-Length: ").append(0).append("\r\n") + .append("\r\n") + .toString(); + os.write(endrequest.getBytes(StandardCharsets.US_ASCII)); + os.flush(); + StringBuilder resp = new StringBuilder(); + crlf = 0; + + // read all headers. + // If the server closed the connection as expected + // we should immediately read EOF + while ((read = is.read()) != -1) { + if (read == '\r') continue; + if (read == '\n') crlf++; + else crlf = 0; + if (crlf == 2) break; + resp.append((char) read); + } + + List lines = List.of(resp.toString().split("\n")); + if (read != -1 || resp.length() != 0) { + System.err.println("Connection not closed!"); + System.err.println("Got: "); + lines.stream().forEach(s -> System.err.println("[end]\t" + s)); + throw new AssertionError("EOF not received after " + count + " data bytes"); + } + if (read != -1) { + throw new AssertionError("EOF was expected after " + count + " bytes, but got: " + read); + } else { + System.out.println("Got expected EOF (" + read + ")"); + } + } catch (IOException x) { + // expected! all is well + System.out.println("Socket closed as expected, got exception writing to it."); + } + } else { + System.out.println("Socket closed as expected"); + } + pass(); + } + } + + /** + * Http Server + */ + HttpServer startHttpServer(String protocol) throws IOException { + if (debug) { + logger = Logger.getLogger("com.sun.net.httpserver"); + Handler outHandler = new StreamHandler(System.out, + new SimpleFormatter()); + outHandler.setLevel(Level.FINEST); + logger.setLevel(Level.FINEST); + logger.addHandler(outHandler); + } + + InetSocketAddress serverAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + HttpServer httpServer = null; + if ("http".equalsIgnoreCase(protocol)) { + httpServer = HttpServer.create(serverAddress, 0); + } + if ("https".equalsIgnoreCase(protocol)) { + HttpsServer httpsServer = HttpsServer.create(serverAddress, 0); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext)); + httpServer = httpsServer; + } + httpServer.createContext("/close/", new MyHandler(POST_SIZE)); + System.out.println("Server created at: " + httpServer.getAddress()); + httpServer.start(); + return httpServer; + } + + class MyHandler implements HttpHandler { + static final int BUFFER_SIZE = 512; + final long expected; + + MyHandler(long expected){ + this.expected = expected; + } + + @Override + public void handle(HttpExchange t) throws IOException { + System.out.println("Server: serving " + t.getRequestURI()); + boolean chunked = t.getRequestURI().getPath().endsWith("/chunked"); + boolean fixed = t.getRequestURI().getPath().endsWith("/fixed"); + boolean end = t.getRequestURI().getPath().endsWith("/end"); + long responseLength = fixed ? POST_SIZE : 0; + responseLength = end ? -1 : responseLength; + responseLength = chunked ? 0 : responseLength; + + if (!end) t.getResponseHeaders().add("connection", "CLose"); + t.sendResponseHeaders(200, responseLength); + + if (!end) { + OutputStream os = t.getResponseBody(); + InputStream is = t.getRequestBody(); + byte[] ba = new byte[BUFFER_SIZE]; + int read; + long count = 0L; + while ((read = is.read(ba)) != -1) { + count += read; + os.write(ba, 0, read); + } + is.close(); + + check(count == expected, "Expected: " + expected + ", received " + + count); + debug("Received " + count + " bytes"); + os.close(); + } + + t.close(); + } + } + + //--------------------- Infrastructure --------------------------- + boolean debug = true; + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} + void debug(String message) {if(debug) { System.out.println(message); } } + public static void main(String[] args) throws Throwable { + Class k = new Object(){}.getClass().getEnclosingClass(); + try {k.getMethod("instanceMain",String[].class) + .invoke( k.newInstance(), (Object) args);} + catch (Throwable e) {throw e.getCause();}} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + +} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/Collection/IteratorMicroBenchmark.java --- a/test/jdk/java/util/Collection/IteratorMicroBenchmark.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/Collection/IteratorMicroBenchmark.java Sun Feb 17 12:21:11 2019 +0000 @@ -69,8 +69,6 @@ * Be patient; this program runs for a very long time. * For faster runs, restrict execution using command line args. * - * This is an interface based version of ArrayList/IteratorMicroBenchmark - * * @author Martin Buchholz */ public class IteratorMicroBenchmark { @@ -115,7 +113,9 @@ CountDownLatch finalized = new CountDownLatch(1); ReferenceQueue queue = new ReferenceQueue<>(); WeakReference ref = new WeakReference<>( - new Object() { protected void finalize() { finalized.countDown(); }}, + new Object() { + @SuppressWarnings("deprecation") + protected void finalize() { finalized.countDown(); }}, queue); try { for (int tries = 3; tries--> 0; ) { @@ -267,16 +267,22 @@ }); } - static List makeSubList(List list) { + String goodClassName(Object x) { + return goodClassName(x.getClass()); + } + + static List makeSubList( + List elements, + UnaryOperator> copyConstructor) { + final ArrayList padded = new ArrayList<>(); final ThreadLocalRandom rnd = ThreadLocalRandom.current(); - int size = list.size(); - if (size <= 2) return list.subList(0, size); - List subList = list.subList(rnd.nextInt(0, 2), - size - rnd.nextInt(0, 2)); - List copy = new ArrayList<>(list); - subList.clear(); - subList.addAll(copy); - return subList; + final int frontPorch = rnd.nextInt(3); + final int backPorch = rnd.nextInt(3); + for (int n = frontPorch; n--> 0; ) padded.add(rnd.nextInt()); + padded.addAll(elements); + for (int n = backPorch; n--> 0; ) padded.add(rnd.nextInt()); + return copyConstructor.apply(padded) + .subList(frontPorch, frontPorch + elements.size()); } void run() throws Throwable { @@ -297,22 +303,42 @@ abq.add(abq.remove()); } - ArrayList jobs = Stream.>of( - al, ad, abq, - makeSubList(new ArrayList<>(al)), + final Integer[] array = al.toArray(new Integer[0]); + final List immutableSubList + = makeSubList(al, x -> List.of(x.toArray(new Integer[0]))); + + Stream> collections = concatStreams( + Stream.of( + // Lists and their subLists + al, + makeSubList(al, ArrayList::new), + new Vector<>(al), + makeSubList(al, Vector::new), new LinkedList<>(al), - makeSubList(new LinkedList<>(al)), + makeSubList(al, LinkedList::new), + new CopyOnWriteArrayList<>(al), + makeSubList(al, CopyOnWriteArrayList::new), + + ad, new PriorityQueue<>(al), - new Vector<>(al), - makeSubList(new Vector<>(al)), - new CopyOnWriteArrayList<>(al), - makeSubList(new CopyOnWriteArrayList<>(al)), new ConcurrentLinkedQueue<>(al), new ConcurrentLinkedDeque<>(al), + + // Blocking Queues + abq, new LinkedBlockingQueue<>(al), new LinkedBlockingDeque<>(al), new LinkedTransferQueue<>(al), - new PriorityBlockingQueue<>(al)) + new PriorityBlockingQueue<>(al), + + List.of(al.toArray(new Integer[0]))), + + // avoid UnsupportedOperationException in jdk9 and jdk10 + (goodClassName(immutableSubList).equals("RandomAccessSubList")) + ? Stream.empty() + : Stream.of(immutableSubList)); + + ArrayList jobs = collections .flatMap(x -> jobs(x)) .filter(job -> nameFilter == null || nameFilter.matcher(job.name()).find()) @@ -329,16 +355,29 @@ return Stream.of(streams).flatMap(s -> s); } + boolean isMutable(Collection x) { + return !(x.getClass().getName().contains("ImmutableCollections$")); + } + Stream jobs(Collection x) { + final String klazz = goodClassName(x); return concatStreams( collectionJobs(x), + (isMutable(x)) + ? mutableCollectionJobs(x) + : Stream.empty(), + (x instanceof Deque) ? dequeJobs((Deque)x) : Stream.empty(), (x instanceof List) ? listJobs((List)x) + : Stream.empty(), + + (x instanceof List && isMutable(x)) + ? mutableListJobs((List)x) : Stream.empty()); } @@ -350,7 +389,7 @@ } Stream collectionJobs(Collection x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " iterate for loop") { public void work() throws Throwable { @@ -381,14 +420,6 @@ sum[0] = 0; x.spliterator().forEachRemaining(n -> sum[0] += n); check.sum(sum[0]);}}}, - new Job(klazz + " removeIf") { - public void work() throws Throwable { - int[] sum = new int[1]; - for (int i = 0; i < iterations; i++) { - sum[0] = 0; - if (x.removeIf(n -> { sum[0] += n; return false; })) - throw new AssertionError(); - check.sum(sum[0]);}}}, new Job(klazz + " contains") { public void work() throws Throwable { int[] sum = new int[1]; @@ -407,14 +438,6 @@ if (x.containsAll(sneakyAdderCollection)) throw new AssertionError(); check.sum(sum[0]);}}}, - new Job(klazz + " remove(Object)") { - public void work() throws Throwable { - int[] sum = new int[1]; - Object sneakyAdder = sneakyAdder(sum); - for (int i = 0; i < iterations; i++) { - sum[0] = 0; - if (x.remove(sneakyAdder)) throw new AssertionError(); - check.sum(sum[0]);}}}, new Job(klazz + " forEach") { public void work() throws Throwable { int[] sum = new int[1]; @@ -498,8 +521,29 @@ check.sum(sum[0]);}}}); } + Stream mutableCollectionJobs(Collection x) { + final String klazz = goodClassName(x); + return Stream.of( + new Job(klazz + " removeIf") { + public void work() throws Throwable { + int[] sum = new int[1]; + for (int i = 0; i < iterations; i++) { + sum[0] = 0; + if (x.removeIf(n -> { sum[0] += n; return false; })) + throw new AssertionError(); + check.sum(sum[0]);}}}, + new Job(klazz + " remove(Object)") { + public void work() throws Throwable { + int[] sum = new int[1]; + Object sneakyAdder = sneakyAdder(sum); + for (int i = 0; i < iterations; i++) { + sum[0] = 0; + if (x.remove(sneakyAdder)) throw new AssertionError(); + check.sum(sum[0]);}}}); + } + Stream dequeJobs(Deque x) { - String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " descendingIterator() loop") { public void work() throws Throwable { @@ -519,7 +563,7 @@ } Stream listJobs(List x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " listIterator forward loop") { public void work() throws Throwable { @@ -555,15 +599,6 @@ if (x.lastIndexOf(sneakyAdder) != -1) throw new AssertionError(); check.sum(sum[0]);}}}, - new Job(klazz + " replaceAll") { - public void work() throws Throwable { - int[] sum = new int[1]; - UnaryOperator sneakyAdder = - x -> { sum[0] += x; return x; }; - for (int i = 0; i < iterations; i++) { - sum[0] = 0; - x.replaceAll(sneakyAdder); - check.sum(sum[0]);}}}, new Job(klazz + " equals") { public void work() throws Throwable { ArrayList copy = new ArrayList<>(x); @@ -577,4 +612,18 @@ if (x.hashCode() != hashCode) throw new AssertionError();}}}); } + + Stream mutableListJobs(List x) { + final String klazz = goodClassName(x); + return Stream.of( + new Job(klazz + " replaceAll") { + public void work() throws Throwable { + int[] sum = new int[1]; + UnaryOperator sneakyAdder = + x -> { sum[0] += x; return x; }; + for (int i = 0; i < iterations; i++) { + sum[0] = 0; + x.replaceAll(sneakyAdder); + check.sum(sum[0]);}}}); + } } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/Collection/RemoveMicroBenchmark.java --- a/test/jdk/java/util/Collection/RemoveMicroBenchmark.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/Collection/RemoveMicroBenchmark.java Sun Feb 17 12:21:11 2019 +0000 @@ -270,6 +270,10 @@ }); } + String goodClassName(Object x) { + return goodClassName(x.getClass()); + } + static List makeSubList(List list) { final ThreadLocalRandom rnd = ThreadLocalRandom.current(); int size = rnd.nextInt(4); @@ -369,7 +373,7 @@ } Stream collectionJobs(Collection x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " removeIf") { public void work() throws Throwable { @@ -422,7 +426,7 @@ } Stream iteratorRemoveJobs(Collection x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " Iterator.remove") { public void work() throws Throwable { @@ -460,7 +464,7 @@ } Stream queueJobs(Queue x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " poll()") { public void work() throws Throwable { @@ -474,7 +478,7 @@ } Stream dequeJobs(Deque x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " descendingIterator().remove") { public void work() throws Throwable { @@ -509,7 +513,7 @@ } Stream blockingQueueJobs(BlockingQueue x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " timed poll()") { public void work() throws Throwable { @@ -545,7 +549,7 @@ } Stream blockingDequeJobs(BlockingDeque x) { - final String klazz = goodClassName(x.getClass()); + final String klazz = goodClassName(x); return Stream.of( new Job(klazz + " timed pollFirst()") { public void work() throws Throwable { diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/HashMap/WhiteBoxResizeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/util/HashMap/WhiteBoxResizeTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018, 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 + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +import static java.util.stream.Collectors.toMap; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/* + * @test + * @bug 8210280 + * @modules java.base/java.util:open + * @summary White box tests for HashMap internals around table resize + * @run testng WhiteBoxResizeTest + * @key randomness + */ +public class WhiteBoxResizeTest { + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + final MethodHandle TABLE_SIZE_FOR; + final VarHandle THRESHOLD; + final VarHandle TABLE; + + public WhiteBoxResizeTest() throws ReflectiveOperationException { + Class mClass = HashMap.class; + String nodeClassName = mClass.getName() + "$Node"; + Class nodeArrayClass = Class.forName("[L" + nodeClassName + ";"); + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(mClass, MethodHandles.lookup()); + TABLE = lookup.findVarHandle(mClass, "table", nodeArrayClass); + this.TABLE_SIZE_FOR = lookup.findStatic( + mClass, "tableSizeFor", + MethodType.methodType(int.class, int.class)); + this.THRESHOLD = lookup.findVarHandle(mClass, "threshold", int.class); + } + + int tableSizeFor(int n) { + try { + return (int) TABLE_SIZE_FOR.invoke(n); + } catch (Throwable t) { throw new AssertionError(t); } + } + + Object[] table(HashMap map) { + try { + return (Object[]) TABLE.get(map); + } catch (Throwable t) { throw new AssertionError(t); } + } + + int capacity(HashMap map) { + return table(map).length; + } + + @Test + public void testTableSizeFor() { + assertEquals(tableSizeFor(0), 1); + assertEquals(tableSizeFor(1), 1); + assertEquals(tableSizeFor(2), 2); + assertEquals(tableSizeFor(3), 4); + assertEquals(tableSizeFor(15), 16); + assertEquals(tableSizeFor(16), 16); + assertEquals(tableSizeFor(17), 32); + int maxSize = 1 << 30; + assertEquals(tableSizeFor(maxSize - 1), maxSize); + assertEquals(tableSizeFor(maxSize), maxSize); + assertEquals(tableSizeFor(maxSize + 1), maxSize); + assertEquals(tableSizeFor(Integer.MAX_VALUE), maxSize); + } + + @Test + public void capacityTestDefaultConstructor() { + capacityTestDefaultConstructor(new HashMap<>()); + capacityTestDefaultConstructor(new LinkedHashMap<>()); + } + + void capacityTestDefaultConstructor(HashMap map) { + assertNull(table(map)); + + map.put(1, 1); + assertEquals(capacity(map), 16); // default initial capacity + + map.putAll(IntStream.range(0, 64).boxed().collect(toMap(i -> i, i -> i))); + assertEquals(capacity(map), 128); + } + + @Test + public void capacityTestInitialCapacity() { + int initialCapacity = rnd.nextInt(2, 128); + List>> suppliers = List.of( + () -> new HashMap<>(initialCapacity), + () -> new HashMap<>(initialCapacity, 0.75f), + () -> new LinkedHashMap<>(initialCapacity), + () -> new LinkedHashMap<>(initialCapacity, 0.75f)); + + for (Supplier> supplier : suppliers) { + HashMap map = supplier.get(); + assertNull(table(map)); + + map.put(1, 1); + assertEquals(capacity(map), tableSizeFor(initialCapacity)); + } + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/concurrent/CountDownLatch/Basic.java --- a/test/jdk/java/util/concurrent/CountDownLatch/Basic.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/concurrent/CountDownLatch/Basic.java Sun Feb 17 12:21:11 2019 +0000 @@ -25,24 +25,27 @@ * @test * @bug 6332435 * @summary Basic tests for CountDownLatch + * @library /test/lib * @author Seetharam Avadhanam, Martin Buchholz */ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; - -interface AwaiterFactory { - Awaiter getAwaiter(); -} - -abstract class Awaiter extends Thread { - private volatile Throwable result = null; - protected void result(Throwable result) { this.result = result; } - public Throwable result() { return this.result; } -} +import jdk.test.lib.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + + interface AwaiterFactory { + Awaiter getAwaiter(); + } + + abstract static class Awaiter extends Thread { + private volatile Throwable result = null; + protected void result(Throwable result) { this.result = result; } + public Throwable result() { return this.result; } + } private void toTheStartingGate(CountDownLatch gate) { try { @@ -78,15 +81,12 @@ catch (Throwable result) { result(result); }}}; } - private AwaiterFactory awaiterFactories(final CountDownLatch latch, - final CountDownLatch gate, - final int i) { - if (i == 1) - return new AwaiterFactory() { public Awaiter getAwaiter() { - return awaiter(latch, gate); }}; + AwaiterFactory awaiterFactory(CountDownLatch latch, CountDownLatch gate) { + return () -> awaiter(latch, gate); + } - return new AwaiterFactory() { public Awaiter getAwaiter() { - return awaiter(latch, gate, 10000); }}; + AwaiterFactory timedAwaiterFactory(CountDownLatch latch, CountDownLatch gate) { + return () -> awaiter(latch, gate, LONG_DELAY_MS); } //---------------------------------------------------------------- @@ -100,8 +100,8 @@ for (int i = 0; i < 3; i++) { CountDownLatch gate = new CountDownLatch(4); - AwaiterFactory factory1 = test.awaiterFactories(latch, gate, 1); - AwaiterFactory factory2 = test.awaiterFactories(latch, gate, 0); + AwaiterFactory factory1 = test.awaiterFactory(latch, gate); + AwaiterFactory factory2 = test.timedAwaiterFactory(latch, gate); a[count] = factory1.getAwaiter(); a[count++].start(); a[count] = factory1.getAwaiter(); a[count++].start(); a[count] = factory2.getAwaiter(); a[count++].start(); @@ -129,8 +129,8 @@ for (int i = 0; i < 3; i++) { CountDownLatch gate = new CountDownLatch(4); - AwaiterFactory factory1 = test.awaiterFactories(latch, gate, 1); - AwaiterFactory factory2 = test.awaiterFactories(latch, gate, 0); + AwaiterFactory factory1 = test.awaiterFactory(latch, gate); + AwaiterFactory factory2 = test.timedAwaiterFactory(latch, gate); a[count] = factory1.getAwaiter(); a[count++].start(); a[count] = factory1.getAwaiter(); a[count++].start(); a[count] = factory2.getAwaiter(); a[count++].start(); @@ -162,8 +162,8 @@ for (int i = 0; i < 3; i++) { CountDownLatch gate = new CountDownLatch(4); - AwaiterFactory factory1 = test.awaiterFactories(latch, gate, 1); - AwaiterFactory factory2 = test.awaiterFactories(latch, gate, 0); + AwaiterFactory factory1 = test.awaiterFactory(latch, gate); + AwaiterFactory factory2 = test.timedAwaiterFactory(latch, gate); a[count] = test.awaiter(latch, gate, timeout[i]); a[count++].start(); a[count] = factory1.getAwaiter(); a[count++].start(); a[count] = factory2.getAwaiter(); a[count++].start(); diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/concurrent/tck/CyclicBarrierTest.java --- a/test/jdk/java/util/concurrent/tck/CyclicBarrierTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/concurrent/tck/CyclicBarrierTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -38,6 +38,9 @@ import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -486,4 +489,34 @@ assertEquals(0, barrier.getNumberWaiting()); } } + + /** + * There can be more threads calling await() than parties, as long as each + * task only calls await once and the task count is a multiple of parties. + */ + public void testMoreTasksThanParties() throws Exception { + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + final int parties = rnd.nextInt(1, 5); + final int nTasks = rnd.nextInt(1, 5) * parties; + final AtomicInteger tripCount = new AtomicInteger(0); + final AtomicInteger awaitCount = new AtomicInteger(0); + final CyclicBarrier barrier = + new CyclicBarrier(parties, () -> tripCount.getAndIncrement()); + final ExecutorService e = Executors.newFixedThreadPool(nTasks); + final Runnable awaiter = () -> { + try { + if (ThreadLocalRandom.current().nextBoolean()) + barrier.await(); + else + barrier.await(LONG_DELAY_MS, MILLISECONDS); + awaitCount.getAndIncrement(); + } catch (Throwable fail) { threadUnexpectedException(fail); }}; + try (PoolCleaner cleaner = cleaner(e)) { + for (int i = nTasks; i--> 0; ) + e.execute(awaiter); + } + assertEquals(nTasks / parties, tripCount.get()); + assertEquals(nTasks, awaitCount.get()); + assertEquals(0, barrier.getNumberWaiting()); + } } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/concurrent/tck/ForkJoinPool9Test.java --- a/test/jdk/java/util/concurrent/tck/ForkJoinPool9Test.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPool9Test.java Sun Feb 17 12:21:11 2019 +0000 @@ -38,6 +38,8 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.Future; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Stream; import junit.framework.Test; import junit.framework.TestSuite; @@ -67,21 +69,33 @@ .findVarHandle(Thread.class, "contextClassLoader", ClassLoader.class); ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); boolean haveSecurityManager = (System.getSecurityManager() != null); - CountDownLatch taskStarted = new CountDownLatch(1); + CountDownLatch runInCommonPoolStarted = new CountDownLatch(1); + ClassLoader classLoaderDistinctFromSystemClassLoader + = ClassLoader.getPlatformClassLoader(); + assertNotSame(classLoaderDistinctFromSystemClassLoader, + systemClassLoader); Runnable runInCommonPool = () -> { - taskStarted.countDown(); + runInCommonPoolStarted.countDown(); assertTrue(ForkJoinTask.inForkJoinPool()); - assertSame(ForkJoinPool.commonPool(), - ForkJoinTask.getPool()); - assertSame(systemClassLoader, - Thread.currentThread().getContextClassLoader()); - assertSame(systemClassLoader, - CCL.get(Thread.currentThread())); + assertSame(ForkJoinPool.commonPool(), ForkJoinTask.getPool()); + Thread currentThread = Thread.currentThread(); + + Stream.of(systemClassLoader, null).forEach(cl -> { + if (ThreadLocalRandom.current().nextBoolean()) + // should always be permitted, without effect + currentThread.setContextClassLoader(cl); + }); + + Stream.of(currentThread.getContextClassLoader(), + (ClassLoader) CCL.get(currentThread)) + .forEach(cl -> assertTrue(cl == systemClassLoader || cl == null)); + if (haveSecurityManager) assertThrows( SecurityException.class, () -> System.getProperty("foo"), - () -> Thread.currentThread().setContextClassLoader(null)); + () -> currentThread.setContextClassLoader( + classLoaderDistinctFromSystemClassLoader)); // TODO ? // if (haveSecurityManager // && Thread.currentThread().getClass().getSimpleName() @@ -91,7 +105,7 @@ Future f = ForkJoinPool.commonPool().submit(runInCommonPool); // Ensure runInCommonPool is truly running in the common pool, // by giving this thread no opportunity to "help" on get(). - await(taskStarted); + await(runInCommonPoolStarted); assertNull(f.get()); } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/concurrent/tck/JSR166TestCase.java --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java Sun Feb 17 12:21:11 2019 +0000 @@ -487,6 +487,12 @@ public static boolean atLeastJava9() { return JAVA_CLASS_VERSION >= 53.0; } public static boolean atLeastJava10() { return JAVA_CLASS_VERSION >= 54.0; } public static boolean atLeastJava11() { return JAVA_CLASS_VERSION >= 55.0; } + public static boolean atLeastJava12() { return JAVA_CLASS_VERSION >= 56.0; } + public static boolean atLeastJava13() { return JAVA_CLASS_VERSION >= 57.0; } + public static boolean atLeastJava14() { return JAVA_CLASS_VERSION >= 58.0; } + public static boolean atLeastJava15() { return JAVA_CLASS_VERSION >= 59.0; } + public static boolean atLeastJava16() { return JAVA_CLASS_VERSION >= 60.0; } + public static boolean atLeastJava17() { return JAVA_CLASS_VERSION >= 61.0; } /** * Collects all JSR166 unit tests as one suite. @@ -577,6 +583,7 @@ "HashMapTest", "LinkedBlockingDeque8Test", "LinkedBlockingQueue8Test", + "LinkedHashMapTest", "LongAccumulatorTest", "LongAdderTest", "SplittableRandomTest", diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/concurrent/tck/LinkedHashMapTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/util/concurrent/tck/LinkedHashMapTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,60 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.LinkedHashMap; +import java.util.Map; + +import junit.framework.Test; + +public class LinkedHashMapTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + class Implementation implements MapImplementation { + public Class klazz() { return LinkedHashMap.class; } + public Map emptyMap() { return new LinkedHashMap(); } + public Object makeKey(int i) { return i; } + public Object makeValue(int i) { return i; } + public boolean isConcurrent() { return false; } + public boolean permitsNullKeys() { return true; } + public boolean permitsNullValues() { return true; } + public boolean supportsSetValue() { return true; } + } + return newTestSuite( + // LinkedHashMapTest.class, + MapTest.testSuite(new Implementation())); + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/java/util/concurrent/tck/MapTest.java --- a/test/jdk/java/util/concurrent/tck/MapTest.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/java/util/concurrent/tck/MapTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -166,6 +166,40 @@ assertEquals(1, m.size()); } + /** + * "Missing" test found while investigating JDK-8210280. + * ant -Djsr166.tckTestClass=HashMapTest -Djsr166.methodFilter=testBug8210280 -Djsr166.runsPerTest=1000000 tck + */ + public void testBug8210280() { + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + final int size1 = rnd.nextInt(32); + final int size2 = rnd.nextInt(128); + + final Map m1 = impl.emptyMap(); + for (int i = 0; i < size1; i++) { + int elt = rnd.nextInt(1024 * i, 1024 * (i + 1)); + assertNull(m1.put(impl.makeKey(elt), impl.makeValue(elt))); + } + + final Map m2 = impl.emptyMap(); + for (int i = 0; i < size2; i++) { + int elt = rnd.nextInt(Integer.MIN_VALUE + 1024 * i, + Integer.MIN_VALUE + 1024 * (i + 1)); + assertNull(m2.put(impl.makeKey(elt), impl.makeValue(-elt))); + } + + final Map m1Copy = impl.emptyMap(); + m1Copy.putAll(m1); + + m1.putAll(m2); + + for (Object elt : m2.keySet()) + assertEquals(m2.get(elt), m1.get(elt)); + for (Object elt : m1Copy.keySet()) + assertSame(m1Copy.get(elt), m1.get(elt)); + assertEquals(size1 + size2, m1.size()); + } + // public void testFailsIntentionallyForDebugging() { // fail(impl.klazz().getSimpleName()); // } diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/javax/net/ssl/interop/ClientHelloBufferUnderflowException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/javax/net/ssl/interop/ClientHelloBufferUnderflowException.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,81 @@ +/* + * 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. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 8215790 + * @summary Verify exception + * @modules java.base/sun.security.util + * @run main/othervm ClientHelloBufferUnderflowException + */ + +import sun.security.util.HexDumpEncoder; +import javax.net.ssl.SSLHandshakeException; + +public class ClientHelloBufferUnderflowException extends ClientHelloInterOp { + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + try { + (new ClientHelloBufferUnderflowException()).run(); + } catch (SSLHandshakeException e) { + System.out.println("Correct exception thrown"); + } catch (Exception e) { + System.out.println("Failed: Exception not SSLHandShakeException"); + System.out.println(e.getMessage()); + throw e; + } + } + + @Override + protected byte[] createClientHelloMessage() { + // The ClientHello message in hex: 16 03 01 00 05 01 00 00 01 03 + // Record Header: + // 16 - type is 0x16 (handshake record) + // 03 01 - protocol version is 3.1 (also known as TLS 1.0) + // 00 05 - 0x05 (5) bytes of handshake message follows + // Handshake Header: + // 01 - handshake message type 0x01 (client hello) + // 00 00 01 - 0x01 (1) bytes of client hello follows + // Client Version: + // 03 - incomplete client version + // + // (Based on https://tls.ulfheim.net) + byte[] bytes = { + 0x16, 0x03, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01, 0x03}; + + System.out.println("The ClientHello message used"); + try { + (new HexDumpEncoder()).encodeBuffer(bytes, System.out); + } catch (Exception e) { + // ignore + } + return bytes; + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/krb5/auto/ReplayCacheTestProcWithMD5.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/sun/security/krb5/auto/ReplayCacheTestProcWithMD5.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,36 @@ +/* + * 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 + * 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 8168518 8194486 + * @summary testing jdk.krb5.rcache.useMD5. This action is put in a separate + * test so that ReplayCacheTestProc.java can be launched with special + * test.* system properties easily. + * @library ../../../../java/security/testlibrary/ /test/lib + * @build jdk.test.lib.Platform + * @run main jdk.test.lib.FileInstaller TestHosts TestHosts + * @run main/othervm/timeout=300 -Djdk.krb5.rcache.useMD5=true + * -Djdk.net.hosts.file=TestHosts + * -Dtest.service=host ReplayCacheTestProc + */ diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/krb5/auto/rcache_usemd5.sh --- a/test/jdk/sun/security/krb5/auto/rcache_usemd5.sh Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -# -# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -# 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 8168518 8194486 -# @summary testing jdk.krb5.rcache.useMD5. This action is put in a separate -# test so that ReplayCacheTestProc.java can be launched with special -# test.* system properties easily. -# @library ../../../../java/security/testlibrary/ /test/lib -# @build jdk.test.lib.Platform -# @run main jdk.test.lib.FileInstaller TestHosts TestHosts -# @run main/othervm/timeout=300 -Djdk.krb5.rcache.useMD5=true -# -Djdk.net.hosts.file=TestHosts -# -Dtest.service=host ReplayCacheTestProc diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/krb5/tools/KtabCheck.java --- a/test/jdk/sun/security/krb5/tools/KtabCheck.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/jdk/sun/security/krb5/tools/KtabCheck.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -21,27 +21,87 @@ * questions. */ +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.HashSet; import java.util.Set; + +import jdk.test.lib.SecurityTools; import sun.security.krb5.internal.ktab.KeyTab; import sun.security.krb5.internal.ktab.KeyTabEntry; -/** - * This class is called by the test ktcheck.sh and is not meant to run - * by itself. +/* + * @test + * @bug 6950546 + * @summary "ktab -d name etype" to "ktab -d name [-e etype] [kvno | all | old]" + * @requires os.family == "windows" + * @library /test/lib + * @modules java.security.jgss/sun.security.krb5.internal.ktab + * java.security.jgss/sun.security.krb5 */ public class KtabCheck { + + private static final String KEYTAB = "ktab.tmp"; + + public static void main(String[] args) throws Exception { + + Files.deleteIfExists(Path.of(KEYTAB)); + + ktab("-a me mine"); + check(1,16,1,23,1,17); + ktab("-a me mine -n 0"); + check(0,16,0,23,0,17); + ktab("-a me mine -n 1 -append"); + check(0,16,0,23,0,17,1,16,1,23,1,17); + ktab("-a me mine -append"); + check(0,16,0,23,0,17,1,16,1,23,1,17,2,16,2,23,2,17); + ktab("-a me mine"); + check(3,16,3,23,3,17); + ktab("-a me mine -n 4 -append"); + check(3,16,3,23,3,17,4,16,4,23,4,17); + ktab("-a me mine -n 5 -append"); + check(3,16,3,23,3,17,4,16,4,23,4,17,5,16,5,23,5,17); + ktab("-a me mine -n 6 -append"); + check(3,16,3,23,3,17,4,16,4,23,4,17,5,16,5,23,5,17,6,16,6,23,6,17); + ktab("-d me 3"); + check(4,16,4,23,4,17,5,16,5,23,5,17,6,16,6,23,6,17); + ktab("-d me -e 16 6"); + check(4,16,4,23,4,17,5,16,5,23,5,17,6,23,6,17); + ktab("-d me -e 17 6"); + check(4,16,4,23,4,17,5,16,5,23,5,17,6,23); + ktab("-d me -e 16 5"); + check(4,16,4,23,4,17,5,23,5,17,6,23); + ktab("-d me old"); + check(4,16,5,17,6,23); + try { + ktab("-d me old"); + throw new Exception("Should fail"); + } catch (Exception e) { + // no-op + } + check(4,16,5,17,6,23); + ktab("-d me"); + check(); + } + + static void ktab(String s) throws Exception { + File conf = new File(System.getProperty("test.src"), "onlythree.conf"); + SecurityTools.ktab("-J-Djava.security.krb5.conf=" + conf + + " -k " + KEYTAB + " -f " + s).shouldHaveExitValue(0); + } + /** * Checks if a keytab contains exactly the keys (kvno and etype) - * @param args keytabname kvno etype... + * @param args kvno etype... */ - public static void main(String[] args) throws Exception { + static void check(int... args) throws Exception { System.out.println("Checking " + Arrays.toString(args)); - KeyTab ktab = KeyTab.getInstance(args[0]); + KeyTab ktab = KeyTab.getInstance(KEYTAB); Set expected = new HashSet<>(); - for (int i=1; i /dev/null -KTAB="${TESTJAVA}${FS}bin${FS}ktab -k $KEYTAB" - -$KTAB -a me@LOCAL mine || exit 1 - -$KTAB -hello -if [ $? = 0 ]; then exit 2; fi - -$KTAB -if [ $? = 0 ]; then exit 3; fi - -exit 0 diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/krb5/tools/ktcheck.sh --- a/test/jdk/sun/security/krb5/tools/ktcheck.sh Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -# -# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 6950546 -# @summary "ktab -d name etype" to "ktab -d name [-e etype] [kvno | all | old]" -# @modules java.security.jgss/sun.security.krb5.internal.ktab -# java.security.jgss/sun.security.krb5 -# @compile KtabCheck.java -# @run shell ktcheck.sh -# - -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi - -OS=`uname -s` -case "$OS" in - CYGWIN* ) - FS="/" - ;; - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - echo "Unsupported system!" - exit 0; - ;; -esac - -KEYTAB=ktab.tmp - -rm $KEYTAB - -EXTRA_OPTIONS="-Djava.security.krb5.conf=${TESTSRC}${FS}onlythree.conf" -KTAB="${TESTJAVA}${FS}bin${FS}ktab -J${EXTRA_OPTIONS} -k $KEYTAB -f" -CHECK="${TESTJAVA}${FS}bin${FS}java -cp ${TESTCLASSES} ${TESTVMOPTS} ${EXTRA_OPTIONS} \ - --add-exports java.security.jgss/sun.security.krb5.internal.ktab=ALL-UNNAMED \ - --add-exports java.security.jgss/sun.security.krb5=ALL-UNNAMED \ - KtabCheck $KEYTAB" - -echo ${EXTRA_OPTIONS} - -$KTAB -a me mine -$CHECK 1 16 1 23 1 17 || exit 1 -$KTAB -a me mine -n 0 -$CHECK 0 16 0 23 0 17 || exit 1 -$KTAB -a me mine -n 1 -append -$CHECK 0 16 0 23 0 17 1 16 1 23 1 17 || exit 1 -$KTAB -a me mine -append -$CHECK 0 16 0 23 0 17 1 16 1 23 1 17 2 16 2 23 2 17 || exit 1 -$KTAB -a me mine -$CHECK 3 16 3 23 3 17 || exit 1 -$KTAB -a me mine -n 4 -append -$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 || exit 1 -$KTAB -a me mine -n 5 -append -$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 5 16 5 23 5 17 || exit 1 -$KTAB -a me mine -n 6 -append -$CHECK 3 16 3 23 3 17 4 16 4 23 4 17 5 16 5 23 5 17 6 16 6 23 6 17 || exit 1 -$KTAB -d me 3 -$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 16 6 23 6 17 || exit 1 -$KTAB -d me -e 16 6 -$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 23 6 17 || exit 1 -$KTAB -d me -e 17 6 -$CHECK 4 16 4 23 4 17 5 16 5 23 5 17 6 23 || exit 1 -$KTAB -d me -e 16 5 -$CHECK 4 16 4 23 4 17 5 23 5 17 6 23 || exit 1 -$KTAB -d me old -$CHECK 4 16 5 17 6 23 || exit 1 -$KTAB -d me old -$CHECK 4 16 5 17 6 23 || exit 1 -$KTAB -d me -$CHECK || exit 1 diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/krb5/tools/ktmissing.sh --- a/test/jdk/sun/security/krb5/tools/ktmissing.sh Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -# -# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. -# 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 7043737 -# @summary klist does not detect non-existing keytab -# @run shell ktmissing.sh -# - -OS=`uname -s` -case "$OS" in - CYGWIN* ) - FS="/" - ;; - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - echo "Unsupported system!" - exit 0; - ;; -esac - -${TESTJAVA}${FS}bin${FS}klist -k this_file_does_not_exist && exit 1 - -echo ABC > this_is_not_a_keytab - -${TESTJAVA}${FS}bin${FS}klist -k this_is_not_a_keytab && exit 2 - -exit 0 diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/krb5/tools/ktzero.sh --- a/test/jdk/sun/security/krb5/tools/ktzero.sh Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 8014196 -# @summary ktab creates a file with zero kt_vno -# @run shell ktzero.sh -# - -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi - -OS=`uname -s` -case "$OS" in - CYGWIN* ) - FS="/" - ;; - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - echo "Unsupported system!" - exit 0; - ;; -esac - -KEYTAB=ktzero.tmp - -rm $KEYTAB 2> /dev/null -KTAB="${TESTJAVA}${FS}bin${FS}ktab -k $KEYTAB" - -# Listing non-existing ktab should fail -$KTAB -l && exit 1 - -# Can add to non-existing ktab -$KTAB -a me@LOCAL mine || exit 2 - -# Now can be listed -$KTAB -l || exit 3 - -echo ABCDEFG > $KEYTAB - -# Invalid keytab should fail for all commands -$KTAB -l && exit 4 -$KTAB -a me@LOCAL mine && exit 2 - -exit 0 diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/CipherTest.java --- a/test/jdk/sun/security/pkcs11/fips/CipherTest.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,608 +0,0 @@ -/* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; - -import java.security.*; -import java.security.cert.*; -import java.security.cert.Certificate; - -import javax.net.ssl.*; - -/** - * Test that all ciphersuites work in all versions and all client - * authentication types. The way this is setup the server is stateless and - * all checking is done on the client side. - * - * The test is multithreaded to speed it up, especially on multiprocessor - * machines. To simplify debugging, run with -DnumThreads=1. - * - * @author Andreas Sterbenz - */ -public class CipherTest { - - // use any available port for the server socket - static int serverPort = 0; - - final int THREADS; - - // assume that if we do not read anything for 20 seconds, something - // has gone wrong - final static int TIMEOUT = 20 * 1000; - - static KeyStore /* trustStore, */ keyStore; - static X509ExtendedKeyManager keyManager; - static X509TrustManager trustManager; - static SecureRandom secureRandom; - - private static PeerFactory peerFactory; - - static abstract class Server implements Runnable { - - final CipherTest cipherTest; - - Server(CipherTest cipherTest) throws Exception { - this.cipherTest = cipherTest; - } - - public abstract void run(); - - void handleRequest(InputStream in, OutputStream out) throws IOException { - boolean newline = false; - StringBuilder sb = new StringBuilder(); - while (true) { - int ch = in.read(); - if (ch < 0) { - throw new EOFException(); - } - sb.append((char)ch); - if (ch == '\r') { - // empty - } else if (ch == '\n') { - if (newline) { - // 2nd newline in a row, end of request - break; - } - newline = true; - } else { - newline = false; - } - } - String request = sb.toString(); - if (request.startsWith("GET / HTTP/1.") == false) { - throw new IOException("Invalid request: " + request); - } - out.write("HTTP/1.0 200 OK\r\n\r\n".getBytes()); - } - - } - - public static class TestParameters { - - String cipherSuite; - String protocol; - String clientAuth; - - TestParameters(String cipherSuite, String protocol, - String clientAuth) { - this.cipherSuite = cipherSuite; - this.protocol = protocol; - this.clientAuth = clientAuth; - } - - boolean isEnabled() { - return TLSCipherStatus.isEnabled(cipherSuite, protocol); - } - - public String toString() { - String s = cipherSuite + " in " + protocol + " mode"; - if (clientAuth != null) { - s += " with " + clientAuth + " client authentication"; - } - return s; - } - - static enum TLSCipherStatus { - // cipher suites supported since TLS 1.2 - CS_01("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF), - CS_02("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF), - CS_03("TLS_RSA_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF), - CS_04("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF), - CS_05("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF), - CS_06("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF), - CS_07("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF), - - CS_08("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_09("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_10("TLS_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_11("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_12("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_13("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_14("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - - CS_15("TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF), - CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), - CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), - - CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - - CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - - CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), - CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), - - // cipher suites obsoleted since TLS 1.2 - CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), - CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), - CS_52("SSL_DHE_DSS_WITH_DES_CBC_SHA", 0x0000, 0x0303), - CS_53("SSL_DH_anon_WITH_DES_CBC_SHA", 0x0000, 0x0303), - CS_54("TLS_KRB5_WITH_DES_CBC_SHA", 0x0000, 0x0303), - CS_55("TLS_KRB5_WITH_DES_CBC_MD5", 0x0000, 0x0303), - - // cipher suites obsoleted since TLS 1.1 - CS_60("SSL_RSA_EXPORT_WITH_RC4_40_MD5", 0x0000, 0x0302), - CS_61("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", 0x0000, 0x0302), - CS_62("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302), - CS_63("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302), - CS_64("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302), - CS_65("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302), - CS_66("TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 0x0000, 0x0302), - CS_67("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 0x0000, 0x0302), - CS_68("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 0x0000, 0x0302), - CS_69("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0x0000, 0x0302), - - // ignore TLS_EMPTY_RENEGOTIATION_INFO_SCSV always - CS_99("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", 0xFFFF, 0x0000); - - // the cipher suite name - final String cipherSuite; - - // supported since protocol version - final int supportedSince; - - // obsoleted since protocol version - final int obsoletedSince; - - TLSCipherStatus(String cipherSuite, - int supportedSince, int obsoletedSince) { - this.cipherSuite = cipherSuite; - this.supportedSince = supportedSince; - this.obsoletedSince = obsoletedSince; - } - - static boolean isEnabled(String cipherSuite, String protocol) { - int versionNumber = toVersionNumber(protocol); - - if (versionNumber < 0) { - return true; // unlikely to happen - } - - for (TLSCipherStatus status : TLSCipherStatus.values()) { - if (cipherSuite.equals(status.cipherSuite)) { - if ((versionNumber < status.supportedSince) || - (versionNumber >= status.obsoletedSince)) { - return false; - } - - return true; - } - } - - return true; - } - - private static int toVersionNumber(String protocol) { - int versionNumber = -1; - - switch (protocol) { - case "SSLv2Hello": - versionNumber = 0x0002; - break; - case "SSLv3": - versionNumber = 0x0300; - break; - case "TLSv1": - versionNumber = 0x0301; - break; - case "TLSv1.1": - versionNumber = 0x0302; - break; - case "TLSv1.2": - versionNumber = 0x0303; - break; - default: - // unlikely to happen - } - - return versionNumber; - } - } - } - - private List tests; - private Iterator testIterator; - private SSLSocketFactory factory; - private boolean failed; - - private CipherTest(PeerFactory peerFactory) throws IOException { - THREADS = Integer.parseInt(System.getProperty("numThreads", "4")); - factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); - SSLSocket socket = (SSLSocket)factory.createSocket(); - String[] cipherSuites = socket.getSupportedCipherSuites(); - String[] protocols = socket.getSupportedProtocols(); -// String[] clientAuths = {null, "RSA", "DSA"}; - String[] clientAuths = {null}; - tests = new ArrayList( - cipherSuites.length * protocols.length * clientAuths.length); - for (int i = 0; i < cipherSuites.length; i++) { - String cipherSuite = cipherSuites[i]; - - for (int j = 0; j < protocols.length; j++) { - String protocol = protocols[j]; - - if (!peerFactory.isSupported(cipherSuite, protocol)) { - continue; - } - - for (int k = 0; k < clientAuths.length; k++) { - String clientAuth = clientAuths[k]; - if ((clientAuth != null) && - (cipherSuite.indexOf("DH_anon") != -1)) { - // no client with anonymous ciphersuites - continue; - } - tests.add(new TestParameters(cipherSuite, protocol, - clientAuth)); - } - } - } - testIterator = tests.iterator(); - } - - synchronized void setFailed() { - failed = true; - } - - public void run() throws Exception { - Thread[] threads = new Thread[THREADS]; - for (int i = 0; i < THREADS; i++) { - try { - threads[i] = new Thread(peerFactory.newClient(this), - "Client " + i); - } catch (Exception e) { - e.printStackTrace(); - return; - } - threads[i].start(); - } - try { - for (int i = 0; i < THREADS; i++) { - threads[i].join(); - } - } catch (InterruptedException e) { - setFailed(); - e.printStackTrace(); - } - if (failed) { - throw new Exception("*** Test '" + peerFactory.getName() + - "' failed ***"); - } else { - System.out.println("Test '" + peerFactory.getName() + - "' completed successfully"); - } - } - - synchronized TestParameters getTest() { - if (failed) { - return null; - } - if (testIterator.hasNext()) { - return (TestParameters)testIterator.next(); - } - return null; - } - - SSLSocketFactory getFactory() { - return factory; - } - - static abstract class Client implements Runnable { - - final CipherTest cipherTest; - - Client(CipherTest cipherTest) throws Exception { - this.cipherTest = cipherTest; - } - - public final void run() { - while (true) { - TestParameters params = cipherTest.getTest(); - if (params == null) { - // no more tests - break; - } - if (params.isEnabled() == false) { - System.out.println("Skipping disabled test " + params); - continue; - } - try { - runTest(params); - System.out.println("Passed " + params); - } catch (Exception e) { - cipherTest.setFailed(); - System.out.println("** Failed " + params + "**"); - e.printStackTrace(); - } - } - } - - abstract void runTest(TestParameters params) throws Exception; - - void sendRequest(InputStream in, OutputStream out) throws IOException { - out.write("GET / HTTP/1.0\r\n\r\n".getBytes()); - out.flush(); - StringBuilder sb = new StringBuilder(); - while (true) { - int ch = in.read(); - if (ch < 0) { - break; - } - sb.append((char)ch); - } - String response = sb.toString(); - if (response.startsWith("HTTP/1.0 200 ") == false) { - throw new IOException("Invalid response: " + response); - } - } - - } - - // for some reason, ${test.src} has a different value when the - // test is called from the script and when it is called directly... - static String pathToStores = "."; - static String pathToStoresSH = "."; - static String keyStoreFile = "keystore"; - static String trustStoreFile = "truststore"; - static char[] passwd = "passphrase".toCharArray(); - - static File PATH; - - private static KeyStore readKeyStore(String name) throws Exception { - File file = new File(PATH, name); - InputStream in = new FileInputStream(file); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(in, passwd); - in.close(); - return ks; - } - - public static void main(PeerFactory peerFactory, KeyStore keyStore, - String[] args) throws Exception { - long time = System.currentTimeMillis(); - String relPath; - if ((args != null) && (args.length > 0) && args[0].equals("sh")) { - relPath = pathToStoresSH; - } else { - relPath = pathToStores; - } - PATH = new File(System.getProperty("test.src", "."), relPath); - CipherTest.peerFactory = peerFactory; - System.out.print( - "Initializing test '" + peerFactory.getName() + "'..."); -// secureRandom = new SecureRandom(); -// secureRandom.nextInt(); -// trustStore = readKeyStore(trustStoreFile); - CipherTest.keyStore = keyStore; -// keyStore = readKeyStore(keyStoreFile); - KeyManagerFactory keyFactory = - KeyManagerFactory.getInstance( - KeyManagerFactory.getDefaultAlgorithm()); - keyFactory.init(keyStore, "test12".toCharArray()); - keyManager = (X509ExtendedKeyManager)keyFactory.getKeyManagers()[0]; - - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(keyStore); - trustManager = (X509TrustManager)tmf.getTrustManagers()[0]; - -// trustManager = new AlwaysTrustManager(); - SSLContext context = SSLContext.getInstance("TLS"); - context.init(new KeyManager[] {keyManager}, - new TrustManager[] {trustManager}, null); - SSLContext.setDefault(context); - - CipherTest cipherTest = new CipherTest(peerFactory); - Thread serverThread = new Thread(peerFactory.newServer(cipherTest), - "Server"); - serverThread.setDaemon(true); - serverThread.start(); - System.out.println("Done"); - cipherTest.run(); - time = System.currentTimeMillis() - time; - System.out.println("Done. (" + time + " ms)"); - } - - static abstract class PeerFactory { - - abstract String getName(); - - abstract Client newClient(CipherTest cipherTest) throws Exception; - - abstract Server newServer(CipherTest cipherTest) throws Exception; - - boolean isSupported(String cipherSuite, String protocol) { - // skip kerberos cipher suites - if (cipherSuite.startsWith("TLS_KRB5")) { - System.out.println("Skipping unsupported test for " + - cipherSuite + " of " + protocol); - return false; - } - - // No ECDH-capable certificate in key store. May restructure - // this in the future. - if (cipherSuite.contains("ECDHE_ECDSA") || - cipherSuite.contains("ECDH_ECDSA") || - cipherSuite.contains("ECDH_RSA")) { - System.out.println("Skipping unsupported test for " + - cipherSuite + " of " + protocol); - return false; - } - - // skip SSLv2Hello protocol - // - // skip TLSv1.2 protocol, we have not implement "SunTls12Prf" and - // SunTls12RsaPremasterSecret in SunPKCS11 provider - if (protocol.equals("SSLv2Hello") || protocol.equals("TLSv1.2")) { - System.out.println("Skipping unsupported test for " + - cipherSuite + " of " + protocol); - return false; - } - - // ignore exportable cipher suite for TLSv1.1 - if (protocol.equals("TLSv1.1")) { - if (cipherSuite.indexOf("_EXPORT_WITH") != -1) { - System.out.println("Skipping obsoleted test for " + - cipherSuite + " of " + protocol); - return false; - } - } - - return true; - } - } - -} - -// we currently don't do any chain verification. we assume that works ok -// and we can speed up the test. we could also just add a plain certificate -// chain comparision with our trusted certificates. -class AlwaysTrustManager implements X509TrustManager { - - public AlwaysTrustManager() { - - } - - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // empty - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // empty - } - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } -} - -class MyX509KeyManager extends X509ExtendedKeyManager { - - private final X509ExtendedKeyManager keyManager; - private String authType; - - MyX509KeyManager(X509ExtendedKeyManager keyManager) { - this.keyManager = keyManager; - } - - void setAuthType(String authType) { - this.authType = authType; - } - - public String[] getClientAliases(String keyType, Principal[] issuers) { - if (authType == null) { - return null; - } - return keyManager.getClientAliases(authType, issuers); - } - - public String chooseClientAlias(String[] keyType, Principal[] issuers, - Socket socket) { - if (authType == null) { - return null; - } - return keyManager.chooseClientAlias(new String[] {authType}, - issuers, socket); - } - - public String chooseEngineClientAlias(String[] keyType, - Principal[] issuers, SSLEngine engine) { - if (authType == null) { - return null; - } - return keyManager.chooseEngineClientAlias(new String[] {authType}, - issuers, engine); - } - - public String[] getServerAliases(String keyType, Principal[] issuers) { - throw new UnsupportedOperationException("Servers not supported"); - } - - public String chooseServerAlias(String keyType, Principal[] issuers, - Socket socket) { - throw new UnsupportedOperationException("Servers not supported"); - } - - public String chooseEngineServerAlias(String keyType, Principal[] issuers, - SSLEngine engine) { - throw new UnsupportedOperationException("Servers not supported"); - } - - public X509Certificate[] getCertificateChain(String alias) { - return keyManager.getCertificateChain(alias); - } - - public PrivateKey getPrivateKey(String alias) { - return keyManager.getPrivateKey(alias); - } - -} - -class DaemonThreadFactory implements ThreadFactory { - - final static ThreadFactory INSTANCE = new DaemonThreadFactory(); - - private final static ThreadFactory DEFAULT = Executors.defaultThreadFactory(); - - public Thread newThread(Runnable r) { - Thread t = DEFAULT.newThread(r); - t.setDaemon(true); - return t; - } - -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java --- a/test/jdk/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. - * 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 6313675 6323647 8028192 - * @summary Verify that all ciphersuites work in FIPS mode - * @library /test/lib .. - * @author Andreas Sterbenz - * @modules java.base/com.sun.net.ssl.internal.ssl - * @run main/manual ClientJSSEServerJSSE - */ - -/* - * JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon - */ - -import java.security.*; - -// This test belongs more in JSSE than here, but the JSSE workspace does not -// have the NSS test infrastructure. It will live here for the time being. - -public class ClientJSSEServerJSSE extends SecmodTest { - - public static void main(String[] args) throws Exception { - if (initSecmod() == false) { - return; - } - - String arch = System.getProperty("os.arch"); - if (!("sparc".equals(arch) || "sparcv9".equals(arch))) { - // we have not updated other platforms with the proper NSS - // libraries yet - System.out.println( - "Test currently works only on solaris-sparc " + - "and solaris-sparcv9. Skipping on " + arch); - return; - } - - String configName = BASE + SEP + "fips.cfg"; - Provider p = getSunPKCS11(configName); - - System.out.println(p); - Security.addProvider(p); - - Security.removeProvider("SunJSSE"); - Provider jsse = new com.sun.net.ssl.internal.ssl.Provider(p); - Security.addProvider(jsse); - System.out.println(jsse.getInfo()); - - KeyStore ks = KeyStore.getInstance("PKCS11", p); - ks.load(null, "test12".toCharArray()); - - CipherTest.main(new JSSEFactory(), ks, args); - } - - private static class JSSEFactory extends CipherTest.PeerFactory { - - String getName() { - return "Client JSSE - Server JSSE"; - } - - CipherTest.Client newClient(CipherTest cipherTest) throws Exception { - return new JSSEClient(cipherTest); - } - - CipherTest.Server newServer(CipherTest cipherTest) throws Exception { - return new JSSEServer(cipherTest); - } - } -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/ImportKeyStore.java --- a/test/jdk/sun/security/pkcs11/fips/ImportKeyStore.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.*; -import java.util.*; - -import java.security.*; -import java.security.KeyStore.*; -import java.security.cert.*; - -/** - -This is an approximation of the process used to create the *.db files -in this directory. - -setenv LD_LIBRARY_PATH $WS/test/sun/security/pkcs11/nss/lib/solaris-sparc -modutil -create -dbdir . -modutil -changepw "NSS Internal PKCS #11 Module" -dbdir . - -$JHOME/bin/keytool -list -storetype PKCS11 -addprovider SunPKCS11 -providerarg "--name=NSS\nnssSecmodDirectory=." -v -storepass test12 - -modutil -fips true -dbdir . - -*/ - -public class ImportKeyStore { - - public static void main(String[] args) throws Exception { - String nssCfg = "--name=NSS\nnssSecmodDirectory=.\n "; -// "attributes(*,CKO_PRIVATE_KEY,CKK_DSA) = { CKA_NETSCAPE_DB = 0h00 }"; - Provider p = Security.getProvider("SunPKCS11"); - p.configure(nssCfg); - - KeyStore ks = KeyStore.getInstance("PKCS11", p); - ks.load(null, "test12".toCharArray()); - System.out.println("Aliases: " + Collections.list(ks.aliases())); - System.out.println(); - - char[] srcpw = "passphrase".toCharArray(); -// importKeyStore("truststore", srcpw, ks); - importKeyStore("keystore", srcpw, ks); - - System.out.println("OK."); - } - - private static void importKeyStore(String filename, char[] passwd, KeyStore dstks) throws Exception { - System.out.println("Importing JKS KeyStore " + filename); - InputStream in = new FileInputStream(filename); - KeyStore srcks = KeyStore.getInstance("JKS"); - srcks.load(in, passwd); - in.close(); - List aliases = Collections.list(srcks.aliases()); - for (String alias : aliases) { - System.out.println("Alias: " + alias); - if (srcks.isCertificateEntry(alias)) { - X509Certificate cert = (X509Certificate)srcks.getCertificate(alias); - System.out.println(" Certificate: " + cert.getSubjectX500Principal()); - dstks.setCertificateEntry(alias + "-cert", cert); - } else if (srcks.isKeyEntry(alias)) { - PrivateKeyEntry entry = (PrivateKeyEntry)srcks.getEntry(alias, new PasswordProtection(passwd)); - System.out.println(" Key: " + entry.getPrivateKey().toString().split("\n")[0]); - dstks.setEntry(alias, entry, null); - } else { - System.out.println(" Unknown entry: " + alias); - } - } - System.out.println(); - } - -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/JSSEClient.java --- a/test/jdk/sun/security/pkcs11/fips/JSSEClient.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.*; -import java.net.*; -import java.util.*; - -import java.security.*; -import java.security.cert.*; -import java.security.cert.Certificate; - -import javax.net.ssl.*; - -class JSSEClient extends CipherTest.Client { - - private final SSLContext sslContext; - private final MyX509KeyManager keyManager; - - JSSEClient(CipherTest cipherTest) throws Exception { - super(cipherTest); - this.keyManager = new MyX509KeyManager(CipherTest.keyManager); - sslContext = SSLContext.getInstance("TLS"); - } - - void runTest(CipherTest.TestParameters params) throws Exception { - SSLSocket socket = null; - try { - keyManager.setAuthType(params.clientAuth); - sslContext.init(new KeyManager[] {CipherTest.keyManager}, new TrustManager[] {cipherTest.trustManager}, cipherTest.secureRandom); - SSLSocketFactory factory = (SSLSocketFactory)sslContext.getSocketFactory(); - socket = (SSLSocket)factory.createSocket("127.0.0.1", cipherTest.serverPort); - socket.setSoTimeout(cipherTest.TIMEOUT); - socket.setEnabledCipherSuites(new String[] {params.cipherSuite}); - socket.setEnabledProtocols(new String[] {params.protocol}); - InputStream in = socket.getInputStream(); - OutputStream out = socket.getOutputStream(); - sendRequest(in, out); - socket.close(); - SSLSession session = socket.getSession(); - session.invalidate(); - String cipherSuite = session.getCipherSuite(); - if (params.cipherSuite.equals(cipherSuite) == false) { - throw new Exception("Negotiated ciphersuite mismatch: " + cipherSuite + " != " + params.cipherSuite); - } - String protocol = session.getProtocol(); - if (params.protocol.equals(protocol) == false) { - throw new Exception("Negotiated protocol mismatch: " + protocol + " != " + params.protocol); - } - if (cipherSuite.indexOf("DH_anon") == -1) { - session.getPeerCertificates(); - } - Certificate[] certificates = session.getLocalCertificates(); - if (params.clientAuth == null) { - if (certificates != null) { - throw new Exception("Local certificates should be null"); - } - } else { - if ((certificates == null) || (certificates.length == 0)) { - throw new Exception("Certificates missing"); - } - String keyAlg = certificates[0].getPublicKey().getAlgorithm(); - if (params.clientAuth != keyAlg) { - throw new Exception("Certificate type mismatch: " + keyAlg + " != " + params.clientAuth); - } - } - } finally { - if (socket != null) { - socket.close(); - } - } - } - -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/JSSEServer.java --- a/test/jdk/sun/security/pkcs11/fips/JSSEServer.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; - -import java.security.*; -import java.security.cert.*; -import java.security.cert.Certificate; - -import javax.net.ssl.*; - -class JSSEServer extends CipherTest.Server { - - SSLServerSocket serverSocket; - - JSSEServer(CipherTest cipherTest) throws Exception { - super(cipherTest); - SSLContext serverContext = SSLContext.getInstance("TLS"); - serverContext.init(new KeyManager[] {cipherTest.keyManager}, new TrustManager[] {cipherTest.trustManager}, cipherTest.secureRandom); - - SSLServerSocketFactory factory = (SSLServerSocketFactory)serverContext.getServerSocketFactory(); - serverSocket = (SSLServerSocket)factory.createServerSocket(cipherTest.serverPort); - cipherTest.serverPort = serverSocket.getLocalPort(); - serverSocket.setEnabledCipherSuites(factory.getSupportedCipherSuites()); -// serverSocket.setWantClientAuth(true); - } - - public void run() { - System.out.println("JSSE Server listening on port " + cipherTest.serverPort); - Executor exec = Executors.newFixedThreadPool - (cipherTest.THREADS, DaemonThreadFactory.INSTANCE); - try { - while (true) { - final SSLSocket socket = (SSLSocket)serverSocket.accept(); - socket.setSoTimeout(cipherTest.TIMEOUT); - Runnable r = new Runnable() { - public void run() { - try { - InputStream in = socket.getInputStream(); - OutputStream out = socket.getOutputStream(); - handleRequest(in, out); - out.flush(); - socket.close(); - socket.getSession().invalidate(); - } catch (IOException e) { - cipherTest.setFailed(); - e.printStackTrace(); - } finally { - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - cipherTest.setFailed(); - System.out.println("Exception closing socket on server side:"); - e.printStackTrace(); - } - } - } - } - }; - exec.execute(r); - } - } catch (IOException e) { - cipherTest.setFailed(); - e.printStackTrace(); - // - } - } - -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/TestTLS12.java --- a/test/jdk/sun/security/pkcs11/fips/TestTLS12.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,453 +0,0 @@ -/* - * Copyright (c) 2018, Red Hat, Inc. - * 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 8029661 - * @summary Test TLS 1.2 - * @modules java.base/sun.security.internal.spec - * java.base/sun.security.util - * java.base/com.sun.net.ssl.internal.ssl - * java.base/com.sun.crypto.provider - * @library /test/lib .. - * @run main/othervm/timeout=120 TestTLS12 - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.nio.ByteBuffer; - -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; -import java.security.Security; - -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManagerFactory; - -import sun.security.internal.spec.TlsMasterSecretParameterSpec; -import sun.security.internal.spec.TlsPrfParameterSpec; -import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; - -public final class TestTLS12 extends SecmodTest { - - private static final boolean enableDebug = true; - - private static Provider sunPKCS11NSSProvider; - private static Provider sunJCEProvider; - private static com.sun.net.ssl.internal.ssl.Provider jsseProvider; - private static KeyStore ks; - private static KeyStore ts; - private static char[] passphrase = "JAHshj131@@".toCharArray(); - private static RSAPrivateKey privateKey; - private static RSAPublicKey publicKey; - - public static void main(String[] args) throws Exception { - try { - initialize(); - } catch (Exception e) { - System.out.println("Test skipped: failure during" + - " initialization"); - return; - } - - if (shouldRun()) { - // Test against JCE - testTlsAuthenticationCodeGeneration(); - - // Self-integrity test (complete TLS 1.2 communication) - new testTLS12SunPKCS11Communication().run(); - - System.out.println("Test PASS - OK"); - } else { - System.out.println("Test skipped: TLS 1.2 mechanisms" + - " not supported by current SunPKCS11 back-end"); - } - } - - private static boolean shouldRun() { - if (sunPKCS11NSSProvider == null) { - return false; - } - try { - KeyGenerator.getInstance("SunTls12MasterSecret", - sunPKCS11NSSProvider); - KeyGenerator.getInstance( - "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider); - KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider); - } catch (NoSuchAlgorithmException e) { - return false; - } - return true; - } - - private static void testTlsAuthenticationCodeGeneration() - throws Exception { - // Generate RSA Pre-Master Secret in SunPKCS11 provider - SecretKey rsaPreMasterSecret = null; - @SuppressWarnings("deprecation") - TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec = - new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303); - { - KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance( - "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider); - rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null); - rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey(); - } - - // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider) - byte[] rsaPlainPreMasterSecret = null; - { - Cipher rsaPreMasterSecretWrapperCipher = - Cipher.getInstance("RSA/ECB/PKCS1Padding", - sunPKCS11NSSProvider); - rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey, - new SecureRandom()); - byte[] rsaEncryptedPreMasterSecret = - rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret); - Cipher rsaPreMasterSecretUnwrapperCipher = - Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider); - rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE, - privateKey, rsaPreMasterSecretSpec); - rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap( - rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret", - Cipher.SECRET_KEY).getEncoded(); - - if (enableDebug) { - System.out.println("rsaPlainPreMasterSecret:"); - for (byte b : rsaPlainPreMasterSecret) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - } - } - - // Generate Master Secret - SecretKey sunPKCS11MasterSecret = null; - SecretKey jceMasterSecret = null; - { - KeyGenerator sunPKCS11MasterSecretGenerator = - KeyGenerator.getInstance("SunTls12MasterSecret", - sunPKCS11NSSProvider); - KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance( - "SunTls12MasterSecret", sunJCEProvider); - @SuppressWarnings("deprecation") - TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec = - new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3, - new byte[32], new byte[32], "SHA-256", 32, 64); - @SuppressWarnings("deprecation") - TlsMasterSecretParameterSpec jceMasterSecretSpec = - new TlsMasterSecretParameterSpec( - new SecretKeySpec(rsaPlainPreMasterSecret, - "Generic"), 3, 3, new byte[32], - new byte[32], "SHA-256", 32, 64); - sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec, - null); - jceMasterSecretGenerator.init(jceMasterSecretSpec, null); - sunPKCS11MasterSecret = - sunPKCS11MasterSecretGenerator.generateKey(); - jceMasterSecret = jceMasterSecretGenerator.generateKey(); - if (enableDebug) { - System.out.println("Master Secret (SunJCE):"); - if (jceMasterSecret != null) { - for (byte b : jceMasterSecret.getEncoded()) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - } - } - } - - // Generate authentication codes - byte[] sunPKCS11AuthenticationCode = null; - byte[] jceAuthenticationCode = null; - { - // Generate SunPKCS11 authentication code - { - @SuppressWarnings("deprecation") - TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec = - new TlsPrfParameterSpec(sunPKCS11MasterSecret, - "client finished", "a".getBytes(), 12, - "SHA-256", 32, 64); - KeyGenerator sunPKCS11AuthCodeGenerator = - KeyGenerator.getInstance("SunTls12Prf", - sunPKCS11NSSProvider); - sunPKCS11AuthCodeGenerator.init( - sunPKCS11AuthenticationCodeSpec); - sunPKCS11AuthenticationCode = - sunPKCS11AuthCodeGenerator.generateKey().getEncoded(); - } - - // Generate SunJCE authentication code - { - @SuppressWarnings("deprecation") - TlsPrfParameterSpec jceAuthenticationCodeSpec = - new TlsPrfParameterSpec(jceMasterSecret, - "client finished", "a".getBytes(), 12, - "SHA-256", 32, 64); - KeyGenerator jceAuthCodeGenerator = - KeyGenerator.getInstance("SunTls12Prf", - sunJCEProvider); - jceAuthCodeGenerator.init(jceAuthenticationCodeSpec); - jceAuthenticationCode = - jceAuthCodeGenerator.generateKey().getEncoded(); - } - - if (enableDebug) { - System.out.println("SunPKCS11 Authentication Code: "); - for (byte b : sunPKCS11AuthenticationCode) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - System.out.println("SunJCE Authentication Code: "); - for (byte b : jceAuthenticationCode) { - System.out.printf("%02X, ", b); - } - System.out.println(""); - } - } - - if (sunPKCS11AuthenticationCode == null || - jceAuthenticationCode == null || - sunPKCS11AuthenticationCode.length == 0 || - jceAuthenticationCode.length == 0 || - !Arrays.equals(sunPKCS11AuthenticationCode, - jceAuthenticationCode)) { - throw new Exception("Authentication codes from JCE" + - " and SunPKCS11 differ."); - } - } - - private static class testTLS12SunPKCS11Communication { - public static void run() throws Exception { - SSLEngine[][] enginesToTest = getSSLEnginesToTest(); - - for (SSLEngine[] engineToTest : enginesToTest) { - - SSLEngine clientSSLEngine = engineToTest[0]; - SSLEngine serverSSLEngine = engineToTest[1]; - - // SSLEngine code based on RedhandshakeFinished.java - - boolean dataDone = false; - - ByteBuffer clientOut = null; - ByteBuffer clientIn = null; - ByteBuffer serverOut = null; - ByteBuffer serverIn = null; - ByteBuffer cTOs; - ByteBuffer sTOc; - - SSLSession session = clientSSLEngine.getSession(); - int appBufferMax = session.getApplicationBufferSize(); - int netBufferMax = session.getPacketBufferSize(); - - clientIn = ByteBuffer.allocate(appBufferMax + 50); - serverIn = ByteBuffer.allocate(appBufferMax + 50); - - cTOs = ByteBuffer.allocateDirect(netBufferMax); - sTOc = ByteBuffer.allocateDirect(netBufferMax); - - clientOut = ByteBuffer.wrap( - "Hi Server, I'm Client".getBytes()); - serverOut = ByteBuffer.wrap( - "Hello Client, I'm Server".getBytes()); - - SSLEngineResult clientResult; - SSLEngineResult serverResult; - - while (!dataDone) { - clientResult = clientSSLEngine.wrap(clientOut, cTOs); - runDelegatedTasks(clientResult, clientSSLEngine); - serverResult = serverSSLEngine.wrap(serverOut, sTOc); - runDelegatedTasks(serverResult, serverSSLEngine); - cTOs.flip(); - sTOc.flip(); - - if (enableDebug) { - System.out.println("Client -> Network"); - printTlsNetworkPacket("", cTOs); - System.out.println(""); - System.out.println("Server -> Network"); - printTlsNetworkPacket("", sTOc); - System.out.println(""); - } - - clientResult = clientSSLEngine.unwrap(sTOc, clientIn); - runDelegatedTasks(clientResult, clientSSLEngine); - serverResult = serverSSLEngine.unwrap(cTOs, serverIn); - runDelegatedTasks(serverResult, serverSSLEngine); - - cTOs.compact(); - sTOc.compact(); - - if (!dataDone && - (clientOut.limit() == serverIn.position()) && - (serverOut.limit() == clientIn.position())) { - checkTransfer(serverOut, clientIn); - checkTransfer(clientOut, serverIn); - dataDone = true; - } - } - } - } - - static void printTlsNetworkPacket(String prefix, ByteBuffer bb) { - ByteBuffer slice = bb.slice(); - byte[] buffer = new byte[slice.remaining()]; - slice.get(buffer); - for (int i = 0; i < buffer.length; i++) { - System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF)); - if (i % 8 == 0 && i % 16 != 0) { - System.out.print(" "); - } - if (i % 16 == 0) { - System.out.println(""); - } - } - System.out.flush(); - } - - private static void checkTransfer(ByteBuffer a, ByteBuffer b) - throws Exception { - a.flip(); - b.flip(); - if (!a.equals(b)) { - throw new Exception("Data didn't transfer cleanly"); - } - a.position(a.limit()); - b.position(b.limit()); - a.limit(a.capacity()); - b.limit(b.capacity()); - } - - private static void runDelegatedTasks(SSLEngineResult result, - SSLEngine engine) throws Exception { - - if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { - Runnable runnable; - while ((runnable = engine.getDelegatedTask()) != null) { - runnable.run(); - } - HandshakeStatus hsStatus = engine.getHandshakeStatus(); - if (hsStatus == HandshakeStatus.NEED_TASK) { - throw new Exception( - "handshake shouldn't need additional tasks"); - } - } - } - - private static SSLEngine[][] getSSLEnginesToTest() throws Exception { - SSLEngine[][] enginesToTest = new SSLEngine[2][2]; - String[][] preferredSuites = new String[][]{ new String[] { - "TLS_RSA_WITH_AES_128_CBC_SHA256" - }, new String[] { - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" - }}; - for (int i = 0; i < enginesToTest.length; i++) { - enginesToTest[i][0] = createSSLEngine(true); - enginesToTest[i][1] = createSSLEngine(false); - enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]); - enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]); - } - return enginesToTest; - } - - static private SSLEngine createSSLEngine(boolean client) - throws Exception { - SSLEngine ssle; - KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", - jsseProvider); - kmf.init(ks, passphrase); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", - jsseProvider); - tmf.init(ts); - - SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", - jsseProvider); - sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - ssle = sslCtx.createSSLEngine("localhost", 443); - ssle.setUseClientMode(client); - SSLParameters sslParameters = ssle.getSSLParameters(); - ssle.setSSLParameters(sslParameters); - - return ssle; - } - } - - private static void initialize() throws Exception { - if (initSecmod() == false) { - return; - } - String configName = BASE + SEP + "fips.cfg"; - sunPKCS11NSSProvider = getSunPKCS11(configName); - System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider); - Security.addProvider(sunPKCS11NSSProvider); - - sunJCEProvider = new com.sun.crypto.provider.SunJCE(); - Security.addProvider(sunJCEProvider); - - Security.removeProvider("SunJSSE"); - jsseProvider =new com.sun.net.ssl.internal.ssl.Provider( - sunPKCS11NSSProvider); - Security.addProvider(jsseProvider); - System.out.println(jsseProvider.getInfo()); - - ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider); - ks.load(null, "test12".toCharArray()); - ts = ks; - - KeyStore ksPlain = readTestKeyStore(); - privateKey = (RSAPrivateKey)ksPlain.getKey("rh_rsa_sha256", - passphrase); - publicKey = (RSAPublicKey)ksPlain.getCertificate( - "rh_rsa_sha256").getPublicKey(); - } - - private static KeyStore readTestKeyStore() throws Exception { - File file = new File(System.getProperty("test.src", "."), "keystore"); - InputStream in = new FileInputStream(file); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(in, "passphrase".toCharArray()); - in.close(); - return ks; - } -} \ No newline at end of file diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/TrustManagerTest.java --- a/test/jdk/sun/security/pkcs11/fips/TrustManagerTest.java Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. - * 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 6323647 - * @summary Verify that the SunJSSE trustmanager works correctly in FIPS mode - * @author Andreas Sterbenz - * @library /test/lib .. - * @modules java.base/com.sun.net.ssl.internal.ssl - * @run main/othervm TrustManagerTest - * @run main/othervm TrustManagerTest sm TrustManagerTest.policy - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.security.KeyStore; -import java.security.Policy; -import java.security.Provider; -import java.security.Security; -import java.security.URIParameter; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -// This test belongs more in JSSE than here, but the JSSE workspace does not -// have the NSS test infrastructure. It will live here for the time being. - -public class TrustManagerTest extends SecmodTest { - - public static void main(String[] args) throws Exception { - if (initSecmod() == false) { - return; - } - - if ("sparc".equals(System.getProperty("os.arch")) == false) { - // we have not updated other platforms with the proper NSS libraries yet - System.out.println("Test currently works only on solaris-sparc, skipping"); - return; - } - - String configName = BASE + SEP + "fips.cfg"; - Provider p = getSunPKCS11(configName); - - System.out.println(p); - Security.addProvider(p); - - Security.removeProvider("SunJSSE"); - Provider jsse = new com.sun.net.ssl.internal.ssl.Provider(p); - Security.addProvider(jsse); - System.out.println(jsse.getInfo()); - - KeyStore ks = KeyStore.getInstance("PKCS11", p); - ks.load(null, "test12".toCharArray()); - - X509Certificate server = loadCertificate("certs/server.cer"); - X509Certificate ca = loadCertificate("certs/ca.cer"); - X509Certificate anchor = loadCertificate("certs/anchor.cer"); - - if (args.length > 1 && "sm".equals(args[0])) { - Policy.setPolicy(Policy.getInstance("JavaPolicy", - new URIParameter(new File(BASE, args[1]).toURI()))); - System.setSecurityManager(new SecurityManager()); - } - - KeyStore trustStore = KeyStore.getInstance("JKS"); - trustStore.load(null, null); - trustStore.setCertificateEntry("anchor", anchor); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); - tmf.init(trustStore); - - X509TrustManager tm = (X509TrustManager)tmf.getTrustManagers()[0]; - - X509Certificate[] chain = {server, ca, anchor}; - - tm.checkServerTrusted(chain, "RSA"); - - System.out.println("OK"); - } - - private static X509Certificate loadCertificate(String name) throws Exception { - try (InputStream in = new FileInputStream(BASE + SEP + name)) { - return (X509Certificate) CertificateFactory.getInstance("X.509") - .generateCertificate(in); - } - } - -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/TrustManagerTest.policy --- a/test/jdk/sun/security/pkcs11/fips/TrustManagerTest.policy Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -grant { - -}; \ No newline at end of file diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/cert8.db Binary file test/jdk/sun/security/pkcs11/fips/cert8.db has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/certs/anchor.cer Binary file test/jdk/sun/security/pkcs11/fips/certs/anchor.cer has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/certs/ca.cer Binary file test/jdk/sun/security/pkcs11/fips/certs/ca.cer has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/certs/server.cer Binary file test/jdk/sun/security/pkcs11/fips/certs/server.cer has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/fips.cfg --- a/test/jdk/sun/security/pkcs11/fips/fips.cfg Sun Feb 17 12:20:37 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ - -name = NSSKeyStore - -nssSecmodDirectory = ${pkcs11test.nss.db} - -nssLibraryDirectory = ${pkcs11test.nss.libdir} - -nssModule = fips - -# NSS needs CKA_NETSCAPE_DB for DSA and DH private keys -# just put an arbitrary value in there to make it happy - -attributes(*,CKO_PRIVATE_KEY,CKK_DSA) = { - CKA_NETSCAPE_DB = 0h00 -} - -attributes(*,CKO_PRIVATE_KEY,CKK_DH) = { - CKA_NETSCAPE_DB = 0h00 -} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/key3.db Binary file test/jdk/sun/security/pkcs11/fips/key3.db has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/keystore Binary file test/jdk/sun/security/pkcs11/fips/keystore has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/secmod.db Binary file test/jdk/sun/security/pkcs11/fips/secmod.db has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/security/pkcs11/fips/truststore Binary file test/jdk/sun/security/pkcs11/fips/truststore has changed diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/tools/jcmd/TestProcess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/sun/tools/jcmd/TestProcess.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package test; + +public class TestProcess { + + public static void main(String[] args) throws Exception { + System.out.print("The process started, pid:" + ProcessHandle.current().pid()); + while(true) { + Thread.sleep(100); + } + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/jdk/sun/tools/jcmd/TestProcessHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/sun/tools/jcmd/TestProcessHelper.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,259 @@ +/* + * 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. + */ + +import jdk.internal.module.ModuleInfoWriter; +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.JarUtils; +import sun.tools.common.ProcessHelper; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.module.ModuleDescriptor; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/* + * @test + * @bug 8205654 + * @summary Unit test for sun.tools.ProcessHelper class. The test launches Java processes with different Java options + * and checks that sun.tools.ProcessHelper.getMainClass(pid) method returns a correct main class. return a . + * + * @requires os.family == "linux" + * @library /test/lib + * @modules jdk.jcmd/sun.tools.common + * java.base/jdk.internal.module + * @build test.TestProcess + * @run main/othervm TestProcessHelper + */ +public class TestProcessHelper { + + private ProcessHelper PROCESS_HELPER = ProcessHelper.platformProcessHelper(); + + private static final String TEST_PROCESS_MAIN_CLASS_NAME = "TestProcess"; + private static final String TEST_PROCESS_MAIN_CLASS_PACKAGE = "test"; + private static final String TEST_PROCESS_MAIN_CLASS = TEST_PROCESS_MAIN_CLASS_PACKAGE + "." + + TEST_PROCESS_MAIN_CLASS_NAME; + private static final Path TEST_CLASSES = FileSystems.getDefault().getPath(System.getProperty("test.classes")); + private static final Path USER_DIR = FileSystems.getDefault().getPath(System.getProperty("user.dir", ".")); + private static final Path TEST_MODULES = USER_DIR.resolve("testmodules"); + private static final String JAVA_PATH = JDKToolFinder.getJDKTool("java"); + private static final Path TEST_CLASS = TEST_CLASSES.resolve(TEST_PROCESS_MAIN_CLASS_PACKAGE) + .resolve(TEST_PROCESS_MAIN_CLASS_NAME + ".class"); + + private static final String[] CP_OPTIONS = {"-cp", "-classpath", "--class-path"}; + private static final String[][] VM_ARGS = {{}, {"-Dtest1=aaa"}, {"-Dtest1=aaa", "-Dtest2=bbb"}}; + private static final String[][] ARGS = {{}, {"param1"}, {"param1", "param2"}}; + private static final String[] MP_OPTIONS = {"-p", "--module-path"}; + private static final String[] MODULE_OPTIONS = {"-m", "--module"}; + private static final String JAR_OPTION = "-jar"; + private static final String MODULE_NAME = "module1"; + + + public static void main(String[] args) throws Exception { + new TestProcessHelper().runTests(); + } + + public void runTests() throws Exception { + testClassPath(); + testJar(); + testModule(); + } + + // Test Java processes that are started with -classpath, -cp, or --class-path options + // and with different combinations of VM and program args. + private void testClassPath() throws Exception { + for (String cp : CP_OPTIONS) { + for (String[] vma : VM_ARGS) { + for (String[] arg : ARGS) { + List cmd = new LinkedList<>(); + cmd.add(JAVA_PATH); + cmd.add(cp); + cmd.add(TEST_CLASSES.toAbsolutePath().toString()); + for (String v : vma) { + cmd.add(v); + } + cmd.add(TEST_PROCESS_MAIN_CLASS); + for (String a : arg) { + cmd.add(a); + } + testProcessHelper(cmd); + } + } + } + } + + // Test Java processes that are started with -jar option + // and with different combinations of VM and program args. + private void testJar() throws Exception { + File jarFile = prepareJar(); + for (String[] vma : VM_ARGS) { + for (String[] arg : ARGS) { + List cmd = new LinkedList<>(); + cmd.add(JAVA_PATH); + for (String v : vma) { + cmd.add(v); + } + cmd.add(JAR_OPTION); + cmd.add(jarFile.getAbsolutePath()); + for (String a : arg) { + cmd.add(a); + } + testProcessHelper(cmd); + } + } + + } + + // Test Java processes that are started with -m or --module options + // and with different combination of VM and program args. + private void testModule() throws Exception { + prepareModule(); + for (String mp : MP_OPTIONS) { + for (String m : MODULE_OPTIONS) { + for (String[] vma : VM_ARGS) { + for (String[] arg : ARGS) { + List cmd = new LinkedList<>(); + cmd.add(JAVA_PATH); + cmd.add(mp); + cmd.add(TEST_MODULES.toAbsolutePath().toString()); + for (String v : vma) { + cmd.add(v); + } + cmd.add(m); + cmd.add(MODULE_NAME + "/" + TEST_PROCESS_MAIN_CLASS); + for (String a : arg) { + cmd.add(a); + } + testProcessHelper(cmd); + } + } + } + } + } + + private void checkMainClass(Process p, String expectedMainClass) { + String mainClass = PROCESS_HELPER.getMainClass(Long.toString(p.pid())); + p.destroyForcibly(); + if (!expectedMainClass.equals(mainClass)) { + throw new RuntimeException("Main class is wrong: " + mainClass); + } + } + + private void testProcessHelper(List args) throws Exception { + ProcessBuilder pb = new ProcessBuilder(args); + String cmd = pb.command().stream().collect(Collectors.joining(" ")); + System.out.println("Starting the process:" + cmd); + Process p = ProcessTools.startProcess("test", pb); + if (!p.isAlive()) { + throw new RuntimeException("Cannot start the process: " + cmd); + } + checkMainClass(p, TEST_PROCESS_MAIN_CLASS); + } + + private File prepareJar() throws Exception { + Path jarFile = USER_DIR.resolve("testprocess.jar"); + Manifest manifest = createManifest(); + JarUtils.createJarFile(jarFile, manifest, TEST_CLASSES, TEST_CLASS); + return jarFile.toFile(); + } + + private void prepareModule() throws Exception { + TEST_MODULES.toFile().mkdirs(); + Path moduleJar = TEST_MODULES.resolve("mod1.jar"); + ModuleDescriptor md = createModuleDescriptor(); + createModuleJarFile(moduleJar, md, TEST_CLASSES, TEST_CLASS); + } + + private Manifest createManifest() { + Manifest manifest = new Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, TEST_PROCESS_MAIN_CLASS); + return manifest; + } + + private ModuleDescriptor createModuleDescriptor() { + ModuleDescriptor.Builder builder + = ModuleDescriptor.newModule(MODULE_NAME).requires("java.base"); + return builder.build(); + } + + private static void createModuleJarFile(Path jarfile, ModuleDescriptor md, Path dir, Path... files) + throws IOException { + + Path parent = jarfile.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + + List entries = findAllRegularFiles(dir, files); + + try (OutputStream out = Files.newOutputStream(jarfile); + JarOutputStream jos = new JarOutputStream(out)) { + if (md != null) { + JarEntry je = new JarEntry("module-info.class"); + jos.putNextEntry(je); + ModuleInfoWriter.write(md, jos); + jos.closeEntry(); + } + + for (Path entry : entries) { + String name = toJarEntryName(entry); + jos.putNextEntry(new JarEntry(name)); + Files.copy(dir.resolve(entry), jos); + jos.closeEntry(); + } + } + } + + private static String toJarEntryName(Path file) { + Path normalized = file.normalize(); + return normalized.subpath(0, normalized.getNameCount()) + .toString() + .replace(File.separatorChar, '/'); + } + + private static List findAllRegularFiles(Path dir, Path[] files) throws IOException { + List entries = new ArrayList<>(); + for (Path file : files) { + try (Stream stream = Files.find(dir.resolve(file), Integer.MAX_VALUE, + (p, attrs) -> attrs.isRegularFile())) { + stream.map(dir::relativize) + .forEach(entries::add); + } + } + return entries; + } + +} diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java Sun Feb 17 12:21:11 2019 +0000 @@ -69,9 +69,7 @@ "-linkoffline", url, testSrc + "/jdk", "-package", "pkg", "mylib.lang"); - checkExit(Exit.ERROR); - checkOutput(Output.OUT, true, - "tag not supported in the generated HTML version: tt"); + checkExit(Exit.OK); checkOutput("pkg/C.html", true, "A method with html tag the method " + "getSystemClassLoader()" + + " title=\"class or interface in java.lang\" class=\"externalLink\">getSystemClassLoader()" + " as the parent class loader.", "
    is equivalent to invoking " + "" + "createTempFile(prefix, suffix, null).
    ", "Link-Plain to String Class", - "getSystemClassLoader()", + "getSystemClassLoader()", "createTempFile(prefix, suffix, null)", "
    RFC 2279: UTF-8, a\n" + " transformation format of ISO 10646,
    getSystemClassLoader()} as the parent class loader. + * getSystemClassLoader()} as the parent class loader. */ public void method1() {} diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/6304921/TestLog.java --- a/test/langtools/tools/javac/6304921/TestLog.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/langtools/tools/javac/6304921/TestLog.java Sun Feb 17 12:21:11 2019 +0000 @@ -76,7 +76,7 @@ Set defaultErrorFlags = (Set) defaultErrorFlagsField.get(diagnosticFactory); - defaultErrorFlags.add(DiagnosticFlag.MULTIPLE); + defaultErrorFlags.add(DiagnosticFlag.API); JavacFileManager.preRegister(context); ParserFactory pfac = ParserFactory.instance(context); diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/diags/examples.not-yet.txt --- a/test/langtools/tools/javac/diags/examples.not-yet.txt Sun Feb 17 12:20:37 2019 +0000 +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt Sun Feb 17 12:21:11 2019 +0000 @@ -125,6 +125,7 @@ compiler.misc.bad.const.pool.entry # constant pool entry has wrong type compiler.warn.access.to.member.from.serializable.lambda # in order to generate it we need to modify a restricted package compiler.warn.invalid.path # this warning is generated only in Windows systems +compiler.err.invalid.path # this error is generated only in Windows systems compiler.note.multiple.elements # needs user code compiler.err.preview.feature.disabled.classfile # preview feature support: needs compilation against classfile compiler.warn.preview.feature.use.classfile # preview feature support: needs compilation against classfile diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/options/T6986895.java --- a/test/langtools/tools/javac/options/T6986895.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/langtools/tools/javac/options/T6986895.java Sun Feb 17 12:21:11 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 6986895 + * @bug 8201544 * @summary compiler gives misleading message for no input files * @modules jdk.compiler */ @@ -38,6 +39,8 @@ String noSourceFiles = "no source files"; String noSourceFilesOrClasses = "no source files or class names"; + String invalidFileName = "Invalid filename"; + boolean isWindows = System.getProperty("os.name").startsWith("Windows"); void run() throws Exception { Locale prev = Locale.getDefault(); @@ -45,6 +48,8 @@ Locale.setDefault(Locale.ENGLISH); test(noSourceFiles, "-Werror"); test(noSourceFilesOrClasses, "-Werror", "-Xprint"); + if (isWindows) + test(invalidFileName, "-Werror", "someNonExistingFile*.java"); } finally { Locale.setDefault(prev); } diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/processing/6994946/SemanticErrorTest.2.out --- a/test/langtools/tools/javac/processing/6994946/SemanticErrorTest.2.out Sun Feb 17 12:20:37 2019 +0000 +++ b/test/langtools/tools/javac/processing/6994946/SemanticErrorTest.2.out Sun Feb 17 12:21:11 2019 +0000 @@ -1,3 +1,4 @@ +- compiler.err.proc.messager: Deliberate Error +SemanticErrorTest.java:13:1: compiler.err.proc.messager: Deliberate Error on Trees SemanticErrorTest.java:13:46: compiler.err.repeated.interface -- compiler.err.proc.messager: Deliberate Error -2 errors +3 errors diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/processing/6994946/TestProcessor.java --- a/test/langtools/tools/javac/processing/6994946/TestProcessor.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/langtools/tools/javac/processing/6994946/TestProcessor.java Sun Feb 17 12:21:11 2019 +0000 @@ -27,13 +27,21 @@ import javax.lang.model.element.*; import static javax.tools.Diagnostic.Kind.*; +import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; + public class TestProcessor extends JavacTestingAbstractProcessor { private int round = 0; public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (++round == 1) + if (++round == 1) { messager.printMessage(ERROR, "Deliberate Error"); + Trees trees = Trees.instance(processingEnv); + TreePath elPath = trees.getPath(roundEnv.getRootElements().iterator().next()); + trees.printMessage(ERROR, "Deliberate Error on Trees", + elPath.getLeaf(), elPath.getCompilationUnit()); + } return false; } } diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/processing/GenerateAndError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/processing/GenerateAndError.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,57 @@ +/* + * 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 8217381 + * @summary Check error are convenient when AP generates a source file and + * an error in the same round + * @library /tools/javac/lib + * @modules jdk.compiler + * @build JavacTestingAbstractProcessor GenerateAndError + * @compile/fail/ref=GenerateAndError.out -XDrawDiagnostics -processor GenerateAndError GenerateAndErrorTest.java + */ + +import java.io.IOException; +import java.io.Writer; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +public class GenerateAndError extends JavacTestingAbstractProcessor { + int round = 0; + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (round++ == 0) { + try (Writer w = processingEnv.getFiler().createSourceFile("Extra").openWriter()) { + w.write("public class Extra {}"); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + processingEnv.getMessager().printMessage(Kind.ERROR, "error"); + } + return false; + } +} diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/processing/GenerateAndError.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/processing/GenerateAndError.out Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,3 @@ +- compiler.err.proc.messager: error +GenerateAndErrorTest.java:2:60: compiler.err.cant.resolve: kindname.class, ExtraExtra, , +2 errors diff -r 4964feb6d75d -r de9dd71ef18c test/langtools/tools/javac/processing/GenerateAndErrorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/processing/GenerateAndErrorTest.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,2 @@ +/* /nodynamiccopyright/ */ +public class GenerateAndErrorTest extends Extra implements ExtraExtra {} diff -r 4964feb6d75d -r de9dd71ef18c test/lib/jdk/test/lib/SecurityTools.java --- a/test/lib/jdk/test/lib/SecurityTools.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/lib/jdk/test/lib/SecurityTools.java Sun Feb 17 12:21:11 2019 +0000 @@ -195,5 +195,33 @@ public static OutputAnalyzer jarsigner(String... args) throws Exception { return jarsigner(List.of(args)); } + + /** + * Runs ktab. + * + * @param args arguments to ktab in a single string. Only call this if + * there is no white space inside an argument. This string will + * be split with {@code \s+}. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer ktab(String args) throws Exception { + return execute(getProcessBuilder( + "ktab", List.of(args.trim().split("\\s+")))); + } + + /** + * Runs klist. + * + * @param args arguments to klist in a single string. Only call this if + * there is no white space inside an argument. This string will + * be split with {@code \s+}. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer klist(String args) throws Exception { + return execute(getProcessBuilder( + "klist", List.of(args.trim().split("\\s+")))); + } } diff -r 4964feb6d75d -r de9dd71ef18c test/lib/sun/hotspot/WhiteBox.java --- a/test/lib/sun/hotspot/WhiteBox.java Sun Feb 17 12:20:37 2019 +0000 +++ b/test/lib/sun/hotspot/WhiteBox.java Sun Feb 17 12:21:11 2019 +0000 @@ -216,6 +216,7 @@ public native void NMTUncommitMemory(long addr, long size); public native void NMTReleaseMemory(long addr, long size); public native long NMTMallocWithPseudoStack(long size, int index); + public native long NMTMallocWithPseudoStackAndType(long size, int index, int type); public native boolean NMTChangeTrackingLevel(); public native int NMTGetHashSize(); diff -r 4964feb6d75d -r de9dd71ef18c test/micro/org/openjdk/bench/java/util/HashMapBench.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/java/util/HashMapBench.java Sun Feb 17 12:21:11 2019 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018, 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 + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +import static java.util.stream.Collectors.toMap; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +public class HashMapBench { + private Supplier> mapSupplier; + private Map bigMapToAdd; + + @Param("1000000") + private int size; + + @Param + private MapType mapType; + + public enum MapType { + HASH_MAP, + LINKED_HASH_MAP, + } + + @Setup + public void setup() { + switch (mapType) { + case HASH_MAP: + mapSupplier = () -> new HashMap<>(); + break; + case LINKED_HASH_MAP: + mapSupplier = () -> new LinkedHashMap<>(); + break; + default: + throw new AssertionError(); + } + + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + this.bigMapToAdd = IntStream.range(0, size).boxed() + .collect(toMap(i -> 7 + i * 128, i -> rnd.nextInt())); + } + + @Benchmark + public int putAllWithBigMapToNonEmptyMap() { + Map map = mapSupplier.get(); + map.put(-1, -1); + map.putAll(bigMapToAdd); + return map.size(); + } + + @Benchmark + public int putAllWithBigMapToEmptyMap() { + Map map = mapSupplier.get(); + map.putAll(bigMapToAdd); + return map.size(); + } + + @Benchmark + public int put() { + Map map = mapSupplier.get(); + for (int k : bigMapToAdd.keySet()) { + map.put(k, bigMapToAdd.get(k)); + } + return map.size(); + } +}