# HG changeset patch # User duke # Date 1499280202 -7200 # Node ID f55df5cfe11c97e4b58998b76f5bd00a73cde12d # Parent 740e7c7adac0923331be9890082f1d1cbcfde50c# Parent f4b5bcf49fa3b86a5bf62168a1dedbbdf046fe0a Merge diff -r f4b5bcf49fa3 -r f55df5cfe11c .hgtags-top-repo --- a/.hgtags-top-repo Wed Jul 05 20:42:40 2017 +0200 +++ b/.hgtags-top-repo Wed Jul 05 20:43:22 2017 +0200 @@ -316,3 +316,4 @@ c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71 8582c35016fb6211b373810b6b172feccf9c483b jdk9-b72 4c2cbaae528bce970dabbb5676005d379357f4b6 jdk9-b73 +57f3134853ecdd4a3ee2d4d26f22ba981d653d79 jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c corba/.hgtags --- a/corba/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/corba/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -316,3 +316,4 @@ cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71 f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72 29096b78d93b01a2f8882509cd40755e3d6b8cd9 jdk9-b73 +622fe934e351e89107edf3c667d6b57f543f58f1 jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/.hgignore --- a/hotspot/.hgignore Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/.hgignore Wed Jul 05 20:43:22 2017 +0200 @@ -10,3 +10,4 @@ .igv.log ^.hgtip .DS_Store +\.class$ diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/.hgtags --- a/hotspot/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -476,3 +476,4 @@ 07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71 c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72 e37d432868be0aa7cb5e0f3d7caff1e825d8ead3 jdk9-b73 +fff6b54e9770ac4c12c2fb4cab5aa7672affa4bd jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -34,7 +34,6 @@ define_pd_global(bool, ConvertSleepToYield, true); define_pd_global(bool, ShareVtableStubs, true); -define_pd_global(bool, CountInterpCalls, true); define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks @@ -61,8 +60,6 @@ define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5)); -define_pd_global(intx, PreInflateSpin, 10); - define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -869,7 +869,7 @@ // native method than the typical interpreter frame setup. address InterpreterGenerator::generate_native_entry(bool synchronized) { // determine code generation flags - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // r1: Method* // rscratch1: sender sp @@ -1307,7 +1307,7 @@ // address InterpreterGenerator::generate_normal_entry(bool synchronized) { // determine code generation flags - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // rscratch1: sender sp address entry_point = __ pc(); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp --- a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2014 SAP AG. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,7 +225,7 @@ return (BasicObjectLock *) get_ijava_state(); } -// SAPJVM ASc 2012-11-21. Return register stack slot addr at which currently interpreted method is found +// Return register stack slot addr at which currently interpreted method is found. inline Method** frame::interpreter_frame_method_addr() const { return (Method**) &(get_ijava_state()->method); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/globals_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -47,8 +47,6 @@ define_pd_global(intx, InlineFrequencyCount, 100); define_pd_global(intx, InlineSmallCode, 1500); -define_pd_global(intx, PreInflateSpin, 10); - // Flags for template interpreter. define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -3433,6 +3433,376 @@ bind(Ldone_false); } +// dest_lo += src1 + src2 +// dest_hi += carry1 + carry2 +void MacroAssembler::add2_with_carry(Register dest_hi, + Register dest_lo, + Register src1, Register src2) { + li(R0, 0); + addc(dest_lo, dest_lo, src1); + adde(dest_hi, dest_hi, R0); + addc(dest_lo, dest_lo, src2); + adde(dest_hi, dest_hi, R0); +} + +// Multiply 64 bit by 64 bit first loop. +void MacroAssembler::multiply_64_x_64_loop(Register x, Register xstart, + Register x_xstart, + Register y, Register y_idx, + Register z, + Register carry, + Register product_high, Register product, + Register idx, Register kdx, + Register tmp) { + // jlong carry, x[], y[], z[]; + // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) { + // huge_128 product = y[idx] * x[xstart] + carry; + // z[kdx] = (jlong)product; + // carry = (jlong)(product >>> 64); + // } + // z[xstart] = carry; + + Label L_first_loop, L_first_loop_exit; + Label L_one_x, L_one_y, L_multiply; + + addic_(xstart, xstart, -1); + blt(CCR0, L_one_x); // Special case: length of x is 1. + + // Load next two integers of x. + sldi(tmp, xstart, LogBytesPerInt); + ldx(x_xstart, x, tmp); +#ifdef VM_LITTLE_ENDIAN + rldicl(x_xstart, x_xstart, 32, 0); +#endif + + align(32, 16); + bind(L_first_loop); + + cmpdi(CCR0, idx, 1); + blt(CCR0, L_first_loop_exit); + addi(idx, idx, -2); + beq(CCR0, L_one_y); + + // Load next two integers of y. + sldi(tmp, idx, LogBytesPerInt); + ldx(y_idx, y, tmp); +#ifdef VM_LITTLE_ENDIAN + rldicl(y_idx, y_idx, 32, 0); +#endif + + + bind(L_multiply); + multiply64(product_high, product, x_xstart, y_idx); + + li(tmp, 0); + addc(product, product, carry); // Add carry to result. + adde(product_high, product_high, tmp); // Add carry of the last addition. + addi(kdx, kdx, -2); + + // Store result. +#ifdef VM_LITTLE_ENDIAN + rldicl(product, product, 32, 0); +#endif + sldi(tmp, kdx, LogBytesPerInt); + stdx(product, z, tmp); + mr_if_needed(carry, product_high); + b(L_first_loop); + + + bind(L_one_y); // Load one 32 bit portion of y as (0,value). + + lwz(y_idx, 0, y); + b(L_multiply); + + + bind( L_one_x ); // Load one 32 bit portion of x as (0,value). + + lwz(x_xstart, 0, x); + b(L_first_loop); + + bind(L_first_loop_exit); +} + +// Multiply 64 bit by 64 bit and add 128 bit. +void MacroAssembler::multiply_add_128_x_128(Register x_xstart, Register y, + Register z, Register yz_idx, + Register idx, Register carry, + Register product_high, Register product, + Register tmp, int offset) { + + // huge_128 product = (y[idx] * x_xstart) + z[kdx] + carry; + // z[kdx] = (jlong)product; + + sldi(tmp, idx, LogBytesPerInt); + if ( offset ) { + addi(tmp, tmp, offset); + } + ldx(yz_idx, y, tmp); +#ifdef VM_LITTLE_ENDIAN + rldicl(yz_idx, yz_idx, 32, 0); +#endif + + multiply64(product_high, product, x_xstart, yz_idx); + ldx(yz_idx, z, tmp); +#ifdef VM_LITTLE_ENDIAN + rldicl(yz_idx, yz_idx, 32, 0); +#endif + + add2_with_carry(product_high, product, carry, yz_idx); + + sldi(tmp, idx, LogBytesPerInt); + if ( offset ) { + addi(tmp, tmp, offset); + } +#ifdef VM_LITTLE_ENDIAN + rldicl(product, product, 32, 0); +#endif + stdx(product, z, tmp); +} + +// Multiply 128 bit by 128 bit. Unrolled inner loop. +void MacroAssembler::multiply_128_x_128_loop(Register x_xstart, + Register y, Register z, + Register yz_idx, Register idx, Register carry, + Register product_high, Register product, + Register carry2, Register tmp) { + + // jlong carry, x[], y[], z[]; + // int kdx = ystart+1; + // for (int idx=ystart-2; idx >= 0; idx -= 2) { // Third loop + // huge_128 product = (y[idx+1] * x_xstart) + z[kdx+idx+1] + carry; + // z[kdx+idx+1] = (jlong)product; + // jlong carry2 = (jlong)(product >>> 64); + // product = (y[idx] * x_xstart) + z[kdx+idx] + carry2; + // z[kdx+idx] = (jlong)product; + // carry = (jlong)(product >>> 64); + // } + // idx += 2; + // if (idx > 0) { + // product = (y[idx] * x_xstart) + z[kdx+idx] + carry; + // z[kdx+idx] = (jlong)product; + // carry = (jlong)(product >>> 64); + // } + + Label L_third_loop, L_third_loop_exit, L_post_third_loop_done; + const Register jdx = R0; + + // Scale the index. + srdi_(jdx, idx, 2); + beq(CCR0, L_third_loop_exit); + mtctr(jdx); + + align(32, 16); + bind(L_third_loop); + + addi(idx, idx, -4); + + multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry, product_high, product, tmp, 8); + mr_if_needed(carry2, product_high); + + multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry2, product_high, product, tmp, 0); + mr_if_needed(carry, product_high); + bdnz(L_third_loop); + + bind(L_third_loop_exit); // Handle any left-over operand parts. + + andi_(idx, idx, 0x3); + beq(CCR0, L_post_third_loop_done); + + Label L_check_1; + + addic_(idx, idx, -2); + blt(CCR0, L_check_1); + + multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry, product_high, product, tmp, 0); + mr_if_needed(carry, product_high); + + bind(L_check_1); + + addi(idx, idx, 0x2); + andi_(idx, idx, 0x1) ; + addic_(idx, idx, -1); + blt(CCR0, L_post_third_loop_done); + + sldi(tmp, idx, LogBytesPerInt); + lwzx(yz_idx, y, tmp); + multiply64(product_high, product, x_xstart, yz_idx); + lwzx(yz_idx, z, tmp); + + add2_with_carry(product_high, product, yz_idx, carry); + + sldi(tmp, idx, LogBytesPerInt); + stwx(product, z, tmp); + srdi(product, product, 32); + + sldi(product_high, product_high, 32); + orr(product, product, product_high); + mr_if_needed(carry, product); + + bind(L_post_third_loop_done); +} // multiply_128_x_128_loop + +void MacroAssembler::multiply_to_len(Register x, Register xlen, + Register y, Register ylen, + Register z, Register zlen, + Register tmp1, Register tmp2, + Register tmp3, Register tmp4, + Register tmp5, Register tmp6, + Register tmp7, Register tmp8, + Register tmp9, Register tmp10, + Register tmp11, Register tmp12, + Register tmp13) { + + ShortBranchVerifier sbv(this); + + assert_different_registers(x, xlen, y, ylen, z, zlen, + tmp1, tmp2, tmp3, tmp4, tmp5, tmp6); + assert_different_registers(x, xlen, y, ylen, z, zlen, + tmp1, tmp2, tmp3, tmp4, tmp5, tmp7); + assert_different_registers(x, xlen, y, ylen, z, zlen, + tmp1, tmp2, tmp3, tmp4, tmp5, tmp8); + + const Register idx = tmp1; + const Register kdx = tmp2; + const Register xstart = tmp3; + + const Register y_idx = tmp4; + const Register carry = tmp5; + const Register product = tmp6; + const Register product_high = tmp7; + const Register x_xstart = tmp8; + const Register tmp = tmp9; + + // First Loop. + // + // final static long LONG_MASK = 0xffffffffL; + // int xstart = xlen - 1; + // int ystart = ylen - 1; + // long carry = 0; + // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx-, kdx--) { + // long product = (y[idx] & LONG_MASK) * (x[xstart] & LONG_MASK) + carry; + // z[kdx] = (int)product; + // carry = product >>> 32; + // } + // z[xstart] = (int)carry; + + mr_if_needed(idx, ylen); // idx = ylen + mr_if_needed(kdx, zlen); // kdx = xlen + ylen + li(carry, 0); // carry = 0 + + Label L_done; + + addic_(xstart, xlen, -1); + blt(CCR0, L_done); + + multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, + carry, product_high, product, idx, kdx, tmp); + + Label L_second_loop; + + cmpdi(CCR0, kdx, 0); + beq(CCR0, L_second_loop); + + Label L_carry; + + addic_(kdx, kdx, -1); + beq(CCR0, L_carry); + + // Store lower 32 bits of carry. + sldi(tmp, kdx, LogBytesPerInt); + stwx(carry, z, tmp); + srdi(carry, carry, 32); + addi(kdx, kdx, -1); + + + bind(L_carry); + + // Store upper 32 bits of carry. + sldi(tmp, kdx, LogBytesPerInt); + stwx(carry, z, tmp); + + // Second and third (nested) loops. + // + // for (int i = xstart-1; i >= 0; i--) { // Second loop + // carry = 0; + // for (int jdx=ystart, k=ystart+1+i; jdx >= 0; jdx--, k--) { // Third loop + // long product = (y[jdx] & LONG_MASK) * (x[i] & LONG_MASK) + + // (z[k] & LONG_MASK) + carry; + // z[k] = (int)product; + // carry = product >>> 32; + // } + // z[i] = (int)carry; + // } + // + // i = xlen, j = tmp1, k = tmp2, carry = tmp5, x[i] = rdx + + bind(L_second_loop); + + li(carry, 0); // carry = 0; + + addic_(xstart, xstart, -1); // i = xstart-1; + blt(CCR0, L_done); + + Register zsave = tmp10; + + mr(zsave, z); + + + Label L_last_x; + + sldi(tmp, xstart, LogBytesPerInt); + add(z, z, tmp); // z = z + k - j + addi(z, z, 4); + addic_(xstart, xstart, -1); // i = xstart-1; + blt(CCR0, L_last_x); + + sldi(tmp, xstart, LogBytesPerInt); + ldx(x_xstart, x, tmp); +#ifdef VM_LITTLE_ENDIAN + rldicl(x_xstart, x_xstart, 32, 0); +#endif + + + Label L_third_loop_prologue; + + bind(L_third_loop_prologue); + + Register xsave = tmp11; + Register xlensave = tmp12; + Register ylensave = tmp13; + + mr(xsave, x); + mr(xlensave, xstart); + mr(ylensave, ylen); + + + multiply_128_x_128_loop(x_xstart, y, z, y_idx, ylen, + carry, product_high, product, x, tmp); + + mr(z, zsave); + mr(x, xsave); + mr(xlen, xlensave); // This is the decrement of the loop counter! + mr(ylen, ylensave); + + addi(tmp3, xlen, 1); + sldi(tmp, tmp3, LogBytesPerInt); + stwx(carry, z, tmp); + addic_(tmp3, tmp3, -1); + blt(CCR0, L_done); + + srdi(carry, carry, 32); + sldi(tmp, tmp3, LogBytesPerInt); + stwx(carry, z, tmp); + b(L_second_loop); + + // Next infrequent code is moved outside loops. + bind(L_last_x); + + lwz(x_xstart, 0, x); + b(L_third_loop_prologue); + + bind(L_done); +} // multiply_to_len void MacroAssembler::asm_assert(bool check_equal, const char *msg, int id) { #ifdef ASSERT diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -677,6 +677,31 @@ void char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg, Register tmp1_reg, Register tmp2_reg); + // Emitters for BigInteger.multiplyToLen intrinsic. + inline void multiply64(Register dest_hi, Register dest_lo, + Register x, Register y); + void add2_with_carry(Register dest_hi, Register dest_lo, + Register src1, Register src2); + void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart, + Register y, Register y_idx, Register z, + Register carry, Register product_high, Register product, + Register idx, Register kdx, Register tmp); + void multiply_add_128_x_128(Register x_xstart, Register y, Register z, + Register yz_idx, Register idx, Register carry, + Register product_high, Register product, Register tmp, + int offset); + void multiply_128_x_128_loop(Register x_xstart, + Register y, Register z, + Register yz_idx, Register idx, Register carry, + Register product_high, Register product, + Register carry2, Register tmp); + void multiply_to_len(Register x, Register xlen, + Register y, Register ylen, + Register z, Register zlen, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, + Register tmp6, Register tmp7, Register tmp8, Register tmp9, Register tmp10, + Register tmp11, Register tmp12, Register tmp13); + // // Debugging // diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -423,6 +423,13 @@ twi(traptoEqual | traptoGreaterThanUnsigned, a/*reg a*/, si16); } +// unsigned integer multiplication 64*64 -> 128 bits +inline void MacroAssembler::multiply64(Register dest_hi, Register dest_lo, + Register x, Register y) { + mulld(dest_lo, x, y); + mulhdu(dest_hi, x, y); +} + #if defined(ABI_ELFv2) inline address MacroAssembler::function_entry() { return pc(); } #else diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Wed Jul 05 20:43:22 2017 +0200 @@ -10930,7 +10930,7 @@ instruct cmpFastLock(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3) %{ match(Set crx (FastLock oop box)); effect(TEMP tmp1, TEMP tmp2, TEMP tmp3); - predicate(/*(!UseNewFastLockPPC64 || UseBiasedLocking) &&*/ !Compile::current()->use_rtm()); + predicate(!Compile::current()->use_rtm()); format %{ "FASTLOCK $oop, $box, $tmp1, $tmp2, $tmp3" %} ins_encode %{ diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -2053,6 +2053,79 @@ __ blr(); } + // Stub for BigInteger::multiplyToLen() + // + // Arguments: + // + // Input: + // R3 - x address + // R4 - x length + // R5 - y address + // R6 - y length + // R7 - z address + // R8 - z length + // + address generate_multiplyToLen() { + + StubCodeMark mark(this, "StubRoutines", "multiplyToLen"); + + address start = __ function_entry(); + + const Register x = R3; + const Register xlen = R4; + const Register y = R5; + const Register ylen = R6; + const Register z = R7; + const Register zlen = R8; + + const Register tmp1 = R2; // TOC not used. + const Register tmp2 = R9; + const Register tmp3 = R10; + const Register tmp4 = R11; + const Register tmp5 = R12; + + // non-volatile regs + const Register tmp6 = R31; + const Register tmp7 = R30; + const Register tmp8 = R29; + const Register tmp9 = R28; + const Register tmp10 = R27; + const Register tmp11 = R26; + const Register tmp12 = R25; + const Register tmp13 = R24; + + BLOCK_COMMENT("Entry:"); + + // Save non-volatile regs (frameless). + int current_offs = 8; + __ std(R24, -current_offs, R1_SP); current_offs += 8; + __ std(R25, -current_offs, R1_SP); current_offs += 8; + __ std(R26, -current_offs, R1_SP); current_offs += 8; + __ std(R27, -current_offs, R1_SP); current_offs += 8; + __ std(R28, -current_offs, R1_SP); current_offs += 8; + __ std(R29, -current_offs, R1_SP); current_offs += 8; + __ std(R30, -current_offs, R1_SP); current_offs += 8; + __ std(R31, -current_offs, R1_SP); + + __ multiply_to_len(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, + tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13); + + // Restore non-volatile regs. + current_offs = 8; + __ ld(R24, -current_offs, R1_SP); current_offs += 8; + __ ld(R25, -current_offs, R1_SP); current_offs += 8; + __ ld(R26, -current_offs, R1_SP); current_offs += 8; + __ ld(R27, -current_offs, R1_SP); current_offs += 8; + __ ld(R28, -current_offs, R1_SP); current_offs += 8; + __ ld(R29, -current_offs, R1_SP); current_offs += 8; + __ ld(R30, -current_offs, R1_SP); current_offs += 8; + __ ld(R31, -current_offs, R1_SP); + + __ blr(); // Return to caller. + + return start; + } + // Initialization void generate_initial() { // Generates all stubs and initializes the entry points @@ -2102,6 +2175,12 @@ generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry, &StubRoutines::_safefetchN_fault_pc, &StubRoutines::_safefetchN_continuation_pc); + +#ifdef COMPILER2 + if (UseMultiplyToLenIntrinsic) { + StubRoutines::_multiplyToLen = generate_multiplyToLen(); + } +#endif } public: diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -668,7 +668,7 @@ address entry = __ pc(); - const bool inc_counter = UseCompiler || CountCompiledCalls; + const bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // ----------------------------------------------------------------------------- // Allocate a new frame that represents the native callee (i2n frame). @@ -1118,7 +1118,7 @@ // Generic interpreted method entry to (asm) interpreter. // address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; address entry = __ pc(); // Generate the code to allocate the interpreter stack frame. Register Rsize_of_parameters = R4_ARG2, // Written by generate_fixed_frame. diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -198,6 +198,10 @@ FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); } + if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { + UseMultiplyToLenIntrinsic = true; + } + // Adjust RTM (Restricted Transactional Memory) flags. if (!has_tcheck() && UseRTMLocking) { // Can't continue because UseRTMLocking affects UseBiasedLocking flag @@ -228,7 +232,6 @@ warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50"); FLAG_SET_DEFAULT(RTMAbortRatio, 50); } - FLAG_SET_ERGO(bool, UseNewFastLockPPC64, false); // Does not implement TM. guarantee(RTMSpinLoopCount > 0, "unsupported"); #else // Only C2 does RTM locking optimization. diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/sparc/vm/globals_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -39,7 +39,6 @@ define_pd_global(bool, DontYieldALot, true); // yield no more than 100 times per second define_pd_global(bool, ConvertSleepToYield, false); // do not convert sleep(0) to yield. Helps GUI define_pd_global(bool, ShareVtableStubs, false); // improves performance markedly for mtrt and compress -define_pd_global(bool, CountInterpCalls, false); // not implemented in the interpreter define_pd_global(bool, NeedsDeoptSuspend, true); // register window machines need this define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks @@ -67,8 +66,6 @@ define_pd_global(intx, StackYellowPages, 2); define_pd_global(intx, StackRedPages, 1); -define_pd_global(intx, PreInflateSpin, 40); // Determined by running design center - define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -801,7 +801,7 @@ // the following temporary registers are used during frame creation const Register Gtmp1 = G3_scratch ; const Register Gtmp2 = G1_scratch; - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // make sure registers are different! assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2); @@ -1225,7 +1225,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { address entry = __ pc(); - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // the following temporary registers are used during frame creation const Register Gtmp1 = G3_scratch ; diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -308,7 +308,7 @@ } } else if (UseGHASHIntrinsics) { if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics)) - warning("GHASH intrinsics require VIS3 insructions support. Intriniscs will be disabled"); + warning("GHASH intrinsics require VIS3 instruction support. Intrinsics will be disabled"); FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/x86/vm/globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -33,7 +33,6 @@ define_pd_global(bool, ConvertSleepToYield, true); define_pd_global(bool, ShareVtableStubs, true); -define_pd_global(bool, CountInterpCalls, true); define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks @@ -66,8 +65,6 @@ define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5)); #endif // AMD64 -define_pd_global(intx, PreInflateSpin, 10); - define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1781,6 +1781,7 @@ cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); } else if ((EmitSync & 128) == 0) { // avoid ST-before-CAS + // register juggle because we need tmpReg for cmpxchgptr below movptr(scrReg, boxReg); movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] @@ -1814,7 +1815,10 @@ } cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3 + // If we weren't able to swing _owner from NULL to the BasicLock + // then take the slow path. jccb (Assembler::notZero, DONE_LABEL); + // update _owner from BasicLock to thread get_thread (scrReg); // beware: clobbers ICCs movptr(Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), scrReg); xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success @@ -2083,6 +2087,9 @@ xorptr(boxReg, boxReg); // box is really EAX if (os::is_MP()) { lock(); } cmpxchgptr(rsp, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); + // There's no successor so we tried to regrab the lock with the + // placeholder value. If that didn't work, then another thread + // grabbed the lock so we're done (and exit was a success). jccb (Assembler::notEqual, LSuccess); // Since we're low on registers we installed rsp as a placeholding in _owner. // Now install Self over rsp. This is safe as we're transitioning from @@ -2190,6 +2197,9 @@ movptr(boxReg, (int32_t)NULL_WORD); if (os::is_MP()) { lock(); } cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); + // There's no successor so we tried to regrab the lock. + // If that didn't work, then another thread grabbed the + // lock so we're done (and exit was a success). jccb (Assembler::notEqual, LSuccess); // Intentional fall-through into slow-path diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -2456,7 +2456,8 @@ // allocate space for the code ResourceMark rm; // setup code generation tools - CodeBuffer buffer("deopt_blob", 1024, 1024); + // note: the buffer code size must account for StackShadowPages=50 + CodeBuffer buffer("deopt_blob", 1536, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; OopMap* map = NULL; diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -2780,6 +2780,7 @@ const XMMRegister xmm_temp7 = xmm7; __ enter(); + handleSOERegisters(true); // Save registers __ movptr(state, state_param); __ movptr(subkeyH, subkeyH_param); @@ -2883,6 +2884,7 @@ __ pshufb(xmm_temp6, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr())); __ movdqu(Address(state, 0), xmm_temp6); // store the result + handleSOERegisters(false); // restore registers __ leave(); __ ret(0); return start; diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -849,7 +849,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // determine code generation flags - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // rbx,: Method* // rsi: sender sp @@ -1265,7 +1265,7 @@ // address InterpreterGenerator::generate_normal_entry(bool synchronized) { // determine code generation flags - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // rbx,: Method* // rsi: sender sp diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -809,7 +809,7 @@ // native method than the typical interpreter frame setup. address InterpreterGenerator::generate_native_entry(bool synchronized) { // determine code generation flags - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // rbx: Method* // r13: sender sp @@ -1256,7 +1256,7 @@ // address InterpreterGenerator::generate_normal_entry(bool synchronized) { // determine code generation flags - bool inc_counter = UseCompiler || CountCompiledCalls; + bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods; // ebx: Method* // r13: sender sp diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/cpu/zero/vm/globals_zero.hpp --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -34,7 +34,6 @@ define_pd_global(bool, ConvertSleepToYield, true); define_pd_global(bool, ShareVtableStubs, true); -define_pd_global(bool, CountInterpCalls, true); define_pd_global(bool, NeedsDeoptSuspend, false); define_pd_global(bool, ImplicitNullChecks, true); @@ -45,7 +44,6 @@ define_pd_global(intx, OptoLoopAlignment, 16); define_pd_global(intx, InlineFrequencyCount, 100); define_pd_global(intx, InlineSmallCode, 1000 ); -define_pd_global(intx, PreInflateSpin, 10); define_pd_global(intx, StackYellowPages, 2); define_pd_global(intx, StackRedPages, 1); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -3740,15 +3740,6 @@ "stack size not a multiple of page size"); initialize_performance_counter(); - - // Win95/Win98 scheduler bug work-around. The Win95/98 scheduler is - // known to deadlock the system, if the VM issues to thread operations with - // a too high frequency, e.g., such as changing the priorities. - // The 6000 seems to work well - no deadlocks has been notices on the test - // programs that we have seen experience this problem. - if (!os::win32::is_nt()) { - StarvationMonitorInterval = 6000; - } } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/Makefile --- a/hotspot/src/share/tools/LogCompilation/Makefile Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/Makefile Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ logc.jar: filelist manifest.mf @mkdir -p $(OUTPUT_DIR) - $(JAVAC) -source 1.5 -deprecation -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) @filelist + $(JAVAC) -deprecation -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) @filelist $(JAR) cvfm logc.jar manifest.mf -C $(OUTPUT_DIR) com .PHONY: filelist diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,29 @@ import java.io.PrintStream; /** - * - * @author never + * Provide basic data structures and behaviour for {@link LogEvent}s. */ public abstract class BasicLogEvent implements LogEvent { + /** + * The event's ID. This is a number; we represent it as a string for + * convenience. + */ protected final String id; + + /** + * The event's start time. + */ protected final double start; + + /** + * The event's end time. + */ protected double end; + + /** + * The compilation during which this event was signalled. + */ protected Compilation compilation; BasicLogEvent(double start, String id) { @@ -43,33 +58,37 @@ this.id = id; } - public double getStart() { + public final double getStart() { return start; } - public double getEnd() { + public final double getEnd() { return end; } - public void setEnd(double end) { + public final void setEnd(double end) { this.end = end; } - public double getElapsedTime() { + public final double getElapsedTime() { return ((int) ((getEnd() - getStart()) * 1000)) / 1000.0; } - public String getId() { + public final String getId() { return id; } - public Compilation getCompilation() { + public final Compilation getCompilation() { return compilation; } + /** + * Set the compilation for this event. This is not a {@code final} method + * as it is overridden in {@link UncommonTrapEvent}. + */ public void setCompilation(Compilation compilation) { this.compilation = compilation; } - abstract public void print(PrintStream stream); + abstract public void print(PrintStream stream, boolean printID); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,41 +29,119 @@ import java.util.ArrayList; import java.util.List; +/** + * Representation of a compilation scope in a compilation log. This class is a + * hybrid: its instances can represent original scopes of methods being + * compiled, but are also used to represent call sites in given methods. + */ public class CallSite { + /** + * The index of the call in the caller. This will be 0 if this instance + * represents a compilation root. + */ private int bci; + + /** + * The method that is called at this call site. This will be {@code null} + * if this instance represents a compilation root. + */ private Method method; + + /** + * The invocation count for this call site. + */ private int count; + + /** + * The receiver type of the call represented by this instance, if known. + */ private String receiver; + + /** + * In case the {@linkplain receiver receiver type} of the call represented + * by this instance is known, this is how often the type was encountered. + */ private int receiver_count; + + /** + * The reason for a success or failure of an inlining operation at this + * call site. + */ private String reason; + + /** + * A list of all calls in this compilation scope. + */ private List calls; + + /** + * Number of nodes in the graph at the end of parsing this compilation + * scope. + */ private int endNodes; + + /** + * Number of live nodes in the graph at the end of parsing this compilation + * scope. + */ private int endLiveNodes; + + /** + * Time in seconds since VM startup at which parsing this compilation scope + * ended. + */ private double timeStamp; + + /** + * The inline ID in case the call represented by this instance is inlined, + * 0 otherwise. + */ private long inlineId; - CallSite() { - } + /** + * List of uncommon traps in this compilation scope. + */ + private List traps; + /** + * Default constructor: used to create an instance that represents the top + * scope of a compilation. + */ + CallSite() {} + + /** + * Constructor to create an instance that represents an actual method call. + */ CallSite(int bci, Method m) { this.bci = bci; this.method = m; } + /** + * Add a call site to the compilation scope represented by this instance. + */ void add(CallSite site) { if (getCalls() == null) { - setCalls(new ArrayList()); + calls = new ArrayList<>(); } getCalls().add(site); } + /** + * Return the last of the {@linkplain #getCalls() call sites} in this + * compilation scope. + */ CallSite last() { - return last(-1); + return getCalls().get(getCalls().size() - 1); } - CallSite last(int fromEnd) { - return getCalls().get(getCalls().size() + fromEnd); + /** + * Return the last-but-one of the {@linkplain #getCalls() call sites} in + * this compilation scope. + */ + CallSite lastButOne() { + return getCalls().get(getCalls().size() - 2); } public String toString() { @@ -84,7 +162,7 @@ } public void print(PrintStream stream) { - print(stream, 0); + print(stream, 0, true, false); } void emit(PrintStream stream, int indent) { @@ -92,21 +170,14 @@ stream.print(' '); } } - private static boolean compat = true; - public void print(PrintStream stream, int indent) { + public void print(PrintStream stream, int indent, boolean printInlining, boolean printUncommonTraps) { emit(stream, indent); String m = getMethod().getHolder() + "::" + getMethod().getName(); if (getReason() == null) { stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); - } else { - if (isCompat()) { - stream.print(" @ " + getBci() + " " + m + " " + getReason()); - } else { - stream.print("- @ " + getBci() + " " + m + - " (" + getMethod().getBytes() + " bytes) " + getReason()); - } + stream.print(" @ " + getBci() + " " + m + " " + getReason()); } stream.printf(" (end time: %6.4f", getTimeStamp()); if (getEndNodes() > 0) { @@ -116,13 +187,16 @@ if (getReceiver() != null) { emit(stream, indent + 4); - // stream.println("type profile " + method.holder + " -> " + receiver + " (" + - // receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)"); stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" + (getReceiverCount() * 100 / getCount()) + "%)"); } - if (getCalls() != null) { + if (printInlining && getCalls() != null) { for (CallSite site : getCalls()) { + site.print(stream, indent + 2, printInlining, printUncommonTraps); + } + } + if (printUncommonTraps && getTraps() != null) { + for (UncommonTrap site : getTraps()) { site.print(stream, indent + 2); } } @@ -180,16 +254,15 @@ return calls; } - public void setCalls(List calls) { - this.calls = calls; + public List getTraps() { + return traps; } - public static boolean isCompat() { - return compat; - } - - public static void setCompat(boolean aCompat) { - compat = aCompat; + void add(UncommonTrap e) { + if (traps == null) { + traps = new ArrayList(); + } + traps.add(e); } void setEndNodes(int n) { @@ -216,21 +289,30 @@ return timeStamp; } + /** + * Check whether this call site matches another. Every late inline call + * site has a unique inline ID. If the call site we're looking for has one, + * then use it; otherwise rely on method name and byte code index. + */ private boolean matches(CallSite other) { - // Every late inline call site has a unique inline id. If the - // call site we're looking for has one then use it other rely - // on method name and bci. if (other.inlineId != 0) { return inlineId == other.inlineId; } return method.equals(other.method) && bci == other.bci; } + /** + * Locate a late inline call site: find, in this instance's + * {@linkplain #calls call sites}, the one furthest down the given call + * stack. + * + * Multiple chains of identical call sites with the same method name / bci + * combination are possible, so we have to try them all until we find the + * late inline call site that has a matching inline ID. + * + * @return a matching call site, or {@code null} if none was found. + */ public CallSite findCallSite(ArrayDeque sites) { - // Locate a late inline call site. Multiple chains of - // identical call sites with the same method name/bci are - // possible so we have to try them all until we find the late - // inline call site that has a matching inline id. if (calls == null) { return null; } @@ -253,6 +335,11 @@ return null; } + /** + * Locate a late inline call site in the tree spanned by all this instance's + * {@linkplain #calls call sites}, and return the sequence of call sites + * (scopes) leading to that late inline call site. + */ public ArrayDeque findCallSite2(CallSite site) { if (calls == null) { return null; @@ -260,7 +347,7 @@ for (CallSite c : calls) { if (c.matches(site)) { - ArrayDeque stack = new ArrayDeque(); + ArrayDeque stack = new ArrayDeque<>(); stack.push(c); return stack; } else { diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,22 +27,94 @@ import java.io.PrintStream; import java.util.ArrayList; +/** + * One particular compilation, represented in the compilation log file as a + * {@code task} element. + */ public class Compilation implements LogEvent { + /** + * The compilation ID. + */ private int id; + + /** + * Whether this is a compilation for on-stack replacement (OSR). + */ private boolean osr; + + /** + * The method being compiled. + */ private Method method; + + /** + * The {@linkplain CallSite scope} of this compilation. This is created as + * an empty {@link CallSite} instance, to be filled with data (and + * meaning) later on. + */ private CallSite call = new CallSite(); + + /** + * In case a {@code late_inline} event occurs during the compilation, this + * field holds the information about it. + */ private CallSite lateInlineCall = new CallSite(); - private int osrBci; + + /** + * The bytecode instruction index for on-stack replacement compilations; -1 + * if this is not an OSR compilation. + */ + private int bci; + + /** + * The method under compilation's invocation count. + */ private String icount; + + /** + * The method under compilation's backedge count. + */ private String bcount; + + /** + * Additional information for special compilations (e.g., adapters). + */ private String special; + + /** + * The name of the compiler performing this compilation. + */ + private String compiler; + + /** + * Start time stamp. + */ private double start; + + /** + * End time stamp. + */ private double end; + + /** + * Trip count of the register allocator. + */ private int attempts; + + /** + * The compilation result (a native method). + */ private NMethod nmethod; - private ArrayList phases = new ArrayList(4); + + /** + * The phases through which this compilation goes. + */ + private ArrayList phases = new ArrayList<>(4); + + /** + * In case this compilation fails, the reason for that. + */ private String failureReason; Compilation(int id) { @@ -52,9 +124,17 @@ void reset() { call = new CallSite(); lateInlineCall = new CallSite(); - phases = new ArrayList(4); + phases = new ArrayList<>(4); } + /** + * Get a compilation phase by name, or {@code null}. + * + * @param s the name of the phase to retrieve in this compilation. + * + * @return a compilation phase, or {@code null} if no phase with the given + * name is found. + */ Phase getPhase(String s) { for (Phase p : getPhases()) { if (p.getName().equals(s)) { @@ -72,20 +152,32 @@ return start; } + public void setCompiler(String compiler) { + this.compiler = compiler; + } + + public String getCompiler() { + return compiler; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getId()); sb.append(" "); + sb.append(getCompiler()); + sb.append(" "); sb.append(getMethod()); sb.append(" "); sb.append(getIcount()); sb.append("+"); sb.append(getBcount()); sb.append("\n"); - for (CallSite site : getCall().getCalls()) { - sb.append(site); - sb.append("\n"); + if (getCall() != null && getCall().getCalls() != null) { + for (CallSite site : getCall().getCalls()) { + sb.append(site); + sb.append("\n"); + } } if (getLateInlineCall().getCalls() != null) { sb.append("late inline:\n"); @@ -101,38 +193,50 @@ if (getMethod() == null) { stream.println(getSpecial()); } else { - int bc = isOsr() ? getOsr_bci() : -1; - stream.print(getId() + getMethod().decodeFlags(bc) + getMethod().format(bc)); + int bc = isOsr() ? getBCI() : -1; + stream.print(getId() + getMethod().decodeFlags(bc) + " " + compiler + " " + getMethod().format(bc)); } } - public void print(PrintStream stream) { - print(stream, 0, false); + public void print(PrintStream stream, boolean printID) { + print(stream, 0, printID, true, false); } - public void print(PrintStream stream, boolean printInlining) { - print(stream, 0, printInlining); + public void print(PrintStream stream, boolean printID, boolean printInlining) { + print(stream, 0, printID, printInlining, false); } - public void print(PrintStream stream, int indent, boolean printInlining) { + public void print(PrintStream stream, boolean printID, boolean printInlining, boolean printUncommonTraps) { + print(stream, 0, printID, printInlining, printUncommonTraps); + } + + public void print(PrintStream stream, int indent, boolean printID, boolean printInlining, boolean printUncommonTraps) { if (getMethod() == null) { stream.println(getSpecial()); } else { - int bc = isOsr() ? getOsr_bci() : -1; - stream.print(getId() + getMethod().decodeFlags(bc) + getMethod().format(bc)); + if (printID) { + stream.print(getId()); + } + int bc = isOsr() ? getBCI() : -1; + stream.print(getMethod().decodeFlags(bc) + " " + compiler + " " + getMethod().format(bc)); stream.println(); if (getFailureReason() != null) { - stream.println("COMPILE FAILED " + getFailureReason()); + stream.println("COMPILE SKIPPED: " + getFailureReason() + " (not retryable)"); } if (printInlining && call.getCalls() != null) { for (CallSite site : call.getCalls()) { + site.print(stream, indent + 2, printInlining, printUncommonTraps); + } + } + if (printUncommonTraps && call.getTraps() != null) { + for (UncommonTrap site : call.getTraps()) { site.print(stream, indent + 2); } } if (printInlining && lateInlineCall.getCalls() != null) { stream.println("late inline:"); for (CallSite site : lateInlineCall.getCalls()) { - site.print(stream, indent + 2); + site.print(stream, indent + 2, printInlining, printUncommonTraps); } } } @@ -154,12 +258,12 @@ this.osr = osr; } - public int getOsr_bci() { - return osrBci; + public int getBCI() { + return bci; } - public void setOsr_bci(int osrBci) { - this.osrBci = osrBci; + public void setBCI(int osrBci) { + this.bci = osrBci; } public String getIcount() { @@ -230,9 +334,13 @@ return method; } + /** + * Set the method under compilation. If it is already set, ignore the + * argument to avoid changing the method by post-parse inlining info. + * + * @param method the method under compilation. May be ignored. + */ public void setMethod(Method method) { - // Don't change method if it is already set to avoid changing - // it by post parse inlining info. if (getMethod() == null) { this.method = method; } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,9 @@ * This class is a filter class to deal with malformed XML that used * to be produced by the JVM when generating LogCompilation. In 1.6 * and later releases it shouldn't be required. - * @author never */ +class LogCleanupReader extends Reader { -class LogCleanupReader extends Reader { private Reader reader; private char[] buffer = new char[4096]; @@ -55,32 +54,38 @@ reader = r; } - static final private Matcher pattern = Pattern.compile(".+ compile_id='[0-9]+'.*( compile_id='[0-9]+)").matcher(""); - static final private Matcher pattern2 = Pattern.compile("' (C[12]) compile_id=").matcher(""); - static final private Matcher pattern3 = Pattern.compile("'(destroy_vm)/").matcher(""); + static final private Matcher duplicateCompileID = Pattern.compile(".+ compile_id='[0-9]+'.*( compile_id='[0-9]+)").matcher(""); + static final private Matcher compilerName = Pattern.compile("' (C[12]) compile_id=").matcher(""); + static final private Matcher destroyVM = Pattern.compile("'(destroy_vm)/").matcher(""); + /** + * The log cleanup takes place in this method. If any of the three patterns + * ({@link #duplicateCompileID}, {@link #compilerName}, {@link #destroyVM}) + * match, that indicates a problem in the log. The cleanup is performed by + * correcting the input line and writing it back into the {@link #line} + * buffer. + */ private void fill() throws IOException { rawFill(); if (length != -1) { boolean changed = false; String s = new String(line, 0, length); - String orig = s; - pattern2.reset(s); - if (pattern2.find()) { - s = s.substring(0, pattern2.start(1)) + s.substring(pattern2.end(1) + 1); + compilerName.reset(s); + if (compilerName.find()) { + s = s.substring(0, compilerName.start(1)) + s.substring(compilerName.end(1) + 1); changed = true; } - pattern.reset(s); - if (pattern.lookingAt()) { - s = s.substring(0, pattern.start(1)) + s.substring(pattern.end(1) + 1); + duplicateCompileID.reset(s); + if (duplicateCompileID.lookingAt()) { + s = s.substring(0, duplicateCompileID.start(1)) + s.substring(duplicateCompileID.end(1) + 1); changed = true; } - pattern3.reset(s); - if (pattern3.find()) { - s = s.substring(0, pattern3.start(1)) + s.substring(pattern3.end(1)); + destroyVM.reset(s); + if (destroyVM.find()) { + s = s.substring(0, destroyVM.start(1)) + s.substring(destroyVM.end(1)); changed = true; } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,60 +22,102 @@ * */ -/** - * The main command line driver of a parser for LogCompilation output. - * @author never - */ - package com.sun.hotspot.tools.compiler; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.PrintStream; import java.util.*; + import org.xml.sax.*; import org.xml.sax.helpers.*; -public class LogCompilation extends DefaultHandler implements ErrorHandler, Constants { +/** + * The LogCompilation tool parses log files generated by HotSpot using the + * {@code -XX:+LogCompilation} command line flag, and outputs the data + * collected therein in a nicely formatted way. There are various sorting + * options available, as well as options that select specific compilation + * events (such as inlining decisions) for inclusion in the output. + * + * The tool is also capable of fixing broken compilation logs as sometimes + * generated by Java 1.5 JVMs. + */ +public class LogCompilation extends DefaultHandler implements ErrorHandler { + /** + * Print usage information and terminate with a given exit code. + */ public static void usage(int exitcode) { System.out.println("Usage: LogCompilation [ -v ] [ -c ] [ -s ] [ -e | -n ] file1 ..."); + System.out.println("By default, the tool will print the logged compilations ordered by start time."); System.out.println(" -c: clean up malformed 1.5 xml"); System.out.println(" -i: print inlining decisions"); System.out.println(" -S: print compilation statistics"); - System.out.println(" -s: sort events by start time"); + System.out.println(" -U: print uncommon trap statistics"); + System.out.println(" -t: print with time stamps"); + System.out.println(" -s: sort events by start time (default)"); System.out.println(" -e: sort events by elapsed time"); System.out.println(" -n: sort events by name and start"); + System.out.println(" -C: compare logs (give files to compare on command line)"); + System.out.println(" -d: do not print compilation IDs"); System.exit(exitcode); } + /** + * Process command line arguments, parse log files and trigger desired + * functionality. + */ public static void main(String[] args) throws Exception { - Comparator defaultSort = LogParser.sortByStart; + Comparator sort = LogParser.sortByStart; boolean statistics = false; boolean printInlining = false; boolean cleanup = false; + boolean trapHistory = false; + boolean printTimeStamps = false; + boolean compare = false; + boolean printID = true; int index = 0; while (args.length > index) { - if (args[index].equals("-e")) { - defaultSort = LogParser.sortByElapsed; + String a = args[index]; + if (a.equals("-e")) { + sort = LogParser.sortByElapsed; + index++; + } else if (a.equals("-n")) { + sort = LogParser.sortByNameAndStart; index++; - } else if (args[index].equals("-n")) { - defaultSort = LogParser.sortByNameAndStart; + } else if (a.equals("-s")) { + sort = LogParser.sortByStart; index++; - } else if (args[index].equals("-s")) { - defaultSort = LogParser.sortByStart; + } else if (a.equals("-t")) { + printTimeStamps = true; index++; - } else if (args[index].equals("-c")) { + } else if (a.equals("-c")) { cleanup = true; index++; - } else if (args[index].equals("-S")) { + } else if (a.equals("-S")) { statistics = true; index++; - } else if (args[index].equals("-h")) { + } else if (a.equals("-U")) { + trapHistory = true; + index++; + } else if (a.equals("-h")) { usage(0); - } else if (args[index].equals("-i")) { + } else if (a.equals("-i")) { printInlining = true; index++; + } else if (a.equals("-C")) { + compare = true; + index++; + } else if (a.equals("-d")) { + printID = false; + index++; } else { + if (a.charAt(0) == '-') { + System.out.println("Unknown option '" + a + "', assuming file name."); + } break; } } @@ -84,19 +126,40 @@ usage(1); } + if (compare) { + compareLogs(index, args); + return; + } + while (index < args.length) { - ArrayList events = LogParser.parse(args[index], cleanup); + ArrayList events = null; + try { + events = LogParser.parse(args[index], cleanup); + } catch (FileNotFoundException fnfe) { + System.out.println("File not found: " + args[index]); + System.exit(1); + } + + Collections.sort(events, sort); if (statistics) { printStatistics(events, System.out); + } else if (trapHistory) { + printTrapHistory(events, System.out); } else { - Collections.sort(events, defaultSort); for (LogEvent c : events) { - if (printInlining && c instanceof Compilation) { - Compilation comp = (Compilation)c; - comp.print(System.out, true); + if (c instanceof NMethod) { + // skip these + continue; + } + if (printTimeStamps) { + System.out.print(c.getStart() + ": "); + } + if (c instanceof Compilation) { + Compilation comp = (Compilation) c; + comp.print(System.out, printID, printInlining); } else { - c.print(System.out); + c.print(System.out, printID); } } } @@ -104,17 +167,25 @@ } } + /** + * Print extensive statistics from parsed log files. + */ public static void printStatistics(ArrayList events, PrintStream out) { + // track code cache size long cacheSize = 0; long maxCacheSize = 0; + // track number of nmethods int nmethodsCreated = 0; int nmethodsLive = 0; + // track how many compilations were attempted multiple times + // (indexed by attempts, mapping to number of compilations) int[] attempts = new int[32]; - double regallocTime = 0; int maxattempts = 0; - LinkedHashMap phaseTime = new LinkedHashMap(7); - LinkedHashMap phaseNodes = new LinkedHashMap(7); + // track time spent in compiler phases + LinkedHashMap phaseTime = new LinkedHashMap<>(7); + // track nodes created per phase + LinkedHashMap phaseNodes = new LinkedHashMap<>(7); double elapsed = 0; for (LogEvent e : events) { @@ -137,18 +208,17 @@ v2 = Integer.valueOf(0); } phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes())); - /* Print phase name, elapsed time, nodes at the start of the phase, - nodes created in the phase, live nodes at the start of the phase, - live nodes added in the phase. - */ - out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes()); + // Print phase name, elapsed time, nodes at the start of + // the phase, nodes created in the phase, live nodes at the + // start of the phase, live nodes added in the phase. + out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getAddedLiveNodes()); } } else if (e instanceof MakeNotEntrantEvent) { MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e; NMethod nm = mne.getNMethod(); if (mne.isZombie()) { if (nm == null) { - System.err.println(mne.getId()); + System.err.println("zombie make not entrant event without nmethod: " + mne.getId()); } cacheSize -= nm.getSize(); nmethodsLive--; @@ -161,8 +231,7 @@ maxCacheSize = Math.max(cacheSize, maxCacheSize); } } - out.printf("NMethods: %d created %d live %d bytes (%d peak) in the code cache\n", - nmethodsCreated, nmethodsLive, cacheSize, maxCacheSize); + out.printf("NMethods: %d created %d live %d bytes (%d peak) in the code cache\n", nmethodsCreated, nmethodsLive, cacheSize, maxCacheSize); out.println("Phase times:"); for (String name : phaseTime.keySet()) { Double v = phaseTime.get(name); @@ -178,4 +247,265 @@ } } } + + /** + * Container class for a pair of a method and a bytecode instruction index + * used by a compiler. This is used in + * {@linkplain #compareLogs() comparing logs}. + */ + static class MethodBCIPair { + public MethodBCIPair(Method m, int b, String c) { + method = m; + bci = b; + compiler = c; + } + + Method method; + int bci; + String compiler; + + public boolean equals(Object other) { + if (!(other instanceof MethodBCIPair)) { + return false; + } + MethodBCIPair otherp = (MethodBCIPair)other; + return (otherp.bci == bci && + otherp.method.equals(method) && + otherp.compiler.equals(compiler)); + } + + public int hashCode() { + return method.hashCode() + bci; + } + + public String toString() { + if (bci != -1) { + return method + "@" + bci + " (" + compiler + ")"; + } else { + return method + " (" + compiler + ")"; + } + } + } + + /** + * Compare a number of compilation log files. Each of the logs is parsed, + * and all compilations found therein are written to a sorted file (prefix + * {@code sorted-}. A summary is written to a new file {@code summary.txt}. + * + * @param index the index in the command line arguments at which to start + * looking for files to compare. + * @param args the command line arguments with which {@link LogCompilation} + * was originally invoked. + * + * @throws Exception in case any exceptions are thrown in the called + * methods. + */ + @SuppressWarnings("unchecked") + static void compareLogs(int index, String[] args) throws Exception { + HashMap methods = new HashMap<>(); + ArrayList> logs = new ArrayList<>(); + PrintStream[] outs = new PrintStream[args.length - index]; + PrintStream summary = new PrintStream(new FileOutputStream("summary.txt")); + int o = 0; + // Process all logs given on the command line: collect compilation + // data; in particular, method/bci pairs. + while (index < args.length) { + String basename = new File(args[index]).getName(); + String outname = "sorted-" + basename; + System.out.println("Sorting " + basename + " to " + outname); + outs[o] = new PrintStream(new FileOutputStream(outname)); + o++; + System.out.println("Parsing " + args[index]); + ArrayList events = LogParser.parse(args[index], false); + HashMap compiles = new HashMap<>(); + logs.add(compiles); + for (LogEvent c : events) { + if (c instanceof Compilation) { + Compilation comp = (Compilation) c; + MethodBCIPair key = new MethodBCIPair(comp.getMethod(), comp.getBCI(), + comp.getCompiler()); + MethodBCIPair e = methods.get(key); + if (e == null) { + methods.put(key, key); + } else { + key = e; + } + Object other = compiles.get(key); + if (other == null) { + compiles.put(key, comp); + } else { + if (!(other instanceof List)) { + List l = new LinkedList<>(); + l.add(other); + l.add(comp); + compiles.put(key, l); + } else { + List l = (List) other; + l.add(comp); + } + } + } + } + index++; + } + + // Process the collected method/bci pairs and write the output. + for (MethodBCIPair pair : methods.keySet()) { + summary.print(pair + " "); + int base = -1; + String first = null; + boolean mismatch = false; + boolean different = false; + String[] output = new String[outs.length]; + o = 0; + for (HashMap set : logs) { + Object e = set.get(pair); + String thisone = null; + Compilation lastc = null; + int n; + if (e == null) { + n = 0; + } else if (e instanceof Compilation) { + n = 1; + lastc = (Compilation) e; + } else { + // Compare the last compilation that was done for this method + n = ((List) e).size(); + lastc = (Compilation) ((List) e).get(n - 1); + } + if (lastc != null) { + n = 1; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + lastc.print(ps, false); + ps.close(); + thisone = new String(baos.toByteArray()); + } + if (base == -1) { + base = n; + } else if (base != n) { + mismatch = true; + } + output[o++] = thisone; + if (thisone != null) { + if (first == null) { + first = thisone; + } else { + if (!first.equals(thisone)) { + different = true; + } + } + } + if (different) { + summary.print(n + "d "); + } else { + summary.print(n + " "); + } + } + if (mismatch) { + summary.print("mismatch"); + } + summary.println(); + if (different) { + for (int i = 0; i < outs.length; i++) { + if (output[i] != null) { + outs[i].println(output[i]); + } + } + } + } + for (int i = 0; i < outs.length; i++) { + outs[i].close(); + } + if (summary != System.out) { + summary.close(); + } + } + + /** + * Print the history of uncommon trap events. + */ + public static void printTrapHistory(ArrayList events, PrintStream out) { + // map method names to a list of log events + LinkedHashMap> traps = new LinkedHashMap<>(); + // map compilation IDs to compilations + HashMap comps = new HashMap<>(); + + // First, iterate over all logged events, collecting data about + // uncommon trap events. + for (LogEvent e : events) { + if (e instanceof NMethod) { + // skip these + continue; + } + if (e instanceof Compilation) { + Compilation c = (Compilation) e; + String name = c.getMethod().getFullName(); + ArrayList elist = traps.get(name); + if (elist != null && comps.get(c.getId()) == null) { + comps.put(c.getId(), c); + // If there were previous events for the method + // then keep track of later compiles too. + elist.add(c); + } + continue; + } + if (e instanceof BasicLogEvent) { + BasicLogEvent ble = (BasicLogEvent) e; + Compilation c = ble.getCompilation(); + if (c == null) { + if (!(ble instanceof NMethod)) { + throw new InternalError("only nmethods should have a null compilation; here's a " + ble.getClass()); + } + continue; + } + String name = c.getMethod().getFullName(); + ArrayList elist = traps.get(name); + if (elist == null) { + elist = new ArrayList(); + traps.put(name, elist); + } + int bleId = Integer.parseInt(ble.getId()); + if (comps.get(bleId) == null) { + comps.put(bleId, c); + // Add the associated compile to the list. It + // will likely go at the end but we need to search + // backwards for the proper insertion point. + double start = c.getStart(); + int ipoint = 0; + while (ipoint < elist.size() && elist.get(ipoint).getStart() < start) { + ipoint++; + } + if (ipoint == elist.size()) { + elist.add(c); + } else { + elist.add(ipoint, c); + } + } + elist.add(ble); + } + } + + // Second, iterate over collected traps and output information. + for (String c: traps.keySet()) { + ArrayList elist = traps.get(c); + String name = ((Compilation) elist.get(0)).getMethod().getFullName(); + System.out.println(name); + double start = 0; + for (LogEvent e: elist) { + if (start > e.getStart() && e.getStart() != 0) { + throw new InternalError("wrong sorting order for traps"); + } + start = e.getStart(); + out.print(e.getStart() + ": "); + if (e instanceof Compilation) { + ((Compilation) e).print(out, true, true, true); + } else { + e.print(out, true); + } + } + out.println(); + } + } + } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,31 @@ package com.sun.hotspot.tools.compiler; import java.io.PrintStream; -import java.util.*; +/** + * The interface of an event from a HotSpot compilation log. Events can have a + * duration, e.g., a compiler {@link Phase} is an event, and so is an entire + * {@link Compilation}. + */ public interface LogEvent { + + /** + * The event's start time. + */ public double getStart(); + /** + * The event's duration in milliseconds. + */ public double getElapsedTime(); + /** + * The compilation during which this event was signalled. + */ public Compilation getCompilation(); - public void print(PrintStream stream); + /** + * Print the event to the given stream. + */ + public void print(PrintStream stream, boolean printID); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Wed Jul 05 20:43:22 2017 +0200 @@ -33,30 +33,269 @@ import java.io.Reader; import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; +import java.util.Deque; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.Stack; +import java.util.regex.Pattern; + import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; + import org.xml.sax.Attributes; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; +import org.xml.sax.Locator; import org.xml.sax.helpers.DefaultHandler; -public class LogParser extends DefaultHandler implements ErrorHandler, Constants { +/** + * A SAX parser for HotSpot compilation logs. The bulk of the parsing and event + * maintenance work is done in the {@link #startElement(String,String,String,Attributes)} + * and {@link #endElement(String,String,String)} methods. + */ +public class LogParser extends DefaultHandler implements ErrorHandler { + + static final Pattern spacePattern = Pattern.compile(" "); - static final HashMap typeMap; + /** + * Map internal array type descriptors to Java names. + */ + static final HashMap type2printableMap; + + /** + * Map Java primitive type names to internal type descriptors. + */ + static final HashMap type2vmtypeMap; + static { - typeMap = new HashMap(); - typeMap.put("[I", "int[]"); - typeMap.put("[C", "char[]"); - typeMap.put("[Z", "boolean[]"); - typeMap.put("[L", "Object[]"); - typeMap.put("[B", "byte[]"); + type2printableMap = new HashMap<>(); + type2printableMap.put("[I", "int[]"); + type2printableMap.put("[C", "char[]"); + type2printableMap.put("[Z", "boolean[]"); + type2printableMap.put("[L", "Object[]"); + type2printableMap.put("[B", "byte[]"); + + type2vmtypeMap = new HashMap<>(); + type2vmtypeMap.put("void", "V"); + type2vmtypeMap.put("boolean", "Z"); + type2vmtypeMap.put("byte", "B"); + type2vmtypeMap.put("char", "C"); + type2vmtypeMap.put("short", "S"); + type2vmtypeMap.put("int", "I"); + type2vmtypeMap.put("long", "J"); + type2vmtypeMap.put("float", "F"); + type2vmtypeMap.put("double", "D"); } + static String[] bytecodes = new String[] { + "nop", + "aconst_null", + "iconst_m1", + "iconst_0", + "iconst_1", + "iconst_2", + "iconst_3", + "iconst_4", + "iconst_5", + "lconst_0", + "lconst_1", + "fconst_0", + "fconst_1", + "fconst_2", + "dconst_0", + "dconst_1", + "bipush", + "sipush", + "ldc", + "ldc_w", + "ldc2_w", + "iload", + "lload", + "fload", + "dload", + "aload", + "iload_0", + "iload_1", + "iload_2", + "iload_3", + "lload_0", + "lload_1", + "lload_2", + "lload_3", + "fload_0", + "fload_1", + "fload_2", + "fload_3", + "dload_0", + "dload_1", + "dload_2", + "dload_3", + "aload_0", + "aload_1", + "aload_2", + "aload_3", + "iaload", + "laload", + "faload", + "daload", + "aaload", + "baload", + "caload", + "saload", + "istore", + "lstore", + "fstore", + "dstore", + "astore", + "istore_0", + "istore_1", + "istore_2", + "istore_3", + "lstore_0", + "lstore_1", + "lstore_2", + "lstore_3", + "fstore_0", + "fstore_1", + "fstore_2", + "fstore_3", + "dstore_0", + "dstore_1", + "dstore_2", + "dstore_3", + "astore_0", + "astore_1", + "astore_2", + "astore_3", + "iastore", + "lastore", + "fastore", + "dastore", + "aastore", + "bastore", + "castore", + "sastore", + "pop", + "pop2", + "dup", + "dup_x1", + "dup_x2", + "dup2", + "dup2_x1", + "dup2_x2", + "swap", + "iadd", + "ladd", + "fadd", + "dadd", + "isub", + "lsub", + "fsub", + "dsub", + "imul", + "lmul", + "fmul", + "dmul", + "idiv", + "ldiv", + "fdiv", + "ddiv", + "irem", + "lrem", + "frem", + "drem", + "ineg", + "lneg", + "fneg", + "dneg", + "ishl", + "lshl", + "ishr", + "lshr", + "iushr", + "lushr", + "iand", + "land", + "ior", + "lor", + "ixor", + "lxor", + "iinc", + "i2l", + "i2f", + "i2d", + "l2i", + "l2f", + "l2d", + "f2i", + "f2l", + "f2d", + "d2i", + "d2l", + "d2f", + "i2b", + "i2c", + "i2s", + "lcmp", + "fcmpl", + "fcmpg", + "dcmpl", + "dcmpg", + "ifeq", + "ifne", + "iflt", + "ifge", + "ifgt", + "ifle", + "if_icmpeq", + "if_icmpne", + "if_icmplt", + "if_icmpge", + "if_icmpgt", + "if_icmple", + "if_acmpeq", + "if_acmpne", + "goto", + "jsr", + "ret", + "tableswitch", + "lookupswitch", + "ireturn", + "lreturn", + "freturn", + "dreturn", + "areturn", + "return", + "getstatic", + "putstatic", + "getfield", + "putfield", + "invokevirtual", + "invokespecial", + "invokestatic", + "invokeinterface", + "invokedynamic", + "new", + "newarray", + "anewarray", + "arraylength", + "athrow", + "checkcast", + "instanceof", + "monitorenter", + "monitorexit", + "wide", + "multianewarray", + "ifnull", + "ifnonnull", + "goto_w", + "jsr_w", + "breakpoint" + }; + + /** + * Sort log events by start time. + */ static Comparator sortByStart = new Comparator() { public int compare(LogEvent a, LogEvent b) { @@ -80,25 +319,29 @@ return 7; } }; + + /** + * Sort log events first by the name of the compiled method, then by start + * time. In case one of the events has no associated compilation (or the + * associated compilation has no method name), the event with a compilation + * and/or name is considered the larger one. + */ static Comparator sortByNameAndStart = new Comparator() { public int compare(LogEvent a, LogEvent b) { Compilation c1 = a.getCompilation(); Compilation c2 = b.getCompilation(); - if (c1 != null && c2 != null) { + if (c1 != null && c1.getMethod() != null && c2 != null && c2.getMethod() != null) { int result = c1.getMethod().toString().compareTo(c2.getMethod().toString()); if (result != 0) { return result; } - } - double difference = (a.getStart() - b.getStart()); - if (difference < 0) { + } else if ((c1 == null || c1.getMethod() == null) && c2 != null && c2.getMethod() != null) { return -1; - } - if (difference > 0) { + } else if ((c2 == null || c2.getMethod() == null) && c1 != null && c1.getMethod() != null) { return 1; } - return 0; + return Double.compare(a.getStart(), b.getStart()); } public boolean equals(Object other) { @@ -110,6 +353,10 @@ return 7; } }; + + /** + * Sort log events by duration. + */ static Comparator sortByElapsed = new Comparator() { public int compare(LogEvent a, LogEvent b) { @@ -134,6 +381,10 @@ } }; + /** + * Shrink-wrapped representation of a JVMState (tailored to meet this + * tool's needs). It only records a method and bytecode instruction index. + */ class Jvms { Jvms(Method method, int bci) { this.method = method; @@ -146,12 +397,33 @@ } } + /** + * Representation of a lock elimination. Locks, corresponding to + * synchronized blocks and method calls, may be eliminated if the object in + * question is guaranteed to be used thread-locally. + */ class LockElimination extends BasicLogEvent { - ArrayList jvms = new ArrayList(1); + /** + * Track all locations from which this lock was eliminated. + */ + ArrayList jvms = new ArrayList<>(1); + + /** + * The kind of lock (coarsened, nested, non-escaping, unknown). + */ final String kind; + + /** + * The lock class (unlock, lock, unknown). + */ final String classId; + + /** + * The precise type of lock. + */ final String tagName; + LockElimination(String tagName, double start, String id, String kind, String classId) { super(start, id); this.kind = kind; @@ -160,8 +432,11 @@ } @Override - public void print(PrintStream stream) { - stream.printf("%s %s %s %s %.3f ", getId(), tagName, kind, classId, getStart()); + public void print(PrintStream stream, boolean printID) { + if (printID) { + stream.printf("%s ", getId()); + } + stream.printf("%s %s %s %.3f ", tagName, kind, classId, getStart()); stream.print(jvms.toString()); stream.print("\n"); } @@ -172,25 +447,154 @@ } - private ArrayList events = new ArrayList(); + /** + * A list of log events. This is populated with the events found in the + * compilation log file during parsing. + */ + private ArrayList events = new ArrayList<>(); + + /** + * Map compilation log IDs to type names. + */ + private HashMap types = new HashMap<>(); - private HashMap types = new HashMap(); - private HashMap methods = new HashMap(); - private LinkedHashMap nmethods = new LinkedHashMap(); - private HashMap compiles = new HashMap(); + /** + * Map compilation log IDs to methods. + */ + private HashMap methods = new HashMap<>(); + + /** + * Map compilation IDs ({@see #makeId()}) to newly created nmethods. + */ + private LinkedHashMap nmethods = new LinkedHashMap<>(); + + /** + * Map compilation task IDs {@see #makeId()}) to {@link Compilation} + * objects. + */ + private HashMap compiles = new HashMap<>(); + + /** + * Track compilation failure reasons. + */ private String failureReason; - private int bci; - private Stack scopes = new Stack(); + + /** + * The current bytecode instruction index. + */ + private int current_bci; + + /** + * The current bytecode instruction. + */ + private int current_bytecode; + + /** + * A sequence of {@link CallSite}s representing a call stack. A scope + * typically holds several {@link CallSite}s that represent calls + * originating from that scope. + * + * New scopes are typically pushed when parse log events are encountered + * ({@see #startElement()}) and popped when parsing of a given Java method + * is done ({@see #endElement()}). Parsing events can be nested. Several + * other events add information to scopes ({@see #startElement()}). + */ + private Deque scopes = new ArrayDeque<>(); + + /** + * The current compilation. + */ private Compilation compile; + + /** + * The {@linkplain CallSite compilation scope} currently in focus. + */ private CallSite site; + + /** + * The {@linkplain CallSite method handle call site} currently under + * observation. + */ private CallSite methodHandleSite; - private Stack phaseStack = new Stack(); + + /** + * Keep track of potentially nested compiler {@linkplain Phase phases}. + */ + private Deque phaseStack = new ArrayDeque<>(); + + /** + * The {@linkplain LockElimination lock elimination event} currently being + * processed. + */ private LockElimination currentLockElimination; + + /** + * The {@linkplain UncommonTrapEvent uncommon trap event} currently being + * processed. + */ private UncommonTrapEvent currentTrap; - private Stack lateInlineScope; + + /** + * During the processing of a late inline event, this stack holds the + * {@link CallSite}s that represent the inlining event's call stack. + */ + private Deque lateInlineScope; + + /** + * Denote whether a late inlining event is currently being processed. + */ private boolean lateInlining; + /** + * A document locator to provide better error messages: this allows the + * tool to display in which line of the log file the problem occurred. + */ + private Locator locator; + /** + * Callback for the SAX framework to set the document locator. + */ + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + /** + * Report an internal error explicitly raised, i.e., not derived from an + * exception. + * + * @param msg The error message to report. + */ + private void reportInternalError(String msg) { + reportInternalError(msg, null); + } + + /** + * Report an internal error derived from an exception. + * + * @param msg The beginning of the error message to report. The message + * from the exception will be appended to this. + * @param e The exception that led to the internal error. + */ + private void reportInternalError(String msg, Exception e) { + if (locator != null) { + msg += " at " + locator.getLineNumber() + ":" + locator.getColumnNumber(); + if (e != null) { + msg += " - " + e.getMessage(); + } + } + if (e != null) { + throw new Error(msg, e); + } else { + throw new Error(msg); + } + } + + /** + * Parse a long hexadecimal address into a {@code long} value. As Java only + * supports positive {@code long} values, extra error handling and parsing + * logic is provided. + */ long parseLong(String l) { try { return Long.decode(l).longValue(); @@ -207,16 +611,29 @@ System.out.println(v1); System.out.println(v2); System.out.println(Long.toHexString(v1 + v2)); - throw new InternalError("bad conversion"); + reportInternalError("bad conversion"); } return v1 + v2; } } + /** + * Entry point for log file parsing with a file name. + * + * @param file The name of the log file to parse. + * @param cleanup Whether to perform bad XML cleanup during parsing (this + * is relevant for some log files generated by the 1.5 JVM). + * @return a list of {@link LogEvent} instances describing the events found + * in the log file. + */ public static ArrayList parse(String file, boolean cleanup) throws Exception { return parse(new FileReader(file), cleanup); } + /** + * Entry point for log file parsing with a file reader. + * {@see #parse(String,boolean)} + */ public static ArrayList parse(Reader reader, boolean cleanup) throws Exception { // Create the XML input factory SAXParserFactory factory = SAXParserFactory.newInstance(); @@ -238,31 +655,58 @@ // Carry on with what we've got... } - // Associate compilations with their NMethods - for (NMethod nm : log.nmethods.values()) { - Compilation c = log.compiles.get(nm.getId()); - nm.setCompilation(c); - // Native wrappers for methods don't have a compilation - if (c != null) { - c.setNMethod(nm); + // Associate compilations with their NMethods and other kinds of events + for (LogEvent e : log.events) { + if (e instanceof BasicLogEvent) { + BasicLogEvent ble = (BasicLogEvent) e; + Compilation c = log.compiles.get(ble.getId()); + if (c == null) { + if (!(ble instanceof NMethod)) { + throw new InternalError("only nmethods should have a null compilation, here's a " + ble.getClass()); + } + continue; + } + ble.setCompilation(c); + if (ble instanceof NMethod) { + c.setNMethod((NMethod) ble); + } } } - // Initially we want the LogEvent log sorted by timestamp - Collections.sort(log.events, sortByStart); - return log.events; } + /** + * Retrieve a given attribute's value from a collection of XML tag + * attributes. Report an error if the requested attribute is not found. + * + * @param attr A collection of XML tag attributes. + * @param name The name of the attribute the value of which is to be found. + * @return The value of the requested attribute, or {@code null} if it was + * not found. + */ String search(Attributes attr, String name) { String result = attr.getValue(name); if (result != null) { return result; } else { - throw new InternalError("can't find " + name); + reportInternalError("can't find " + name); + return null; } } + /** + * Retrieve a given attribute's value from a collection of XML tag + * attributes. Return a default value if the requested attribute is not + * found. + * + * @param attr A collection of XML tag attributes. + * @param name The name of the attribute the value of which is to be found. + * @param defaultValue The default value to return if the attribute is not + * found. + * @return The value of the requested attribute, or the default value if it + * was not found. + */ String search(Attributes attr, String name, String defaultValue) { String result = attr.getValue(name); if (result != null) { @@ -270,33 +714,70 @@ } return defaultValue; } - int indent = 0; + /** + * Map a type ID from the compilation log to an actual type name. In case + * the type represents an internal array type descriptor, return a + * Java-level name. If the type ID cannot be mapped to a name, raise an + * error. + */ String type(String id) { String result = types.get(id); if (result == null) { - throw new InternalError(id); + reportInternalError(id); } - String remapped = typeMap.get(result); + String remapped = type2printableMap.get(result); if (remapped != null) { return remapped; } return result; } + /** + * Register a mapping from log file type ID to type name. + */ void type(String id, String name) { assert type(id) == null; types.put(id, name); } + /** + * Map a log file type ID to an internal type declarator. + */ + String sigtype(String id) { + String result = types.get(id); + String remapped = type2vmtypeMap.get(result); + if (remapped != null) { + return remapped; + } + if (result == null) { + reportInternalError(id); + } + if (result.charAt(0) == '[') { + return result; + } + return "L" + result + ";"; + } + + /** + * Retrieve a method based on the log file ID it was registered under. + * Raise an error if the ID does not map to a method. + */ Method method(String id) { Method result = methods.get(id); if (result == null) { - throw new InternalError(id); + reportInternalError(id); } return result; } + /** + * From a compilation ID and kind, assemble a compilation ID for inclusion + * in the output. + * + * @param atts A collection of XML attributes from which the required + * attributes are retrieved. + */ public String makeId(Attributes atts) { String id = atts.getValue("compile_id"); String kind = atts.getValue("kind"); @@ -306,11 +787,60 @@ return id; } + /** + * Process the start of a compilation log XML element.
    + *
  • phase: record the beginning of a compilation phase, pushing + * it on the {@linkplain #phaseStack phase stack} and collecting + * information about the compiler graph.
  • + *
  • phase_done: record the end of a compilation phase, popping it + * off the {@linkplain #phaseStack phase stack} and collecting information + * about the compiler graph (number of nodes and live nodes).
  • + *
  • task: register the start of a new compilation.
  • + *
  • type: register a type.
  • + *
  • bc: note the current bytecode index and instruction name, + * updating {@link #current_bci} and {@link #current_bytecode}.
  • + *
  • klass: register a type (class).
  • + *
  • method: register a Java method.
  • + *
  • call: process a call, populating {@link #site} with the + * appropriate data.
  • + *
  • regalloc: record the register allocator's trip count in the + * {@linkplain #compile current compilation}.
  • + *
  • inline_fail: record the reason for a failed inline + * operation.
  • + *
  • inline_success: record a successful inlining operation, + * noting the success reason in the {@linkplain #site call site}.
  • + *
  • failure: note a compilation failure, storing the reason + * description in {@link #failureReason}.
  • + *
  • task_done: register the end of a compilation, recording time + * stamp and success information.
  • + *
  • make_not_entrant: deal with making a native method + * non-callable (e.g., during an OSR compilation, if there are still + * activations) or a zombie (when the method can be deleted).
  • + *
  • uncommon_trap: process an uncommon trap, setting the + * {@link #currentTrap} field.
  • + *
  • eliminate_lock: record the start of a lock elimination, + * setting the {@link #currentLockElimination} event.
  • + *
  • late_inline: start processing a late inline decision: + * initialize the {@linkplain #lateInlineScope inline scope stack}, create + * an {@linkplain #site initial scope} with a bogus bytecode index and the + * right inline ID, and push the scope with the inline ID attached. Note + * that most of late inlining processing happens in + * {@link #endElement()}.
  • + *
  • jvms: record a {@linkplain Jvms JVMState}. Depending on the + * context in which this event is encountered, this can mean adding + * information to the currently being processed trap, lock elimination, or + * inlining operation.
  • + *
  • inline_id: set the inline ID in the + * {@linkplain #site current call site}.
  • + *
  • nmethod: record the creation of a new {@link NMethod} and + * store it in the {@link #nmethods} map.
  • + *
  • parse: begin parsing a Java method's bytecode and + * transforming it into an initial compiler IR graph.
  • + *
  • parse_done: finish parsing a Java method's bytecode.
  • + *
+ */ @Override - public void startElement(String uri, - String localName, - String qname, - Attributes atts) { + public void startElement(String uri, String localName, String qname, Attributes atts) { if (qname.equals("phase")) { Phase p = new Phase(search(atts, "name"), Double.parseDouble(search(atts, "stamp")), @@ -322,45 +852,62 @@ String phaseName = search(atts, "name", null); if (phaseName != null && !p.getId().equals(phaseName)) { System.out.println("phase: " + p.getId()); - throw new InternalError("phase name mismatch"); + reportInternalError("phase name mismatch"); } p.setEnd(Double.parseDouble(search(atts, "stamp"))); p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); p.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0"))); compile.getPhases().add(p); } else if (qname.equals("task")) { + String id = makeId(atts); + + // Create the new Compilation instance and populate it with readily + // available data. compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1"))); compile.setStart(Double.parseDouble(search(atts, "stamp"))); compile.setICount(search(atts, "count", "0")); compile.setBCount(search(atts, "backedge_count", "0")); - - String method = atts.getValue("method"); - int space = method.indexOf(' '); - method = method.substring(0, space) + "::" + - method.substring(space + 1, method.indexOf(' ', space + 1) + 1); + compile.setBCI(Integer.parseInt(search(atts, "osr_bci", "-1"))); String compiler = atts.getValue("compiler"); if (compiler == null) { compiler = ""; } + compile.setCompiler(compiler); + + // Extract the name of the compiled method. + String[] parts = spacePattern.split(atts.getValue("method")); + String methodName = parts[0] + "::" + parts[1]; + + // Continue collecting compilation meta-data. String kind = atts.getValue("compile_kind"); if (kind == null) { kind = "normal"; } if (kind.equals("osr")) { compile.setOsr(true); - compile.setOsr_bci(Integer.parseInt(search(atts, "osr_bci"))); } else if (kind.equals("c2i")) { - compile.setSpecial("--- adapter " + method); + compile.setSpecial("--- adapter " + methodName); } else { - compile.setSpecial(compile.getId() + " " + method + " (0 bytes)"); + compile.setSpecial(compile.getId() + " " + methodName + " (0 bytes)"); } + + // Build a dummy method to stuff in the Compilation at the + // beginning. + Method m = new Method(); + m.setHolder(parts[0]); + m.setName(parts[1]); + m.setSignature(parts[2]); + m.setFlags("0"); + m.setBytes("unknown"); + compile.setMethod(m); events.add(compile); - compiles.put(makeId(atts), compile); + compiles.put(id, compile); site = compile.getCall(); } else if (qname.equals("type")) { type(search(atts, "id"), search(atts, "name")); } else if (qname.equals("bc")) { - bci = Integer.parseInt(search(atts, "bci")); + current_bci = Integer.parseInt(search(atts, "bci")); + current_bytecode = Integer.parseInt(search(atts, "code")); } else if (qname.equals("klass")) { type(search(atts, "id"), search(atts, "name")); } else if (qname.equals("method")) { @@ -369,7 +916,19 @@ m.setHolder(type(search(atts, "holder"))); m.setName(search(atts, "name")); m.setReturnType(type(search(atts, "return"))); - m.setArguments(search(atts, "arguments", "void")); + String arguments = atts.getValue("arguments");; + if (arguments == null) { + m.setSignature("()" + sigtype(atts.getValue("return"))); + } else { + String[] args = spacePattern.split(arguments); + StringBuilder sb = new StringBuilder("("); + for (int i = 0; i < args.length; i++) { + sb.append(sigtype(args[i])); + } + sb.append(")"); + sb.append(sigtype(atts.getValue("return"))); + m.setSignature(sb.toString()); + } if (search(atts, "unloaded", "0").equals("0")) { m.setBytes(search(atts, "bytes")); @@ -385,15 +944,17 @@ if (lateInlining && scopes.size() == 0) { // re-attempting already seen call site (late inlining for MH invokes) if (m != site.getMethod()) { - if (bci != site.getBci()) { - System.out.println(m + " bci: " + bci); - System.out.println(site.getMethod() + " bci: " + site.getBci()); - throw new InternalError("bci mismatch after late inlining"); + if (current_bci != site.getBci()) { + System.err.println(m + " bci: " + current_bci); + System.err.println(site.getMethod() + " bci: " + site.getBci()); + reportInternalError("bci mismatch after late inlining"); } site.setMethod(m); } } else { - site = new CallSite(bci, m); + // We're dealing with a new call site; the called method is + // likely to be parsed next. + site = new CallSite(current_bci, m); } site.setCount(Integer.parseInt(search(atts, "count", "0"))); String receiver = atts.getValue("receiver"); @@ -403,7 +964,8 @@ } int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0")); if (lateInlining && scopes.size() == 0) { - // The call was added before this round of late inlining + // The call was already added before this round of late + // inlining. Ignore. } else if (methodHandle == 0) { scopes.peek().add(site); } else { @@ -421,18 +983,16 @@ methodHandleSite = null; } if (lateInlining && scopes.size() == 0) { - site.setReason(search(atts, "reason")); + site.setReason("fail: " + search(atts, "reason")); lateInlining = false; } else { - scopes.peek().last().setReason(search(atts, "reason")); + scopes.peek().last().setReason("fail: " + search(atts, "reason")); } } else if (qname.equals("inline_success")) { if (methodHandleSite != null) { - throw new InternalError("method handle site should have been replaced"); + reportInternalError("method handle site should have been replaced"); } - if (lateInlining && scopes.size() == 0) { - site.setReason(null); - } + site.setReason("succeed: " + search(atts, "reason")); } else if (qname.equals("failure")) { failureReason = search(atts, "reason"); } else if (qname.equals("task_done")) { @@ -444,7 +1004,7 @@ } else if (qname.equals("make_not_entrant")) { String id = makeId(atts); NMethod nm = nmethods.get(id); - if (nm == null) throw new InternalError(); + if (nm == null) reportInternalError("nm == null"); LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id, atts.getValue("zombie") != null, nm); events.add(e); @@ -459,8 +1019,22 @@ Integer.parseInt(search(atts, "count", "0"))); events.add(currentTrap); } else { - // uncommon trap inserted during parsing. - // ignore for now + if (atts.getValue("method") != null) { + // These are messages from ciTypeFlow that don't + // actually correspond to generated code. + return; + } + try { + if (scopes.size() == 0) { + reportInternalError("scope underflow"); + } + scopes.peek().add(new UncommonTrap(Integer.parseInt(search(atts, "bci")), + search(atts, "reason"), + search(atts, "action"), + bytecodes[current_bytecode])); + } catch (Error e) { + e.printStackTrace(); + } } } else if (qname.startsWith("eliminate_lock")) { String id = atts.getValue("compile_id"); @@ -474,24 +1048,27 @@ } else if (qname.equals("late_inline")) { long inlineId = 0; try { - Long.parseLong(search(atts, "inline_id")); + inlineId = Long.parseLong(search(atts, "inline_id")); } catch (InternalError ex) { // Log files from older hotspots may lack inline_id, // and zero is an acceptable substitute that allows processing to continue. } - lateInlineScope = new Stack(); - site = new CallSite(-999, method(search(atts, "method"))); + lateInlineScope = new ArrayDeque<>(); + Method m = method(search(atts, "method")); + site = new CallSite(-999, m); site.setInlineId(inlineId); lateInlineScope.push(site); } else if (qname.equals("jvms")) { // if (currentTrap != null) { - currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); + String[] parts = spacePattern.split(atts.getValue("method")); + currentTrap.addMethodAndBCI(parts[0].replace('/', '.') + '.' + parts[1] + parts[2], Integer.parseInt(atts.getValue("bci"))); } else if (currentLockElimination != null) { currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci"))); } else if (lateInlineScope != null) { - bci = Integer.parseInt(search(atts, "bci")); - site = new CallSite(bci, method(search(atts, "method"))); + current_bci = Integer.parseInt(search(atts, "bci")); + Method m = method(search(atts, "method")); + site = new CallSite(current_bci, m); lateInlineScope.push(site); } else { // Ignore , @@ -499,7 +1076,7 @@ } } else if (qname.equals("inline_id")) { if (methodHandleSite != null) { - throw new InternalError("method handle site should have been replaced"); + reportInternalError("method handle site should have been replaced"); } long id = Long.parseLong(search(atts, "id")); site.setInlineId(id); @@ -513,33 +1090,53 @@ events.add(nm); } else if (qname.equals("parse")) { if (failureReason != null && scopes.size() == 0 && !lateInlining) { + // A compilation just failed, and we're back at a top + // compilation scope. failureReason = null; compile.reset(); site = compile.getCall(); } + // Error checking. if (methodHandleSite != null) { - throw new InternalError("method handle site should have been replaced"); + reportInternalError("method handle site should have been replaced"); } - Method m = method(search(atts, "method")); + Method m = method(search(atts, "method")); // this is the method being parsed if (lateInlining && scopes.size() == 0) { if (site.getMethod() != m) { - System.out.println(site.getMethod()); - System.out.println(m); - throw new InternalError("Unexpected method mismatch during late inlining"); + reportInternalError("Unexpected method mismatch during late inlining (method at call site: " + + site.getMethod() + ", method being parsed: " + m + ")"); } } + if (scopes.size() == 0 && !lateInlining) { + // The method being parsed is actually the method being + // compiled; i.e., we're dealing with a compilation top scope, + // which we must consequently push to the scopes stack. compile.setMethod(m); scopes.push(site); } else { + // The method being parsed is *not* the current compilation's + // top scope; i.e., we're dealing with an actual call site + // in the top scope or somewhere further down a call stack. if (site.getMethod() == m) { + // We're dealing with monomorphic inlining that didn't have + // to be narrowed down, because the receiver was known + // beforehand. scopes.push(site); - } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().last(-2).getMethod()) { - scopes.push(scopes.peek().last(-2)); + } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().lastButOne().getMethod()) { + // We're dealing with an at least bimorphic call site, and + // the compiler has now decided to parse the last-but-one + // method. The last one may already have been parsed for + // inlining. + scopes.push(scopes.peek().lastButOne()); } else { - // C1 prints multiple method tags during inlining when it narrows method being inlinied. - // Example: + // The method has been narrowed down to the one we're now + // going to parse, which is inlined here. It's monomorphic + // inlining, but was not immediately clear as such. + // + // C1 prints multiple method tags during inlining when it + // narrows the method being inlined. Example: // ... // // @@ -552,100 +1149,132 @@ } } } else if (qname.equals("parse_done")) { - CallSite call = scopes.pop(); + // Attach collected information about IR nodes to the current + // parsing scope before it's popped off the stack in endElement() + // (see where the parse tag is handled). + CallSite call = scopes.peek(); call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0"))); call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); - scopes.push(call); } } + /** + * Process the end of a compilation log XML element.
    + *
  • parse: finish transforming a Java method's bytecode + * instructions to an initial compiler IR graph.
  • + *
  • uncommon_trap: record the end of processing an uncommon trap, + * resetting {@link #currentTrap}.
  • + *
  • eliminate_lock: record the end of a lock elimination, + * resetting {@link #currentLockElimination}.
  • + *
  • late_inline: the closing tag for late_inline does not denote + * the end of a late inlining operation, but the end of the descriptive log + * data given at its beginning. That is, we're now in the position to + * assemble details about the inlining chain (bytecode instruction index in + * caller, called method). The {@link #lateInlining} flag is set to + * {@code true} here. (It will be reset when parsing the inlined methods is + * done; this happens for the successful case in this method as well, when + * {@code parse} elements are processed; and for inlining failures, in + * {@link #startElement()}, when {@code inline_fail} elements are + * processed.)
  • + *
  • task: perform cleanup at the end of a compilation. Note that + * the explicit {@code task_done} event is handled in + * {@link #startElement()}.
  • + *
+ */ @Override - public void endElement(String uri, - String localName, - String qname) { - if (qname.equals("parse")) { - indent -= 2; - scopes.pop(); - if (scopes.size() == 0) { - lateInlining = false; - } - } else if (qname.equals("uncommon_trap")) { - currentTrap = null; - } else if (qname.startsWith("eliminate_lock")) { - currentLockElimination = null; - } else if (qname.equals("late_inline")) { - // Populate late inlining info. - if (scopes.size() != 0) { - throw new InternalError("scopes should be empty for late inline"); - } - // late inline scopes are specified in reverse order: - // compiled method should be on top of stack. - CallSite caller = lateInlineScope.pop(); - Method m = compile.getMethod(); - if (m != caller.getMethod()) { - System.err.println(m); - System.err.println(caller.getMethod() + " bci: " + bci); - throw new InternalError("call site and late_inline info don't match"); - } + public void endElement(String uri, String localName, String qname) { + try { + if (qname.equals("parse")) { + // Finish dealing with the current call scope. If no more are + // left, no late inlining can be going on. + scopes.pop(); + if (scopes.size() == 0) { + lateInlining = false; + } + } else if (qname.equals("uncommon_trap")) { + currentTrap = null; + } else if (qname.startsWith("eliminate_lock")) { + currentLockElimination = null; + } else if (qname.equals("late_inline")) { + // Populate late inlining info. + if (scopes.size() != 0) { + reportInternalError("scopes should be empty for late inline"); + } + // late inline scopes are specified in reverse order: + // compiled method should be on top of stack. + CallSite caller = lateInlineScope.pop(); + Method m = compile.getMethod(); + if (!m.equals(caller.getMethod())) { + reportInternalError(String.format("call site and late_inline info don't match:\n method %s\n caller method %s, bci %d", m, caller.getMethod(), current_bci)); + } - // late_inline contains caller+bci info, convert it - // to bci+callee info used by LogCompilation. - CallSite lateInlineSite = compile.getLateInlineCall(); - ArrayDeque thisCallScopes = new ArrayDeque(); - do { - bci = caller.getBci(); - // Next inlined call. - caller = lateInlineScope.pop(); - CallSite callee = new CallSite(bci, caller.getMethod()); - callee.setInlineId(caller.getInlineId()); - thisCallScopes.addLast(callee); - lateInlineSite.add(callee); - lateInlineSite = callee; - } while (!lateInlineScope.empty()); + // Walk down the inlining chain and assemble bci+callee info. + // This needs to be converted from caller+bci info contained in + // the late_inline data. + CallSite lateInlineSite = compile.getLateInlineCall(); + ArrayDeque thisCallScopes = new ArrayDeque<>(); + do { + current_bci = caller.getBci(); + // Next inlined call. + caller = lateInlineScope.pop(); + CallSite callee = new CallSite(current_bci, caller.getMethod()); + callee.setInlineId(caller.getInlineId()); + thisCallScopes.addLast(callee); + lateInlineSite.add(callee); + lateInlineSite = callee; + } while (!lateInlineScope.isEmpty()); - site = compile.getCall().findCallSite(thisCallScopes); - if (site == null) { - System.out.println("call scopes:"); - for (CallSite c : thisCallScopes) { - System.out.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId()); + site = compile.getCall().findCallSite(thisCallScopes); + if (site == null) { + // Call site could not be found - report the problem in detail. + System.err.println("call scopes:"); + for (CallSite c : thisCallScopes) { + System.err.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId()); + } + CallSite c = thisCallScopes.getLast(); + if (c.getInlineId() != 0) { + System.err.println("Looking for call site in entire tree:"); + ArrayDeque stack = compile.getCall().findCallSite2(c); + for (CallSite c2 : stack) { + System.err.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId()); + } + } + System.err.println(caller.getMethod() + " bci: " + current_bci); + reportInternalError("couldn't find call site"); } - CallSite c = thisCallScopes.getLast(); - if (c.getInlineId() != 0) { - System.out.println("Looking for call site in entire tree:"); - ArrayDeque stack = compile.getCall().findCallSite2(c); - for (CallSite c2 : stack) { - System.out.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId()); + lateInlining = true; + + if (caller.getBci() != -999) { + System.out.println(caller.getMethod()); + reportInternalError("broken late_inline info"); + } + if (site.getMethod() != caller.getMethod()) { + if (site.getInlineId() == caller.getInlineId()) { + site.setMethod(caller.getMethod()); + } else { + System.out.println(site.getMethod()); + System.out.println(caller.getMethod()); + reportInternalError("call site and late_inline info don't match"); } } - System.out.println(caller.getMethod() + " bci: " + bci); - throw new InternalError("couldn't find call site"); - } - lateInlining = true; - - if (caller.getBci() != -999) { - System.out.println(caller.getMethod()); - throw new InternalError("broken late_inline info"); + // late_inline is followed by parse with scopes.size() == 0, + // 'site' will be pushed to scopes. + lateInlineScope = null; + } else if (qname.equals("task")) { + types.clear(); + methods.clear(); + site = null; } - if (site.getMethod() != caller.getMethod()) { - if (site.getInlineId() == caller.getInlineId()) { - site.setMethod(caller.getMethod()); - } else { - System.out.println(site.getMethod()); - System.out.println(caller.getMethod()); - throw new InternalError("call site and late_inline info don't match"); - } - } - // late_inline is followed by parse with scopes.size() == 0, - // 'site' will be pushed to scopes. - lateInlineScope = null; - } else if (qname.equals("task")) { - types.clear(); - methods.clear(); - site = null; + } catch (Exception e) { + reportInternalError("exception while processing end element", e); } } + // + // Handlers for problems that occur in XML parsing itself. + // + @Override public void warning(org.xml.sax.SAXParseException e) { System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber()); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,25 @@ * questions. * */ - package com.sun.hotspot.tools.compiler; import java.io.PrintStream; +/** + * In a compilation log, represent the event of making a given compiled method + * not-entrant, e.g., during an OSR compilation. + */ class MakeNotEntrantEvent extends BasicLogEvent { + + /** + * Denote whether the method is marked as a zombie, i.e., no further + * activations exist. + */ private final boolean zombie; + /** + * The method in question. + */ private NMethod nmethod; MakeNotEntrantEvent(double s, String i, boolean z, NMethod nm) { @@ -41,7 +52,7 @@ return nmethod; } - public void print(PrintStream stream) { + public void print(PrintStream stream, boolean printID) { if (isZombie()) { stream.printf("%s make_zombie\n", getId()); } else { diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,16 +26,58 @@ import java.util.Arrays; -public class Method implements Constants { +import static com.sun.hotspot.tools.compiler.Constants.*; + +/** + * Representation of a Java method in a compilation log. + */ +public class Method { + /** + * The name of the class holding the method. + */ private String holder; + + /** + * The method's name. + */ private String name; + + /** + * The return type of the method, as a fully qualified (source-level) class + * or primitive type name. + */ private String returnType; - private String arguments; + + /** + * The method's signature, in internal form. + */ + private String signature; + + /** + * The length of the method's byte code. + */ private String bytes; + + /** + * The number of times this method was invoked in the interpreter. + */ private String iicount; + + /** + * The method's flags, in the form of a {@code String} representing the + * {@code int} encoding them. + */ private String flags; + /** + * Decode the {@link flags} numerical string to a format for console + * output. The result does not honour all possible flags but includes + * information about OSR compilation. + * + * @param osr_bci the byte code index at which an OSR compilation takes + * place, or -1 if the compilation is not an OSR one. + */ String decodeFlags(int osr_bci) { int f = Integer.parseInt(getFlags()); char[] c = new char[4]; @@ -49,6 +91,12 @@ return new String(c); } + /** + * Format this method for console output. + * + * @param osr_bci the byte code index at which OSR takes place, or -1 if no + * OSR compilation is going on. + */ String format(int osr_bci) { if (osr_bci >= 0) { return getHolder() + "::" + getName() + " @ " + osr_bci + " (" + getBytes() + " bytes)"; @@ -62,6 +110,10 @@ return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)"; } + public String getFullName() { + return getHolder().replace('/', '.') + "." + getName() + signature; + } + public String getHolder() { return holder; } @@ -86,12 +138,16 @@ this.returnType = returnType; } - public String getArguments() { - return arguments; + public String getSignature() { + return signature; } - public void setArguments(String arguments) { - this.arguments = arguments; + public void setSignature(String signature) { + this.signature = signature.replace('/', '.'); + } + + public String getArguments() { + return signature.substring(0, signature.indexOf(')') + 1); } public String getBytes() { @@ -121,10 +177,13 @@ @Override public boolean equals(Object o) { if (o instanceof Method) { - Method other = (Method)o; - return holder.equals(other.holder) && name.equals(other.name) && - arguments.equals(other.arguments) && returnType.equals(other.returnType); + Method other = (Method) o; + return holder.equals(other.holder) && name.equals(other.name) && signature.equals(other.signature); } return false; } + + public int hashCode() { + return holder.hashCode() ^ name.hashCode(); + } } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,20 @@ import java.io.PrintStream; +/** + * A compilation log event that is signalled whenever a new nmethod (a native + * method, a compilation result) is created. + */ public class NMethod extends BasicLogEvent { + /** + * The nmethod's starting address in memory. + */ private long address; + + /** + * The nmethod's size in bytes. + */ private long size; NMethod(double s, String i, long a, long sz) { @@ -37,7 +48,7 @@ size = sz; } - public void print(PrintStream out) { + public void print(PrintStream out, boolean printID) { // XXX Currently we do nothing // throw new InternalError(); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,30 @@ import java.io.PrintStream; +/** + * Representation of a compilation phase as a log event. + */ public class Phase extends BasicLogEvent { + /** + * The number of nodes in the compilation at the beginning of this phase. + */ private final int startNodes; + + /** + * The number of nodes in the compilation at the end of this phase. + */ private int endNodes; + + /** + * The number of live nodes in the compilation at the beginning of this + * phase. + */ private final int startLiveNodes; + + /** + * The number of live nodes in the compilation at the end of this phase. + */ private int endLiveNodes; Phase(String n, double s, int nodes, int live) { @@ -58,8 +77,11 @@ public int getEndNodes() { return endNodes; } - /* Number of live nodes added by the phase */ - int getLiveNodes() { + + /** + * The number of live nodes added by this phase. + */ + int getAddedLiveNodes() { return getEndLiveNodes() - getStartLiveNodes(); } @@ -76,7 +98,7 @@ } @Override - public void print(PrintStream stream) { + public void print(PrintStream stream, boolean printID) { throw new UnsupportedOperationException("Not supported yet."); } } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.hotspot.tools.compiler; + +import java.io.PrintStream; + +/** + * An instance of this class represents an uncommon trap associated with a + * given bytecode instruction. An uncommon trap is described in terms of its + * reason and action to be taken. An instance of this class is always relative + * to a specific method and only contains the relevant bytecode instruction + * index. + */ +class UncommonTrap { + + private int bci; + private String reason; + private String action; + private String bytecode; + + public UncommonTrap(int b, String r, String a, String bc) { + bci = b; + reason = r; + action = a; + bytecode = bc; + } + + public int getBCI() { + return bci; + } + + public String getReason() { + return reason; + } + + public String getAction() { + return action; + } + + public String getBytecode() { + return bytecode; + } + + void emit(PrintStream stream, int indent) { + for (int i = 0; i < indent; i++) { + stream.print(' '); + } + } + + public void print(PrintStream stream, int indent) { + emit(stream, indent); + stream.println(this); + } + + public String toString() { + return "@ " + bci + " " + getBytecode() + " uncommon trap " + getReason() + " " + getAction(); + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Wed Jul 05 20:43:22 2017 +0200 @@ -21,17 +21,33 @@ * questions. * */ - package com.sun.hotspot.tools.compiler; import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +/** + * Represents an uncommon trap encountered during a compilation. + */ class UncommonTrapEvent extends BasicLogEvent { private final String reason; private final String action; + + /** + * Denote how many times this trap has been encountered. + */ private int count; - private String jvms = ""; + + /** + * The name of the bytecode instruction at which the trap occurred. + */ + private String bytecode; + + private List jvmsMethods = new ArrayList<>(); + + private List jvmsBCIs = new ArrayList<>(); UncommonTrapEvent(double s, String i, String r, String a, int c) { super(s, i); @@ -40,20 +56,26 @@ count = c; } - - public void addJVMS(String method, int bci) { - setJvms(getJvms() + " @" + bci + " " + method + "\n"); - } - public void updateCount(UncommonTrapEvent trap) { setCount(Math.max(getCount(), trap.getCount())); } - public void print(PrintStream stream) { - stream.printf("%s uncommon trap %.3f %s %s\n", getId(), getStart(), getReason(), getAction()); - stream.print(getJvms()); + public void print(PrintStream stream, boolean printID) { + if (printID) { + stream.print(getId() + " "); + } + stream.printf("uncommon trap %s %s %s\n", bytecode, getReason(), getAction()); + int indent = 2; + for (int j = 0; j < jvmsMethods.size(); j++) { + for (int i = 0; i < indent; i++) { + stream.print(' '); + } + stream.println("@ " + jvmsBCIs.get(j) + " " + jvmsMethods.get(j)); + indent += 2; + } } + public String getReason() { return reason; } @@ -70,15 +92,56 @@ this.count = count; } - public String getJvms() { - return jvms; + /** + * Set the compilation for this event. This involves identifying the call + * site to which this uncommon trap event belongs. In addition to setting + * the {@link #compilation} link, this method will consequently also set + * the {@link #bytecode} field. + */ + public void setCompilation(Compilation compilation) { + super.setCompilation(compilation); + // Attempt to associate a bytecode with with this trap + CallSite site = compilation.getCall(); + int i = 0; + try { + List traps = site.getTraps(); + while (i + 1 < jvmsMethods.size()) { + if (!jvmsMethods.get(i).equals(site.getMethod().getFullName())) { + throw new InternalError(jvmsMethods.get(i) + " != " + site.getMethod().getFullName()); + } + CallSite result = null; + for (CallSite call : site.getCalls()) { + if (call.getBci() == jvmsBCIs.get(i) && + call.getMethod().getFullName().equals(jvmsMethods.get(i + 1)) && + call.getReceiver() == null) { + result = call; + i++; + break; + } + } + if (result == null) { + throw new InternalError("couldn't find call site"); + } + site = result; + traps = site.getTraps(); + } + for (UncommonTrap trap : traps) { + if (trap.getBCI() == jvmsBCIs.get(i) && + trap.getReason().equals(getReason()) && + trap.getAction().equals(getAction())) { + bytecode = trap.getBytecode(); + return; + } + } + throw new InternalError("couldn't find bytecode"); + } catch (Exception e) { + bytecode = ""; + } } - public void setJvms(String jvms) { - this.jvms = jvms; + public void addMethodAndBCI(String method, int bci) { + jvmsMethods.add(0, method); + jvmsBCIs.add(0, bci); } - public void setCompilation(Compilation compilation) { - this.compilation = compilation; - } } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/ci/ciMethod.cpp --- a/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -75,6 +75,9 @@ { assert(h_m() != NULL, "no null method"); + if (LogTouchedMethods) { + h_m()->log_touched(Thread::current()); + } // These fields are always filled in in loaded methods. _flags = ciFlags(h_m()->access_flags()); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -2698,8 +2698,7 @@ // Inner class index u2 inner_class_info_index = cfs->get_u2_fast(); check_property( - inner_class_info_index == 0 || - valid_klass_reference_at(inner_class_info_index), + valid_klass_reference_at(inner_class_info_index), "inner_class_info_index %u has bad constant type in class file %s", inner_class_info_index, CHECK_0); // Outer class index @@ -5163,8 +5162,8 @@ // The first non-signature thing better be a ')' if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { length--; - if (name->utf8_length() > 0 && name->byte_at(0) == '<') { - // All internal methods must return void + if (name == vmSymbols::object_initializer_name()) { + // All "" methods must return void if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) { return args_size; } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/classfile/symbolTable.cpp --- a/hotspot/src/share/vm/classfile/symbolTable.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -58,14 +58,14 @@ if (DumpSharedSpaces) { // Allocate all symbols to CLD shared metaspace - sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1); + sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, PERM_REFCOUNT); } else if (c_heap) { // refcount starts as 1 sym = new (len, THREAD) Symbol(name, len, 1); assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); } else { // Allocate to global arena - sym = new (len, arena(), THREAD) Symbol(name, len, -1); + sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT); } return sym; } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -2846,7 +2846,7 @@ if (sig_stream.type() != T_VOID) { if (method_name == vmSymbols::object_initializer_name()) { // method must have a void return type - /* Unreachable? Class file parser verifies that methods with '<' have + /* Unreachable? Class file parser verifies that methods have * void return */ verify_error(ErrorContext::bad_code(bci), "Return type must be void in method"); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/compiler/compileBroker.cpp --- a/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -501,8 +501,8 @@ methodHandle method(thread, this->method()); ResourceMark rm(thread); - // - log->print(" compile_id='%d'", _compile_id); + // + log->print(" compiler='%s' compile_id='%d'", _comp_level <= CompLevel_full_profile ? "C1" : "C2", _compile_id); if (_osr_bci != CompileBroker::standard_entry_bci) { log->print(" compile_kind='osr'"); // same as nmethod::compile_kind } // else compile_kind='c2c' diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/gc/cms/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -848,7 +848,7 @@ _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); - } while (!_gch->no_allocs_since_save_marks(true /* include_young */)); + } while (!_gch->no_allocs_since_save_marks()); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/gc/serial/defNewGeneration.cpp --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -96,7 +96,7 @@ void DefNewGeneration::EvacuateFollowersClosure::do_void() { do { _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); - } while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen)); + } while (!_gch->no_allocs_since_save_marks()); } DefNewGeneration::FastEvacuateFollowersClosure:: @@ -112,7 +112,7 @@ void DefNewGeneration::FastEvacuateFollowersClosure::do_void() { do { _gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older); - } while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen)); + } while (!_gch->no_allocs_since_save_marks()); guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan"); } @@ -597,7 +597,7 @@ gch->rem_set()->prepare_for_younger_refs_iterate(false); - assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen), + assert(gch->no_allocs_since_save_marks(), "save marks have not been newly set."); // Not very pretty. @@ -617,7 +617,7 @@ &fsc_with_no_gc_barrier, &fsc_with_gc_barrier); - assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen), + assert(gch->no_allocs_since_save_marks(), "save marks have not been newly set."); { diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -741,11 +741,9 @@ #undef GCH_SINCE_SAVE_MARKS_ITERATE_DEFN -bool GenCollectedHeap::no_allocs_since_save_marks(bool include_young) { - if (include_young && !_young_gen->no_allocs_since_save_marks()) { - return false; - } - return _old_gen->no_allocs_since_save_marks(); +bool GenCollectedHeap::no_allocs_since_save_marks() { + return _young_gen->no_allocs_since_save_marks() && + _old_gen->no_allocs_since_save_marks(); } bool GenCollectedHeap::supports_inline_contig_alloc() const { diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -436,7 +436,7 @@ // Returns "true" iff no allocations have occurred since the last // call to "save_marks". - bool no_allocs_since_save_marks(bool include_young); + bool no_allocs_since_save_marks(); // Returns true if an incremental collection is likely to fail. // We optionally consult the young gen, if asked to do so; diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/oops/markOop.cpp --- a/hotspot/src/share/vm/oops/markOop.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/oops/markOop.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -32,26 +32,32 @@ void markOopDesc::print_on(outputStream* st) const { if (is_marked()) { st->print(" marked(" INTPTR_FORMAT ")", value()); + } else if (has_monitor()) { + // have to check has_monitor() before is_locked() + st->print(" monitor(" INTPTR_FORMAT ")=", value()); + ObjectMonitor* mon = monitor(); + if (mon == NULL) { + st->print("NULL (this should never be seen!)"); + } else { + st->print("{count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT + ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", + mon->count(), mon->waiters(), mon->recursions(), + p2i(mon->owner())); + } } else if (is_locked()) { st->print(" locked(" INTPTR_FORMAT ")->", value()); if (is_neutral()) { st->print("is_neutral"); - if (has_no_hash()) st->print(" no_hash"); - else st->print(" hash=" INTPTR_FORMAT, hash()); + if (has_no_hash()) { + st->print(" no_hash"); + } else { + st->print(" hash=" INTPTR_FORMAT, hash()); + } st->print(" age=%d", age()); } else if (has_bias_pattern()) { st->print("is_biased"); JavaThread* jt = biased_locker(); st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt)); - } else if (has_monitor()) { - ObjectMonitor* mon = monitor(); - if (mon == NULL) - st->print("monitor=NULL"); - else { - BasicLock * bl = (BasicLock *) mon->owner(); - st->print("monitor={count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", - mon->count(), mon->waiters(), mon->recursions(), p2i(bl)); - } } else { st->print("??"); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -422,6 +422,11 @@ if (!mh->init_method_counters(counters)) { MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters); } + + if (LogTouchedMethods) { + mh->log_touched(CHECK_NULL); + } + return mh->method_counters(); } @@ -2130,6 +2135,85 @@ } #endif // INCLUDE_SERVICES +// LogTouchedMethods and PrintTouchedMethods + +// TouchedMethodRecord -- we can't use a HashtableEntry because +// the Method may be garbage collected. Let's roll our own hash table. +class TouchedMethodRecord : CHeapObj { +public: + // It's OK to store Symbols here because they will NOT be GC'ed if + // LogTouchedMethods is enabled. + TouchedMethodRecord* _next; + Symbol* _class_name; + Symbol* _method_name; + Symbol* _method_signature; +}; + +static const int TOUCHED_METHOD_TABLE_SIZE = 20011; +static TouchedMethodRecord** _touched_method_table = NULL; + +void Method::log_touched(TRAPS) { + + const int table_size = TOUCHED_METHOD_TABLE_SIZE; + Symbol* my_class = klass_name(); + Symbol* my_name = name(); + Symbol* my_sig = signature(); + + unsigned int hash = my_class->identity_hash() + + my_name->identity_hash() + + my_sig->identity_hash(); + juint index = juint(hash) % table_size; + + MutexLocker ml(TouchedMethodLog_lock, THREAD); + if (_touched_method_table == NULL) { + _touched_method_table = NEW_C_HEAP_ARRAY2(TouchedMethodRecord*, table_size, + mtTracing, CURRENT_PC); + memset(_touched_method_table, 0, sizeof(TouchedMethodRecord*)*table_size); + } + + TouchedMethodRecord* ptr = _touched_method_table[index]; + while (ptr) { + if (ptr->_class_name == my_class && + ptr->_method_name == my_name && + ptr->_method_signature == my_sig) { + return; + } + if (ptr->_next == NULL) break; + ptr = ptr->_next; + } + TouchedMethodRecord* nptr = NEW_C_HEAP_OBJ(TouchedMethodRecord, mtTracing); + my_class->set_permanent(); // prevent reclaimed by GC + my_name->set_permanent(); + my_sig->set_permanent(); + nptr->_class_name = my_class; + nptr->_method_name = my_name; + nptr->_method_signature = my_sig; + nptr->_next = NULL; + + if (ptr == NULL) { + // first + _touched_method_table[index] = nptr; + } else { + ptr->_next = nptr; + } +} + +void Method::print_touched_methods(outputStream* out) { + MutexLockerEx ml(Thread::current()->is_VM_thread() ? NULL : TouchedMethodLog_lock); + out->print_cr("# Method::print_touched_methods version 1"); + if (_touched_method_table) { + for (int i = 0; i < TOUCHED_METHOD_TABLE_SIZE; i++) { + TouchedMethodRecord* ptr = _touched_method_table[i]; + while(ptr) { + ptr->_class_name->print_symbol_on(out); out->print("."); + ptr->_method_name->print_symbol_on(out); out->print(":"); + ptr->_method_signature->print_symbol_on(out); out->cr(); + ptr = ptr->_next; + } + } + } +} + // Verification void Method::verify_on(outputStream* st) { diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/oops/method.hpp --- a/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -625,6 +625,8 @@ #if INCLUDE_SERVICES void collect_statistics(KlassSizeStats *sz) const; #endif + void log_touched(TRAPS); + static void print_touched_methods(outputStream* out); // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/oops/symbol.hpp --- a/hotspot/src/share/vm/oops/symbol.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/oops/symbol.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,12 +96,16 @@ // TempNewSymbol (passed in as a parameter) so the reference count on its symbol // will be decremented when it goes out of scope. - // This cannot be inherited from ResourceObj because it cannot have a vtable. // Since sometimes this is allocated from Metadata, pick a base allocation // type without virtual functions. class ClassLoaderData; +// Set _refcount to PERM_REFCOUNT to prevent the Symbol from being GC'ed. +#ifndef PERM_REFCOUNT +#define PERM_REFCOUNT -1 +#endif + // We separate the fields in SymbolBase from Symbol::_body so that // Symbol::size(int) can correctly calculate the space needed. class SymbolBase : public MetaspaceObj { @@ -160,6 +164,13 @@ int refcount() const { return _refcount; } void increment_refcount(); void decrement_refcount(); + // Set _refcount non zero to avoid being reclaimed by GC. + void set_permanent() { + assert(LogTouchedMethods, "Should not be called with LogTouchedMethods off"); + if (_refcount != PERM_REFCOUNT) { + _refcount = PERM_REFCOUNT; + } + } int byte_at(int index) const { assert(index >=0 && index < _length, "symbol index overflow"); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -280,6 +280,10 @@ || (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) { return false; // too large to safely clone } + + // check for vectorized loops, any peeling done was already applied + if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) return false; + while( test != _head ) { // Scan till run off top of loop if( test->is_If() ) { // Test? Node *ctrl = phase->get_ctrl(test->in(1)); @@ -656,7 +660,12 @@ _local_loop_unroll_limit = LoopUnrollLimit; _local_loop_unroll_factor = 4; int future_unroll_ct = cl->unrolled_count() * 2; - if (future_unroll_ct > LoopMaxUnroll) return false; + if (!cl->do_unroll_only()) { + if (future_unroll_ct > LoopMaxUnroll) return false; + } else { + // obey user constraints on vector mapped loops with additional unrolling applied + if ((future_unroll_ct / cl->slp_max_unroll()) > LoopMaxUnroll) return false; + } // Check for initial stride being a small enough constant if (abs(cl->stride_con()) > (1<<2)*future_unroll_ct) return false; @@ -759,13 +768,19 @@ if (LoopMaxUnroll > _local_loop_unroll_factor) { // Once policy_slp_analysis succeeds, mark the loop with the // maximal unroll factor so that we minimize analysis passes - if ((future_unroll_ct > _local_loop_unroll_factor) || - (body_size > (uint)_local_loop_unroll_limit)) { + if (future_unroll_ct >= _local_loop_unroll_factor) { policy_unroll_slp_analysis(cl, phase, future_unroll_ct); } } } + int slp_max_unroll_factor = cl->slp_max_unroll(); + if (cl->has_passed_slp()) { + if (slp_max_unroll_factor >= future_unroll_ct) return true; + // Normal case: loop too big + return false; + } + // Check for being too big if (body_size > (uint)_local_loop_unroll_limit) { if (xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true; @@ -773,6 +788,10 @@ return false; } + if(cl->do_unroll_only()) { + NOT_PRODUCT(if (TraceSuperWordLoopUnrollAnalysis) tty->print_cr("policy_unroll passed vector loop(vlen=%d,factor = %d)\n", slp_max_unroll_factor, future_unroll_ct)); + } + // Unroll once! (Each trip will soon do double iterations) return true; } @@ -780,28 +799,24 @@ void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_ct) { // Enable this functionality target by target as needed if (SuperWordLoopUnrollAnalysis) { - if (!cl->has_passed_slp()) { + if (!cl->was_slp_analyzed()) { SuperWord sw(phase); sw.transform_loop(this, false); // If the loop is slp canonical analyze it if (sw.early_return() == false) { - sw.unrolling_analysis(cl, _local_loop_unroll_factor); + sw.unrolling_analysis(_local_loop_unroll_factor); } } - int slp_max_unroll_factor = cl->slp_max_unroll(); - if ((slp_max_unroll_factor > 4) && - (slp_max_unroll_factor >= future_unroll_ct)) { - int new_limit = cl->node_count_before_unroll() * slp_max_unroll_factor; - if (new_limit > LoopUnrollLimit) { -#ifndef PRODUCT - if (TraceSuperWordLoopUnrollAnalysis) { - tty->print_cr("slp analysis is applying unroll limit %d, the original limit was %d\n", - new_limit, _local_loop_unroll_limit); + if (cl->has_passed_slp()) { + int slp_max_unroll_factor = cl->slp_max_unroll(); + if (slp_max_unroll_factor >= future_unroll_ct) { + int new_limit = cl->node_count_before_unroll() * slp_max_unroll_factor; + if (new_limit > LoopUnrollLimit) { + NOT_PRODUCT(if (TraceSuperWordLoopUnrollAnalysis) tty->print_cr("slp analysis unroll=%d, default limit=%d\n", new_limit, _local_loop_unroll_limit)); + _local_loop_unroll_limit = new_limit; } -#endif - _local_loop_unroll_limit = new_limit; } } } @@ -830,6 +845,9 @@ if (cl->is_main_no_pre_loop()) return false; // Disallowed for now. Node *trip_counter = cl->phi(); + // check for vectorized loops, some opts are no longer needed + if (cl->do_unroll_only()) return false; + // Check loop body for tests of trip-counter plus loop-invariant vs // loop-invariant. for (uint i = 0; i < _body.size(); i++) { @@ -880,6 +898,8 @@ // Return TRUE or FALSE if the loop should NEVER be RCE'd or aligned. Useful // for unrolling loops with NO array accesses. bool IdealLoopTree::policy_peel_only( PhaseIdealLoop *phase ) const { + // check for vectorized loops, any peeling done was already applied + if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) return false; for( uint i = 0; i < _body.size(); i++ ) if( _body[i]->is_Mem() ) diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/opto/loopUnswitch.cpp --- a/hotspot/src/share/vm/opto/loopUnswitch.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopUnswitch.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -61,6 +61,12 @@ if (!_head->is_Loop()) { return false; } + + // check for vectorized loops, any unswitching was already applied + if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) { + return false; + } + int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes(); if ((int)(2 * _body.size()) > nodes_left) { return false; // Too speculative if running low on nodes. diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/opto/loopnode.cpp --- a/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -2317,7 +2317,11 @@ // Reassociate invariants and prep for split_thru_phi for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { IdealLoopTree* lpt = iter.current(); - if (!lpt->is_counted() || !lpt->is_inner()) continue; + bool is_counted = lpt->is_counted(); + if (!is_counted || !lpt->is_inner()) continue; + + // check for vectorized loops, any reassociation of invariants was already done + if (is_counted && lpt->_head->as_CountedLoop()->do_unroll_only()) continue; lpt->reassociate_invariants(this); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/opto/loopnode.hpp --- a/hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -64,7 +64,9 @@ PartialPeelLoop=32, PartialPeelFailed=64, HasReductions=128, - PassedSlpAnalysis=256 }; + WasSlpAnalyzed=256, + PassedSlpAnalysis=512, + DoUnrollOnly=1024 }; char _unswitch_count; enum { _unswitch_max=3 }; @@ -80,7 +82,9 @@ int partial_peel_has_failed() const { return _loop_flags & PartialPeelFailed; } void mark_partial_peel_failed() { _loop_flags |= PartialPeelFailed; } void mark_has_reductions() { _loop_flags |= HasReductions; } + void mark_was_slp() { _loop_flags |= WasSlpAnalyzed; } void mark_passed_slp() { _loop_flags |= PassedSlpAnalysis; } + void mark_do_unroll_only() { _loop_flags |= DoUnrollOnly; } int unswitch_max() { return _unswitch_max; } int unswitch_count() { return _unswitch_count; } @@ -212,7 +216,9 @@ int is_main_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Main; } int is_post_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Post; } int is_reduction_loop() const { return (_loop_flags&HasReductions) == HasReductions; } + int was_slp_analyzed () const { return (_loop_flags&WasSlpAnalyzed) == WasSlpAnalyzed; } int has_passed_slp () const { return (_loop_flags&PassedSlpAnalysis) == PassedSlpAnalysis; } + int do_unroll_only () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; } int is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; } void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; } @@ -235,6 +241,9 @@ void set_nonexact_trip_count() { _loop_flags &= ~HasExactTripCount; } + void set_notpassed_slp() { + _loop_flags &= ~PassedSlpAnalysis; + } void set_profile_trip_cnt(float ptc) { _profile_trip_cnt = ptc; } float profile_trip_cnt() { return _profile_trip_cnt; } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -100,6 +100,10 @@ return; } + // We only re-enter slp when we vector mapped a queried loop and we want to + // continue unrolling, in this case, slp is not subsequently done. + if (cl->do_unroll_only()) return; + // Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit)))) CountedLoopEndNode* pre_end = get_pre_loop_end(cl); if (pre_end == NULL) return; @@ -121,12 +125,13 @@ } //------------------------------early unrolling analysis------------------------------ -void SuperWord::unrolling_analysis(CountedLoopNode *cl, int &local_loop_unroll_factor) { +void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) { bool is_slp = true; ResourceMark rm; size_t ignored_size = lpt()->_body.size(); int *ignored_loop_nodes = NEW_RESOURCE_ARRAY(int, ignored_size); Node_Stack nstack((int)ignored_size); + CountedLoopNode *cl = lpt()->_head->as_CountedLoop(); Node *cl_exit = cl->loopexit(); // First clear the entries @@ -249,13 +254,9 @@ // If a max vector exists which is not larger than _local_loop_unroll_factor // stop looking, we already have the max vector to map to. - if (cur_max_vector <= local_loop_unroll_factor) { + if (cur_max_vector < local_loop_unroll_factor) { is_slp = false; -#ifndef PRODUCT - if (TraceSuperWordLoopUnrollAnalysis) { - tty->print_cr("slp analysis fails: unroll limit equals max vector\n"); - } -#endif + NOT_PRODUCT(if (TraceSuperWordLoopUnrollAnalysis) tty->print_cr("slp analysis fails: unroll limit greater than max vector\n")); break; } @@ -268,8 +269,9 @@ } if (is_slp) { local_loop_unroll_factor = max_vector; + cl->mark_passed_slp(); } - cl->mark_passed_slp(); + cl->mark_was_slp(); cl->set_slp_max_unroll(local_loop_unroll_factor); } } @@ -1758,7 +1760,9 @@ } Compile* C = _phase->C; + CountedLoopNode *cl = lpt()->_head->as_CountedLoop(); uint max_vlen_in_bytes = 0; + uint max_vlen = 0; for (int i = 0; i < _block.length(); i++) { Node* n = _block.at(i); Node_List* p = my_pack(n); @@ -1841,6 +1845,7 @@ _igvn._worklist.push(vn); if (vlen_in_bytes > max_vlen_in_bytes) { + max_vlen = vlen; max_vlen_in_bytes = vlen_in_bytes; } #ifdef ASSERT @@ -1852,6 +1857,18 @@ } } C->set_max_vector_size(max_vlen_in_bytes); + if (SuperWordLoopUnrollAnalysis) { + if (cl->has_passed_slp()) { + uint slp_max_unroll_factor = cl->slp_max_unroll(); + if (slp_max_unroll_factor == max_vlen) { + NOT_PRODUCT(if (TraceSuperWordLoopUnrollAnalysis) tty->print_cr("vector loop(unroll=%d, len=%d)\n", max_vlen, max_vlen_in_bytes*BitsPerByte)); + // For atomic unrolled loops which are vector mapped, instigate more unrolling. + cl->set_notpassed_slp(); + C->set_major_progress(); + cl->mark_do_unroll_only(); + } + } + } } //------------------------------vector_opd--------------------------- diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/opto/superword.hpp --- a/hotspot/src/share/vm/opto/superword.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/opto/superword.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -241,7 +241,7 @@ void transform_loop(IdealLoopTree* lpt, bool do_optimization); - void unrolling_analysis(CountedLoopNode *cl, int &local_loop_unroll_factor); + void unrolling_analysis(int &local_loop_unroll_factor); // Accessors for SWPointer PhaseIdealLoop* phase() { return _phase; } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -277,6 +277,8 @@ { "ParallelGCRetainPLAB", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "ThreadSafetyMargin", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "LazyBootClassLoader", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "StarvationMonitorInterval", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "PreInflateSpin", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { NULL, JDK_Version(0), JDK_Version(0) } }; diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -1291,7 +1291,7 @@ experimental(intx, hashCode, 5, \ "(Unstable) select hashCode generation algorithm") \ \ - experimental(intx, WorkAroundNPTLTimedWaitHang, 1, \ + experimental(intx, WorkAroundNPTLTimedWaitHang, 0, \ "(Unstable, Linux-specific) " \ "avoid NPTL-FUTEX hang pthread_cond_timedwait") \ \ @@ -2717,6 +2717,12 @@ develop(bool, EagerInitialization, false, \ "Eagerly initialize classes if possible") \ \ + diagnostic(bool, LogTouchedMethods, false, \ + "Log methods which have been ever touched in runtime") \ + \ + diagnostic(bool, PrintTouchedMethodsAtExit, false, \ + "Print all methods that have been ever touched in runtime") \ + \ develop(bool, TraceMethodReplacement, false, \ "Print when methods are replaced do to recompilation") \ \ @@ -3282,9 +3288,6 @@ develop(intx, ProfilerNodeSize, 1024, \ "Size in K to allocate for the Profile Nodes of each thread") \ \ - product_pd(intx, PreInflateSpin, \ - "Number of times to spin wait before inflation") \ - \ /* gc parameters */ \ product(size_t, InitialHeapSize, 0, \ "Initial heap size (in bytes); zero means use ergonomics") \ @@ -3725,9 +3728,6 @@ develop(intx, LongCompileThreshold, 50, \ "Used with +TraceLongCompiles") \ \ - product(intx, StarvationMonitorInterval, 200, \ - "Pause between each check (in milliseconds)") \ - \ /* recompilation */ \ product_pd(intx, CompileThreshold, \ "number of interpreted method invocations before (re-)compiling") \ @@ -4080,9 +4080,6 @@ develop(bool, TraceDefaultMethods, false, \ "Trace the default method processing steps") \ \ - develop(bool, VerifyGenericSignatures, false, \ - "Abort VM on erroneous or inconsistent generic signatures") \ - \ diagnostic(bool, WhiteBoxAPI, false, \ "Enable internal testing APIs") \ \ diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/java.cpp --- a/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -330,6 +330,10 @@ SystemDictionary::print(); } + if (LogTouchedMethods && PrintTouchedMethodsAtExit) { + Method::print_touched_methods(tty); + } + if (PrintBiasedLockingStatistics) { BiasedLocking::print_counters(); } @@ -382,6 +386,10 @@ if (PrintNMTStatistics) { MemTracker::final_report(tty); } + + if (LogTouchedMethods && PrintTouchedMethodsAtExit) { + Method::print_touched_methods(tty); + } } #endif diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -63,6 +63,7 @@ Mutex* StringDedupTable_lock = NULL; Monitor* CodeCache_lock = NULL; Mutex* MethodData_lock = NULL; +Mutex* TouchedMethodLog_lock = NULL; Mutex* RetData_lock = NULL; Monitor* VMOperationQueue_lock = NULL; Monitor* VMOperationRequest_lock = NULL; @@ -274,6 +275,7 @@ def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes); def(MethodData_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always); + def(TouchedMethodLog_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always); def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always); def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/mutexLocker.hpp --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -55,6 +55,7 @@ extern Mutex* StringDedupTable_lock; // a lock on the string deduplication table extern Monitor* CodeCache_lock; // a lock on the CodeCache, rank is special, use MutexLockerEx extern Mutex* MethodData_lock; // a lock on installation of method data +extern Mutex* TouchedMethodLog_lock; // a lock on allocation of LogExecutedMethods info extern Mutex* RetData_lock; // a lock on installation of RetData inside method data extern Mutex* DerivedPointerTableGC_lock; // a lock to protect the derived pointer table extern Monitor* VMOperationQueue_lock; // a lock on queue of vm_operations waiting to execute diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/objectMonitor.cpp --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,8 +103,10 @@ // The knob* variables are effectively final. Once set they should // never be modified hence. Consider using __read_mostly with GCC. +int ObjectMonitor::Knob_ExitRelease = 0; int ObjectMonitor::Knob_Verbose = 0; int ObjectMonitor::Knob_VerifyInUse = 0; +int ObjectMonitor::Knob_VerifyMatch = 0; int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool - static int Knob_LogSpins = 0; // enable jvmstat tally for spins static int Knob_HandOff = 0; @@ -251,24 +253,6 @@ // ----------------------------------------------------------------------------- // Enter support -bool ObjectMonitor::try_enter(Thread* THREAD) { - if (THREAD != _owner) { - if (THREAD->is_lock_owned ((address)_owner)) { - assert(_recursions == 0, "internal state error"); - _owner = THREAD; - _recursions = 1; - return true; - } - if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) { - return false; - } - return true; - } else { - _recursions++; - return true; - } -} - void NOINLINE ObjectMonitor::enter(TRAPS) { // The following code is ordered to check the most common cases first // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors. @@ -2272,7 +2256,7 @@ } inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) { - assert(node != NULL, "should not dequeue NULL node"); + assert(node != NULL, "should not add NULL node"); assert(node->_prev == NULL, "node already in list"); assert(node->_next == NULL, "node already in list"); // put node at end of queue (circular doubly linked list) @@ -2407,8 +2391,8 @@ char * v = kvGet(kvList, Key); int rslt = v ? ::strtol(v, NULL, 0) : Default; if (Knob_ReportSettings && v != NULL) { - ::printf (" SyncKnob: %s %d(%d)\n", Key, rslt, Default) ; - ::fflush(stdout); + tty->print_cr("INFO: SyncKnob: %s %d(%d)", Key, rslt, Default) ; + tty->flush(); } return rslt; } @@ -2442,8 +2426,10 @@ #define SETKNOB(x) { Knob_##x = kvGetInt(knobs, #x, Knob_##x); } SETKNOB(ReportSettings); + SETKNOB(ExitRelease); SETKNOB(Verbose); SETKNOB(VerifyInUse); + SETKNOB(VerifyMatch); SETKNOB(FixedSpin); SETKNOB(SpinLimit); SETKNOB(SpinBase); @@ -2477,7 +2463,9 @@ if (os::is_MP()) { BackOffMask = (1 << Knob_SpinBackOff) - 1; - if (Knob_ReportSettings) ::printf("BackOffMask=%X\n", BackOffMask); + if (Knob_ReportSettings) { + tty->print_cr("INFO: BackOffMask=0x%X", BackOffMask); + } // CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1) } else { Knob_SpinLimit = 0; diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/objectMonitor.hpp --- a/hotspot/src/share/vm/runtime/objectMonitor.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -196,8 +196,10 @@ static PerfCounter * _sync_Deflations; static PerfLongVariable * _sync_MonExtant; + static int Knob_ExitRelease; static int Knob_Verbose; static int Knob_VerifyInUse; + static int Knob_VerifyMatch; static int Knob_SpinLimit; void* operator new (size_t size) throw() { @@ -317,7 +319,6 @@ void print(); #endif - bool try_enter(TRAPS); void enter(TRAPS); void exit(bool not_suspended, TRAPS); void wait(jlong millis, bool interruptable, TRAPS); @@ -354,14 +355,14 @@ #undef TEVENT #define TEVENT(nom) { if (SyncVerbose) FEVENT(nom); } -#define FEVENT(nom) \ - { \ - static volatile int ctr = 0; \ - int v = ++ctr; \ - if ((v & (v - 1)) == 0) { \ - ::printf(#nom " : %d\n", v); \ - ::fflush(stdout); \ - } \ +#define FEVENT(nom) \ + { \ + static volatile int ctr = 0; \ + int v = ++ctr; \ + if ((v & (v - 1)) == 0) { \ + tty->print_cr("INFO: " #nom " : %d", v); \ + tty->flush(); \ + } \ } #undef TEVENT diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/synchronizer.cpp --- a/hotspot/src/share/vm/runtime/synchronizer.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -40,6 +40,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/vframe.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/preserveException.hpp" @@ -927,8 +928,9 @@ if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) { if (ObjectMonitor::Knob_Verbose) { - ::printf ("Monitor scavenge - Induced STW @%s (%d)\n", Whence, ForceMonitorScavenge) ; - ::fflush(stdout); + tty->print_cr("INFO: Monitor scavenge - Induced STW @%s (%d)", + Whence, ForceMonitorScavenge) ; + tty->flush(); } // Induce a 'null' safepoint to scavenge monitors // Must VM_Operation instance be heap allocated as the op will be enqueue and posted @@ -937,8 +939,9 @@ VMThread::execute(new VM_ForceAsyncSafepoint()); if (ObjectMonitor::Knob_Verbose) { - ::printf ("Monitor scavenge - STW posted @%s (%d)\n", Whence, ForceMonitorScavenge) ; - ::fflush(stdout); + tty->print_cr("INFO: Monitor scavenge - STW posted @%s (%d)", + Whence, ForceMonitorScavenge) ; + tty->flush(); } } } @@ -1603,10 +1606,11 @@ // Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree. if (ObjectMonitor::Knob_Verbose) { - ::printf("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n", - nInCirculation, nInuse, nScavenged, ForceMonitorScavenge, - gMonitorPopulation, gMonitorFreeCount); - ::fflush(stdout); + tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d " + "ForceMonitorScavenge=%d : pop=%d free=%d", + nInCirculation, nInuse, nScavenged, ForceMonitorScavenge, + gMonitorPopulation, gMonitorFreeCount); + tty->flush(); } ForceMonitorScavenge = 0; // Reset @@ -1643,6 +1647,14 @@ ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {} void do_monitor(ObjectMonitor* mid) { if (mid->owner() == THREAD) { + if (ObjectMonitor::Knob_VerifyMatch != 0) { + Handle obj((oop) mid->object()); + tty->print("INFO: unexpected locked object:"); + javaVFrame::print_locked_object_class_name(tty, obj, "locked"); + fatal(err_msg("exiting JavaThread=" INTPTR_FORMAT + " unexpectedly owns ObjectMonitor=" INTPTR_FORMAT, + THREAD, mid)); + } (void)mid->complete_exit(CHECK); } } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -1802,14 +1802,25 @@ assert(!this->has_pending_exception(), "ensure_join should have cleared"); // 6282335 JNI DetachCurrentThread spec states that all Java monitors - // held by this thread must be released. A detach operation must only - // get here if there are no Java frames on the stack. Therefore, any - // owned monitors at this point MUST be JNI-acquired monitors which are - // pre-inflated and in the monitor cache. + // held by this thread must be released. The spec does not distinguish + // between JNI-acquired and regular Java monitors. We can only see + // regular Java monitors here if monitor enter-exit matching is broken. + // + // Optionally release any monitors for regular JavaThread exits. This + // is provided as a work around for any bugs in monitor enter-exit + // matching. This can be expensive so it is not enabled by default. + // ObjectMonitor::Knob_ExitRelease is a superset of the + // JNIDetachReleasesMonitors option. // - // ensure_join() ignores IllegalThreadStateExceptions, and so does this. - if (exit_type == jni_detach && JNIDetachReleasesMonitors) { - assert(!this->has_last_Java_frame(), "detaching with Java frames?"); + // ensure_join() ignores IllegalThreadStateExceptions, and so does + // ObjectSynchronizer::release_monitors_owned_by_thread(). + if ((exit_type == jni_detach && JNIDetachReleasesMonitors) || + ObjectMonitor::Knob_ExitRelease) { + // Sanity check even though JNI DetachCurrentThread() would have + // returned JNI_ERR if there was a Java frame. JavaThread exit + // should be done executing Java code by the time we get here. + assert(!this->has_last_Java_frame(), + "should not have a Java frame when detaching or exiting"); ObjectSynchronizer::release_monitors_owned_by_thread(this); assert(!this->has_pending_exception(), "release_monitors should have cleared"); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/vframe.cpp --- a/hotspot/src/share/vm/runtime/vframe.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vframe.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -144,7 +144,7 @@ return result; } -static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) { +void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) { if (obj.not_null()) { st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj()); if (obj->klass() == SystemDictionary::Class_klass()) { @@ -160,17 +160,29 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ResourceMark rm; - // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver. + // If this is the first frame and it is java.lang.Object.wait(...) + // then print out the receiver. Locals are not always available, + // e.g., compiled native frames have no scope so there are no locals. if (frame_count == 0) { if (method()->name() == vmSymbols::wait_name() && method()->method_holder()->name() == vmSymbols::java_lang_Object()) { + const char *wait_state = "waiting on"; // assume we are waiting + // If earlier in the output we reported java.lang.Thread.State == + // "WAITING (on object monitor)" and now we report "waiting on", then + // we are still waiting for notification or timeout. Otherwise if + // we earlier reported java.lang.Thread.State == "BLOCKED (on object + // monitor)", then we are actually waiting to re-lock the monitor. + // At this level we can't distinguish the two cases to report + // "waited on" rather than "waiting on" for the second case. StackValueCollection* locs = locals(); if (!locs->is_empty()) { StackValue* sv = locs->at(0); if (sv->type() == T_OBJECT) { Handle o = locs->at(0)->get_obj(); - print_locked_object_class_name(st, o, "waiting on"); + print_locked_object_class_name(st, o, wait_state); } + } else { + st->print_cr("\t- %s ", wait_state); } } else if (thread()->current_park_blocker() != NULL) { oop obj = thread()->current_park_blocker(); @@ -179,8 +191,8 @@ } } - - // Print out all monitors that we have locked or are trying to lock + // Print out all monitors that we have locked, or are trying to lock, + // including re-locking after being notified or timing out in a wait(). GrowableArray* mons = monitors(); if (!mons->is_empty()) { bool found_first_monitor = false; @@ -202,14 +214,14 @@ if (monitor->owner() != NULL) { // the monitor is associated with an object, i.e., it is locked - // First, assume we have the monitor locked. If we haven't found an - // owned monitor before and this is the first frame, then we need to - // see if we have completed the lock or we are blocked trying to - // acquire it - we can only be blocked if the monitor is inflated - markOop mark = NULL; const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { + // If this is the first frame and we haven't found an owned + // monitor before, then we need to see if we have completed + // the lock or if we are blocked trying to acquire it. Only + // an inflated monitor that is first on the monitor list in + // the first frame can block us on a monitor enter. mark = monitor->owner()->mark(); if (mark->has_monitor() && ( // we have marked ourself as pending on this monitor @@ -219,13 +231,35 @@ )) { lock_state = "waiting to lock"; } else { - mark = NULL; // Disable printing below + // We own the monitor which is not as interesting so + // disable the extra printing below. + mark = NULL; + } + } else if (frame_count != 0 && ObjectMonitor::Knob_Verbose) { + // This is not the first frame so we either own this monitor + // or we owned the monitor before and called wait(). Because + // wait() could have been called on any monitor in a lower + // numbered frame on the stack, we have to check all the + // monitors on the list for this frame. + // Note: Only enable this new output line in verbose mode + // since existing tests are not ready for it. + mark = monitor->owner()->mark(); + if (mark->has_monitor() && + ( // we have marked ourself as pending on this monitor + mark->monitor() == thread()->current_pending_monitor() || + // we are not the owner of this monitor + !mark->monitor()->is_entered(thread()) + )) { + lock_state = "waiting to re-lock in wait()"; + } else { + // We own the monitor which is not as interesting so + // disable the extra printing below. + mark = NULL; } } print_locked_object_class_name(st, monitor->owner(), lock_state); - if (Verbose && mark != NULL) { - // match with format above, replacing "-" with " ". - st->print("\t lockbits="); + if (ObjectMonitor::Knob_Verbose && mark != NULL) { + st->print("\t- lockbits="); mark->print_on(st); st->cr(); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/vframe.hpp --- a/hotspot/src/share/vm/runtime/vframe.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vframe.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,7 +135,8 @@ // Return an array of monitors locked by this frame in the youngest to oldest order GrowableArray* locked_monitors(); - // printing used during stack dumps + // printing used during stack dumps and diagnostics + static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state); void print_lock_info_on(outputStream* st, int frame_count); void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/runtime/vm_operations.hpp --- a/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -101,6 +101,7 @@ template(WhiteBoxOperation) \ template(ClassLoaderStatsOperation) \ template(DumpHashtable) \ + template(DumpTouchedMethods) \ template(MarkActiveNMethods) \ template(PrintCompileQueue) \ template(PrintCodeList) \ diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/services/diagnosticCommand.cpp --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 20:43:22 2017 +0200 @@ -74,6 +74,7 @@ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); // Enhanced JMX Agent Support // These commands won't be exported via the DiagnosticCommandMBean until an @@ -808,3 +809,35 @@ } #endif + +class VM_DumpTouchedMethods : public VM_Operation { +private: + outputStream* _out; +public: + VM_DumpTouchedMethods(outputStream* out) { + _out = out; + } + + virtual VMOp_Type type() const { return VMOp_DumpTouchedMethods; } + + virtual void doit() { + Method::print_touched_methods(_out); + } +}; + +TouchedMethodsDCmd::TouchedMethodsDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap) +{} + +void TouchedMethodsDCmd::execute(DCmdSource source, TRAPS) { + if (!UnlockDiagnosticVMOptions) { + output()->print_cr("VM.touched_methods command requires -XX:+UnlockDiagnosticVMOptions"); + return; + } + VM_DumpTouchedMethods dumper(output()); + VMThread::execute(&dumper); +} + +int TouchedMethodsDCmd::num_arguments() { + return 0; +} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/src/share/vm/services/diagnosticCommand.hpp --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 20:43:22 2017 +0200 @@ -35,6 +35,7 @@ #include "services/diagnosticFramework.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" +#include "oops/method.hpp" class HelpDCmd : public DCmdWithParser { protected: @@ -341,6 +342,22 @@ virtual void execute(DCmdSource source, TRAPS); }; +class TouchedMethodsDCmd : public DCmdWithParser { +public: + TouchedMethodsDCmd(outputStream* output, bool heap); + static const char* name() { + return "VM.print_touched_methods"; + } + static const char* description() { + return "Print all methods that have ever been touched during the lifetime of this JVM."; + } + static const char* impact() { + return "Medium: Depends on Java content."; + } + static int num_arguments(); + virtual void execute(DCmdSource source, TRAPS); +}; + // See also: thread_dump in attachListener.cpp class ThreadDumpDCmd : public DCmdWithParser { protected: diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/compiler/codegen/7184394/TestAESBase.java --- a/hotspot/test/compiler/codegen/7184394/TestAESBase.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/compiler/codegen/7184394/TestAESBase.java Wed Jul 05 20:43:22 2017 +0200 @@ -61,12 +61,12 @@ final Random random = Utils.getRandomInstance(); Cipher cipher; Cipher dCipher; - AlgorithmParameters algParams; + AlgorithmParameters algParams = null; SecretKey key; GCMParameterSpec gcm_spec; - byte[] aad; + byte[] aad = { 0x11, 0x22, 0x33, 0x44, 0x55 }; int tlen = 12; - byte[] iv; + byte[] iv = new byte[16]; static int numThreads = 0; int threadId; @@ -80,7 +80,10 @@ public void prepare() { try { - System.out.println("\nalgorithm=" + algorithm + ", mode=" + mode + ", paddingStr=" + paddingStr + ", msgSize=" + msgSize + ", keySize=" + keySize + ", noReinit=" + noReinit + ", checkOutput=" + checkOutput + ", encInputOffset=" + encInputOffset + ", encOutputOffset=" + encOutputOffset + ", decOutputOffset=" + decOutputOffset + ", lastChunkSize=" +lastChunkSize ); + System.out.println("\nalgorithm=" + algorithm + ", mode=" + mode + ", paddingStr=" + paddingStr + + ", msgSize=" + msgSize + ", keySize=" + keySize + ", noReinit=" + noReinit + + ", checkOutput=" + checkOutput + ", encInputOffset=" + encInputOffset + ", encOutputOffset=" + + encOutputOffset + ", decOutputOffset=" + decOutputOffset + ", lastChunkSize=" +lastChunkSize ); if (encInputOffset % ALIGN != 0 || encOutputOffset % ALIGN != 0 || decOutputOffset % ALIGN !=0 ) testingMisalignment = true; @@ -101,22 +104,24 @@ cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); + // CBC init if (mode.equals("CBC")) { - int ivLen = (algorithm.equals("AES") ? 16 : algorithm.equals("DES") ? 8 : 0); - IvParameterSpec initVector = new IvParameterSpec(new byte[ivLen]); + IvParameterSpec initVector = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, key, initVector); + algParams = cipher.getParameters(); + dCipher.init(Cipher.DECRYPT_MODE, key, initVector); + + // GCM init } else if (mode.equals("GCM")) { - iv = new byte[64]; - random.nextBytes(iv); - aad = new byte[5]; - random.nextBytes(aad); - gcm_init(); + gcm_init(true); + gcm_init(false); + + // ECB init } else { - algParams = cipher.getParameters(); cipher.init(Cipher.ENCRYPT_MODE, key, algParams); + dCipher.init(Cipher.DECRYPT_MODE, key, algParams); } - algParams = cipher.getParameters(); - dCipher.init(Cipher.DECRYPT_MODE, key, algParams); + if (threadId == 0) { childShowCipher(); } @@ -198,11 +203,18 @@ abstract void childShowCipher(); - void gcm_init() throws Exception { - tlen = 12; + void gcm_init(boolean encrypt) throws Exception { gcm_spec = new GCMParameterSpec(tlen * 8, iv); - cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); - cipher.init(Cipher.ENCRYPT_MODE, key, gcm_spec); - cipher.update(aad); + if (encrypt) { + // Get a new instance everytime because of reuse IV restrictions + cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); + cipher.init(Cipher.ENCRYPT_MODE, key, gcm_spec); + cipher.updateAAD(aad); + } else { + dCipher.init(Cipher.DECRYPT_MODE, key, gcm_spec); + dCipher.updateAAD(aad); + + + } } } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/compiler/codegen/7184394/TestAESDecode.java --- a/hotspot/test/compiler/codegen/7184394/TestAESDecode.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/compiler/codegen/7184394/TestAESDecode.java Wed Jul 05 20:43:22 2017 +0200 @@ -32,7 +32,11 @@ @Override public void run() { try { - if (!noReinit) dCipher.init(Cipher.DECRYPT_MODE, key, algParams); + if (mode.equals("GCM")) { + gcm_init(false); + } else if (!noReinit) { + dCipher.init(Cipher.DECRYPT_MODE, key, algParams); + } decode = new byte[decodeLength]; if (testingMisalignment) { int tempSize = dCipher.update(encode, encOutputOffset, (decodeMsgSize - lastChunkSize), decode, decOutputOffset); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/compiler/codegen/7184394/TestAESEncode.java --- a/hotspot/test/compiler/codegen/7184394/TestAESEncode.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/compiler/codegen/7184394/TestAESEncode.java Wed Jul 05 20:43:22 2017 +0200 @@ -33,7 +33,7 @@ public void run() { try { if (mode.equals("GCM")) { - gcm_init(); + gcm_init(true); } else if (!noReinit) { cipher.init(Cipher.ENCRYPT_MODE, key, algParams); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/CommandLine/PrintTouchedMethods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/CommandLine/PrintTouchedMethods.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8025692 + * @modules java.base/sun.misc + * java.management + * @library /testlibrary + * @compile TestLogTouchedMethods.java PrintTouchedMethods.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+LogTouchedMethods PrintTouchedMethods + */ + +import java.io.File; +import java.util.List; +import jdk.test.lib.*; + +public class PrintTouchedMethods { + + public static void main(String args[]) throws Exception { + String[] javaArgs1 = {"-XX:-UnlockDiagnosticVMOptions", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"}; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1); + + // UnlockDiagnostic turned off, should fail + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Error: VM option 'LogTouchedMethods' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions."); + output.shouldContain("Error: Could not create the Java Virtual Machine."); + + String[] javaArgs2 = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"}; + pb = ProcessTools.createJavaProcessBuilder(javaArgs2); + output = new OutputAnalyzer(pb.start()); + // check order: + // 1 "# Method::print_touched_methods version 1" is the first in first line + // 2 should contain TestLogMethods.methodA:()V + // 3 should not contain TestLogMethods.methodB:()V + // Repeat above for another run with -Xint + List lines = output.asLines(); + + if (lines.size() < 1) { + throw new Exception("Empty output"); + } + + String first = lines.get(0); + if (!first.equals("# Method::print_touched_methods version 1")) { + throw new Exception("First line mismatch"); + } + + output.shouldContain("TestLogTouchedMethods.methodA:()V"); + output.shouldNotContain("TestLogTouchedMethods.methodB:()V"); + output.shouldHaveExitValue(0); + + String[] javaArgs3 = {"-XX:+UnlockDiagnosticVMOptions", "-Xint", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"}; + pb = ProcessTools.createJavaProcessBuilder(javaArgs3); + output = new OutputAnalyzer(pb.start()); + lines = output.asLines(); + + if (lines.size() < 1) { + throw new Exception("Empty output"); + } + + first = lines.get(0); + if (!first.equals("# Method::print_touched_methods version 1")) { + throw new Exception("First line mismatch"); + } + + output.shouldContain("TestLogTouchedMethods.methodA:()V"); + output.shouldNotContain("TestLogTouchedMethods.methodB:()V"); + output.shouldHaveExitValue(0); + + // Test jcmd PrintTouchedMethods VM.print_touched_methods + String pid = Integer.toString(ProcessTools.getProcessId()); + pb = new ProcessBuilder(); + pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.print_touched_methods"}); + output = new OutputAnalyzer(pb.start()); + try { + output.shouldContain("PrintTouchedMethods.main:([Ljava/lang/String;)V"); + } catch (RuntimeException e) { + output.shouldContain("Unknown diagnostic command"); + } + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/CommandLine/TestLogTouchedMethods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/CommandLine/TestLogTouchedMethods.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* used by PrintTouchedMethods.java */ +public class TestLogTouchedMethods { + public static void main(String[] args) { + new TestLogTouchedMethods().methodA(); + } + + public void methodA() {} // called + public void methodB() {} // this should not be called +} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java --- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java Wed Jul 05 20:43:22 2017 +0200 @@ -46,16 +46,8 @@ runTest("-XX:-CreateCoredumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped"); if (Platform.isWindows()) { - runTest("-XX:+CreateCoredumpOnCrash").shouldContain("Core dump will be written. Default location"); - // The old CreateMinidumpOnCrash option should still work - runTest("-XX:+CreateMinidumpOnCrash").shouldContain("Core dump will be written. Default location"); runTest("-XX:-CreateMinidumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped"); - - if (Platform.isDebugBuild()) { - // Make sure we create dumps on Windows debug builds by default - runTest("-Ddummyopt=false").shouldContain("Core dump will be written. Default location"); - } } else { runTest("-XX:+CreateCoredumpOnCrash").shouldNotContain("CreateCoredumpOnCrash turned off, no core file dumped"); } diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/ErrorHandling/TestOnError.java --- a/hotspot/test/runtime/ErrorHandling/TestOnError.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/runtime/ErrorHandling/TestOnError.java Wed Jul 05 20:43:22 2017 +0200 @@ -45,6 +45,7 @@ // Execute the VM so that a ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:-TransmitErrorReport", + "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=12", // trigger potential SEGV "-XX:OnError=echo " + msg, TestOnError.class.getName()); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/classFileParserBug/BadInitMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/BadInitMethod.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8130669 + * @summary VM prohibits methods with return values + * @compile ignoredClinit.jasm + * @compile badInit.jasm + * @run main/othervm -Xverify:all BadInitMethod + */ + +// Test that a non-void method does not cause an exception to be +// thrown. But that a non-void method causes a ClassFormatError +// exception. +public class BadInitMethod { + public static void main(String args[]) throws Throwable { + + System.out.println("Regression test for bug 8130669"); + try { + Class newClass = Class.forName("ignoredClinit"); + } catch (java.lang.Throwable e) { + throw new RuntimeException("Unexpected exception: " + e.getMessage()); + } + + try { + Class newClass = Class.forName("badInit"); + throw new RuntimeException("Expected ClassFormatError exception not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed"); + } + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/classFileParserBug/EnclosingMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/EnclosingMethod.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8130183 + * @summary For InnerClasses attribute, VM permits inner_class_info_index value of zero + * @compile badEnclMthd.jcod + * @run main/othervm -Xverify:all EnclosingMethod + */ + +// Test that an EnclosingMethod attribute with the value of 0 causes a ClassFormatError. +public class EnclosingMethod { + public static void main(String args[]) throws Throwable { + + System.out.println("Regression test for bug 8130183"); + try { + Class newClass = Class.forName("badEnclMthd"); + throw new RuntimeException("Expected ClassFormatError exception not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test EnclosingMethod passed"); + } + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/classFileParserBug/badEnclMthd.jcod --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/badEnclMthd.jcod Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// Source: badEnclMthd +class badEnclMthd { + 0xCAFEBABE; + 0; // minor version + 50; // major version + [] { // Constant Pool + ; // first element is empty + Utf8 "badEnclMthd"; // #1 + class #1; // #2 + Utf8 "java/lang/Object"; // #3 + class #3; // #4 + Utf8 "InnerClasses"; // #5 + Utf8 "badEnclMthd"; // #6 + class #6; // #7 + Utf8 "badEnclMthd"; // #8 + class #8; // #9 + } // Constant Pool + 0x0001; // access public + #2;// this_cpx + #4;// super_cpx + [] { // interfaces + } // interfaces + [] { // fields + } // fields + [] { // methods + } // methods + [] { // attributes + Attr(#5) { // InnerClasses + [] { // InnerClasses + #0 #2 #6 1; // Bad inner_class_info_index of 0 !!! + #9 #0 #8 1; + } + } // end InnerClasses + ; + } // attributes +} // end class badEnclMthd diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/classFileParserBug/badInit.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/badInit.jasm Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +super public class badInit + version 52:0 +{ + + +// This method has a non-void signature. It should cause a +// ClassFormatError exception. +Method "":"(I)I" + stack 1 locals 2 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + iconst_4; + ireturn; +} + +public static Method main:"([Ljava/lang/String;)V" + stack 0 locals 1 +{ + return; +} + +} // end Class badInit diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// This class contains a method with signature: ()I. The JVM should +// not complain about this because methods named that have arguments +// and/or are not void should be ignored by the JVM. + +public class ignoredClinit version 51:0 +{ + + public static Method "":"()I" + stack 1 locals 1 + { + iconst_0; + ireturn; + } + +} // end Class ignoredClinit diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/runtime/memory/ReserveMemory.java --- a/hotspot/test/runtime/memory/ReserveMemory.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/runtime/memory/ReserveMemory.java Wed Jul 05 20:43:22 2017 +0200 @@ -60,6 +60,7 @@ "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-XX:-TransmitErrorReport", + "-XX:-CreateCoredumpOnCrash", "-Xmx32m", "ReserveMemory", "test"); diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/serviceability/hprof/cpu002.java --- a/hotspot/test/serviceability/hprof/cpu002.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8076421 - * @summary Test of hprof option crashes Zero - * @compile cpu002.java - * @run main/othervm -Xrunhprof:cpu=times,file=cpu002.hprof.out cpu002 - */ - -import java.io.*; - -public class cpu002 { - public static final int PASSED = 0; - public static final int FAILED = 2; - public static final int JCK_STATUS_BASE = 95; - - public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { - return PASSED; - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c hotspot/test/serviceability/sa/TestStackTrace.java --- a/hotspot/test/serviceability/sa/TestStackTrace.java Wed Jul 05 20:42:40 2017 +0200 +++ b/hotspot/test/serviceability/sa/TestStackTrace.java Wed Jul 05 20:43:22 2017 +0200 @@ -34,6 +34,7 @@ * @test * @library /../../test/lib/share/classes * @library /testlibrary + * @ignore 8129971 * @build jdk.test.lib.* * @build jdk.test.lib.apps.* * @run main TestStackTrace diff -r f4b5bcf49fa3 -r f55df5cfe11c jaxp/.hgtags --- a/jaxp/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/jaxp/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -316,3 +316,4 @@ a3200b88f259f904876b9ab13fd4c4ec2726f8ba jdk9-b71 81e85f3b6174314155991048767452a9931e12e2 jdk9-b72 be5efc34a43bdd982d1cbe11cb2f6d6a060dde60 jdk9-b73 +eadcb2b55cd1daf77625813aad0f6f3967b1528a jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/DTDDVFactory.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/DTDDVFactory.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/DTDDVFactory.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,13 +1,13 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2001, 2002,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 + * 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 * @@ -20,8 +20,10 @@ package com.sun.org.apache.xerces.internal.impl.dv; +import com.sun.org.apache.xerces.internal.impl.dv.dtd.DTDDVFactoryImpl; +import com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl; +import com.sun.org.apache.xerces.internal.utils.ObjectFactory; import java.util.Hashtable; -import com.sun.org.apache.xerces.internal.utils.ObjectFactory; /** * The factory to create and return DTD types. The implementation should @@ -35,7 +37,11 @@ */ public abstract class DTDDVFactory { - private static final String DEFAULT_FACTORY_CLASS = "com.sun.org.apache.xerces.internal.impl.dv.dtd.DTDDVFactoryImpl"; + private static final String DEFAULT_FACTORY_CLASS = + "com.sun.org.apache.xerces.internal.impl.dv.dtd.DTDDVFactoryImpl"; + + private static final String XML11_DATATYPE_VALIDATOR_FACTORY = + "com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl"; /** * Get an instance of the default DTDDVFactory implementation. @@ -58,9 +64,15 @@ */ public static final DTDDVFactory getInstance(String factoryClass) throws DVFactoryException { try { - // if the class name is not specified, use the default one - return (DTDDVFactory) - (ObjectFactory.newInstance(factoryClass, true)); + if (DEFAULT_FACTORY_CLASS.equals(factoryClass)) { + return new DTDDVFactoryImpl(); + } else if (XML11_DATATYPE_VALIDATOR_FACTORY.equals(factoryClass)) { + return new XML11DTDDVFactoryImpl(); + } else { + //fall back for compatibility + return (DTDDVFactory) + (ObjectFactory.newInstance(factoryClass, true)); + } } catch (ClassCastException e) { throw new DVFactoryException("DTD factory class " + factoryClass + " does not extend from DTDDVFactory."); diff -r f4b5bcf49fa3 -r f55df5cfe11c jaxws/.hgtags --- a/jaxws/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/jaxws/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -319,3 +319,4 @@ 61caeb7061bbf8cc74a767997e5d17cc00712629 jdk9-b71 1d87054e2d2f405c114f0061b97cbf8214bddf0a jdk9-b72 285939df908721cdb2b18a119638114306b8dca7 jdk9-b73 +6232472e51418757f7b2bf05332678ea78096e6b jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/.hgtags --- a/jdk/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -316,3 +316,4 @@ e47d3bfbc61accc3fbd372a674fdce2933b54f31 jdk9-b71 f376824d4940f45719d91838f3f6249f873440db jdk9-b72 1c8bca2ebba13948199de33a1b71e2d6f1c7a8a6 jdk9-b73 +6dd82d2e4a104f4d204b2890f33ef11ec3e3f8d0 jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,6 @@ private static final String LFN_SIG = "L" + LFN + ";"; private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V"; - private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; /** Name of its super class*/ private static final String superName = OBJ; @@ -571,7 +570,7 @@ mv.visitLdcInsn(constantPlaceholder(cls)); mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG, false); if (Object[].class.isAssignableFrom(cls)) mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); else if (PROFILE_LEVEL > 0) diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,7 +219,7 @@ if (convSpec == null) continue; MethodHandle fn; if (convSpec instanceof Class) { - fn = Lazy.MH_castReference.bindTo(convSpec); + fn = Lazy.MH_cast.bindTo(convSpec); } else { fn = (MethodHandle) convSpec; } @@ -239,7 +239,7 @@ if (convSpec == void.class) fn = null; else - fn = Lazy.MH_castReference.bindTo(convSpec); + fn = Lazy.MH_cast.bindTo(convSpec); } else { fn = (MethodHandle) convSpec; } @@ -302,7 +302,7 @@ Name conv; if (convSpec instanceof Class) { Class convClass = (Class) convSpec; - conv = new Name(Lazy.MH_castReference, convClass, names[INARG_BASE + i]); + conv = new Name(Lazy.MH_cast, convClass, names[INARG_BASE + i]); } else { MethodHandle fn = (MethodHandle) convSpec; conv = new Name(fn, names[INARG_BASE + i]); @@ -326,7 +326,7 @@ conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType()))); } else if (convSpec instanceof Class) { Class convClass = (Class) convSpec; - conv = new Name(Lazy.MH_castReference, convClass, names[OUT_CALL]); + conv = new Name(Lazy.MH_cast, convClass, names[OUT_CALL]); } else { MethodHandle fn = (MethodHandle) convSpec; if (fn.type().parameterCount() == 0) @@ -343,25 +343,6 @@ return SimpleMethodHandle.make(srcType, form); } - /** - * Identity function, with reference cast. - * @param t an arbitrary reference type - * @param x an arbitrary reference value - * @return the same value x - */ - @ForceInline - @SuppressWarnings("unchecked") - static T castReference(Class t, U x) { - // inlined Class.cast because we can't ForceInline it - if (x != null && !t.isInstance(x)) - throw newClassCastException(t, x); - return (T) x; - } - - private static ClassCastException newClassCastException(Class t, Object obj) { - return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); - } - static Object[] computeValueConversions(MethodType srcType, MethodType dstType, boolean strict, boolean monobox) { final int INARG_COUNT = srcType.parameterCount(); @@ -591,6 +572,7 @@ */ static class Lazy { private static final Class MHI = MethodHandleImpl.class; + private static final Class CLS = Class.class; private static final MethodHandle[] ARRAYS; private static final MethodHandle[] FILL_ARRAYS; @@ -600,7 +582,7 @@ static final NamedFunction NF_throwException; static final NamedFunction NF_profileBoolean; - static final MethodHandle MH_castReference; + static final MethodHandle MH_cast; static final MethodHandle MH_selectAlternative; static final MethodHandle MH_copyAsPrimitiveArray; static final MethodHandle MH_fillNewTypedArray; @@ -623,8 +605,8 @@ NF_throwException.resolve(); NF_profileBoolean.resolve(); - MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", - MethodType.methodType(Object.class, Class.class, Object.class)); + MH_cast = IMPL_LOOKUP.findVirtual(CLS, "cast", + MethodType.methodType(Object.class, Object.class)); MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class)); MH_arrayIdentity = IMPL_LOOKUP.findStatic(MHI, "identity", diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/java/security/CodeSource.java --- a/jdk/src/java.base/share/classes/java/security/CodeSource.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java Wed Jul 05 20:43:22 2017 +0200 @@ -339,7 +339,7 @@ * @param strict If true then a strict equality match is performed. * Otherwise a subset match is performed. */ - private boolean matchCerts(CodeSource that, boolean strict) + boolean matchCerts(CodeSource that, boolean strict) { boolean match; diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/java/security/SecureClassLoader.java --- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java Wed Jul 05 20:43:22 2017 +0200 @@ -25,9 +25,10 @@ package java.security; -import java.util.Map; +import java.net.URL; import java.util.ArrayList; -import java.net.URL; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -50,15 +51,15 @@ private final boolean initialized; /* - * Map that maps the CodeSource URL (as a String) to ProtectionDomain. - * We use a String instead of a CodeSource/URL as the key to avoid + * Map that maps the CodeSource to a ProtectionDomain. The key is a + * CodeSourceKey class that uses a String instead of a URL to avoid * potential expensive name service lookups. This does mean that URLs that * are equivalent after nameservice lookup will be placed in separate * ProtectionDomains; however during policy enforcement these URLs will be * canonicalized and resolved resulting in a consistent set of granted * permissions. */ - private final Map pdcache + private final Map pdcache = new ConcurrentHashMap<>(11); private static final Debug debug = Debug.getInstance("scl"); @@ -209,17 +210,14 @@ return null; } - // Use a String form of the URL as the key. It should behave in the - // same manner as the URL when compared for equality except that no - // nameservice lookup is done on the hostname (String comparison + // Use a CodeSourceKey object key. It should behave in the + // same manner as the CodeSource when compared for equality except + // that no nameservice lookup is done on the hostname (String comparison // only), and the fragment is not considered. - String key = cs.getLocationNoFragString(); - if (key == null) { - key = ""; - } + CodeSourceKey key = new CodeSourceKey(cs); return pdcache.computeIfAbsent(key, new Function<>() { @Override - public ProtectionDomain apply(String key /* not used */) { + public ProtectionDomain apply(CodeSourceKey key /* not used */) { PermissionCollection perms = SecureClassLoader.this.getPermissions(cs); ProtectionDomain pd = new ProtectionDomain( @@ -242,4 +240,37 @@ } } + private static class CodeSourceKey { + private final CodeSource cs; + + CodeSourceKey(CodeSource cs) { + this.cs = cs; + } + + @Override + public int hashCode() { + String locationNoFrag = cs.getLocationNoFragString(); + return locationNoFrag != null ? locationNoFrag.hashCode() : 0; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof CodeSourceKey)) { + return false; + } + + CodeSourceKey csk = (CodeSourceKey) obj; + + if (!Objects.equals(cs.getLocationNoFragString(), + csk.cs.getLocationNoFragString())) { + return false; + } + + return cs.matchCerts(csk.cs, true); + } + } } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java --- a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java Wed Jul 05 20:43:22 2017 +0200 @@ -29,6 +29,9 @@ import java.nio.file.attribute.FileTime; import java.util.Objects; import java.util.concurrent.TimeUnit; +import java.time.LocalDateTime; +import java.time.ZonedDateTime; +import java.time.ZoneId; import static java.util.zip.ZipConstants64.*; @@ -195,6 +198,85 @@ } /** + * Sets the last modification time of the entry in local date-time. + * + *

If the entry is output to a ZIP file or ZIP file formatted + * output stream the last modification time set by this method will + * be stored into the {@code date and time fields} of the zip file + * entry and encoded in standard {@code MS-DOS date and time format}. + * If the date-time set is out of the range of the standard {@code + * MS-DOS date and time format}, the time will also be stored into + * zip file entry's extended timestamp fields in {@code optional + * extra data} in UTC time. The {@link java.time.ZoneId#systemDefault() + * system default TimeZone} is used to convert the local date-time + * to UTC time. + * + *

{@code LocalDateTime} uses a precision of nanoseconds, whereas + * this class uses a precision of milliseconds. The conversion will + * truncate any excess precision information as though the amount in + * nanoseconds was subject to integer division by one million. + * + * @param time + * The last modification time of the entry in local date-time + * + * @see #getTimeLocal() + * @since 1.9 + */ + public void setTimeLocal(LocalDateTime time) { + int year = time.getYear() - 1980; + if (year < 0) { + this.xdostime = DOSTIME_BEFORE_1980; + } else { + this.xdostime = (year << 25 | + time.getMonthValue() << 21 | + time.getDayOfMonth() << 16 | + time.getHour() << 11 | + time.getMinute() << 5 | + time.getSecond() >> 1) + + ((long)(((time.getSecond() & 0x1) * 1000) + + time.getNano() / 1000_000) << 32); + } + if (xdostime != DOSTIME_BEFORE_1980 && year <= 0x7f) { + this.mtime = null; + } else { + this.mtime = FileTime.from( + ZonedDateTime.of(time, ZoneId.systemDefault()).toInstant()); + } + } + + /** + * Returns the last modification time of the entry in local date-time. + * + *

If the entry is read from a ZIP file or ZIP file formatted + * input stream, this is the last modification time from the zip + * file entry's {@code optional extra data} if the extended timestamp + * fields are present. Otherwise, the last modification time is read + * from entry's standard MS-DOS formatted {@code date and time fields}. + * + *

The {@link java.time.ZoneId#systemDefault() system default TimeZone} + * is used to convert the UTC time to local date-time. + * + * @return The last modification time of the entry in local date-time + * + * @see #setTimeLocal(LocalDateTime) + * @since 1.9 + */ + public LocalDateTime getTimeLocal() { + if (mtime != null) { + return LocalDateTime.ofInstant(mtime.toInstant(), ZoneId.systemDefault()); + } + int ms = (int)(xdostime >> 32); + return LocalDateTime.of((int)(((xdostime >> 25) & 0x7f) + 1980), + (int)((xdostime >> 21) & 0x0f), + (int)((xdostime >> 16) & 0x1f), + (int)((xdostime >> 11) & 0x1f), + (int)((xdostime >> 5) & 0x3f), + (int)((xdostime << 1) & 0x3e) + ms / 1000, + (ms % 1000) * 1000_000); + } + + + /** * Sets the last modification time of the entry. * *

When output to a ZIP file or ZIP file formatted output stream @@ -498,15 +580,15 @@ // flag its presence or absence. But if mtime is present // in LOC it must be present in CEN as well. if ((flag & 0x1) != 0 && (sz0 + 4) <= sz) { - mtime = unixTimeToFileTime(get32(extra, off + sz0)); + mtime = unixTimeToFileTime(get32S(extra, off + sz0)); sz0 += 4; } if ((flag & 0x2) != 0 && (sz0 + 4) <= sz) { - atime = unixTimeToFileTime(get32(extra, off + sz0)); + atime = unixTimeToFileTime(get32S(extra, off + sz0)); sz0 += 4; } if ((flag & 0x4) != 0 && (sz0 + 4) <= sz) { - ctime = unixTimeToFileTime(get32(extra, off + sz0)); + ctime = unixTimeToFileTime(get32S(extra, off + sz0)); sz0 += 4; } break; diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java --- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Jul 05 20:43:22 2017 +0200 @@ -99,9 +99,9 @@ if (year < 1980) { return ZipEntry.DOSTIME_BEFORE_1980; } - return (year - 1980) << 25 | (d.getMonth() + 1) << 21 | - d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 | - d.getSeconds() >> 1; + return ((year - 1980) << 25 | (d.getMonth() + 1) << 21 | + d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 | + d.getSeconds() >> 1) & 0xffffffffL; } /** @@ -144,4 +144,13 @@ public static final long get64(byte b[], int off) { return get32(b, off) | (get32(b, off+4) << 32); } + + /** + * Fetches signed 32-bit value from byte array at specified offset. + * The bytes are assumed to be in Intel (little-endian) byte order. + * + */ + public static final int get32S(byte b[], int off) { + return (get16(b, off) | (get16(b, off+2) << 16)); + } } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java Wed Jul 05 20:43:22 2017 +0200 @@ -112,7 +112,12 @@ @Override public byte[] getStringBytes(int offset) { - return getStringBytes(id, offset); + byte[] ret = getStringBytes(id, offset); + if (ret == null) { + throw new OutOfMemoryError("Error accessing array at offset " + + offset); + } + return ret; } @Override diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java Wed Jul 05 20:43:22 2017 +0200 @@ -355,7 +355,7 @@ try { return cloneDigest(finMD).digest(); } catch (Exception e) { - throw new Error("BAD"); + throw new Error("Error during hash calculation", e); } } } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.base/share/native/libjava/Image.c --- a/jdk/src/java.base/share/native/libjava/Image.c Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.base/share/native/libjava/Image.c Wed Jul 05 20:43:22 2017 +0200 @@ -104,6 +104,9 @@ size = strlen(data); // Allocate byte array. byteArray = (*env)->NewByteArray(env, (jsize) size); + if (byteArray == NULL) { + return NULL; + } // Get array base address. rawBytes = (*env)->GetByteArrayElements(env, byteArray, NULL); // Copy bytes from image string table. @@ -122,6 +125,9 @@ jlong* ret; attributes = (*env)->NewLongArray(env, JVM_ImageGetAttributesCount(env)); + if (attributes == NULL) { + return NULL; + } // Get base address for jlong array. rawAttributes = (*env)->GetLongArrayElements(env, attributes, NULL); ret = JVM_ImageGetAttributes(env, rawAttributes, id, offset); @@ -143,6 +149,9 @@ count = JVM_ImageGetAttributesCount(env); attributes = (*env)->NewLongArray(env, JVM_ImageGetAttributesCount(env)); + if (attributes == NULL) { + return NULL; + } // Get base address for jlong array. rawAttributes = (*env)->GetLongArrayElements(env, attributes, NULL); size = (*env)->GetArrayLength(env, utf8); @@ -165,6 +174,9 @@ length = JVM_ImageAttributeOffsetsLength(env, id); offsets = (*env)->NewIntArray(env, length); + if (offsets == NULL) { + return NULL; + } // Get base address of result. rawOffsets = (*env)->GetIntArrayElements(env, offsets, NULL); ret = JVM_ImageAttributeOffsets(env, rawOffsets, length, id); diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java Wed Jul 05 20:43:22 2017 +0200 @@ -75,10 +75,11 @@ } } - // XXX Can renew a ticket but not ask for a renewable renewed ticket - // See impl of Credentials.renew(). - if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) != - rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) { + // Reply to a renewable request should be renewable, but if request does + // not contain renewable, KDC is free to issue a renewable ticket (for + // example, if ticket_lifetime is too big). + if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) && + !rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) { throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/Krb5KeyExchangeService.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/Krb5KeyExchangeService.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/Krb5KeyExchangeService.java Wed Jul 05 20:43:22 2017 +0200 @@ -83,6 +83,12 @@ (PrivilegedExceptionAction) () -> Krb5Util.getServiceCreds( GSSCaller.CALLER_SSL_SERVER, null, acc)); + if (serviceCreds == null) { + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Kerberos serviceCreds not available"); + } + return null; + } if (debug != null && Debug.isOn("handshake")) { System.out.println("Using Kerberos creds"); } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/src/jdk.policytool/share/classes/sun/security/tools/policytool/PolicyTool.java --- a/jdk/src/jdk.policytool/share/classes/sun/security/tools/policytool/PolicyTool.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/src/jdk.policytool/share/classes/sun/security/tools/policytool/PolicyTool.java Wed Jul 05 20:43:22 2017 +0200 @@ -633,17 +633,16 @@ type.equals(PolicyParser.PrincipalEntry.REPLACE_NAME)) { return; } - Class PRIN = Class.forName("java.security.Principal"); Class pc = Class.forName(type, true, Thread.currentThread().getContextClassLoader()); - if (!PRIN.isAssignableFrom(pc)) { + if (!Principal.class.isAssignableFrom(pc)) { MessageFormat form = new MessageFormat(getMessage ("Illegal.Principal.Type.type")); Object[] source = {type}; throw new InstantiationException(form.format(source)); } - if (ToolDialog.X500_PRIN_CLASS.equals(pc.getName())) { + if (X500Principal.class.getName().equals(pc.getName())) { // PolicyParser checks validity of X500Principal name // - PolicyTool needs to as well so that it doesn't store // an invalid name that can't be read in later @@ -1563,14 +1562,6 @@ public static final int NEW = 2; public static final int OPEN = 3; - public static final String ALL_PERM_CLASS = - "java.security.AllPermission"; - public static final String FILE_PERM_CLASS = - "java.io.FilePermission"; - - public static final String X500_PRIN_CLASS = - "javax.security.auth.x500.X500Principal"; - /* popup menus */ public static final String PERM = PolicyTool.getMessage @@ -1752,11 +1743,11 @@ for (int i = 0; i < PERM_ARRAY.size(); i++) { Perm next = PERM_ARRAY.get(i); if (fullClassName) { - if (next.FULL_CLASS.equals(clazz)) { + if (next.getName().equals(clazz)) { return next; } } else { - if (next.CLASS.equals(clazz)) { + if (next.getSimpleName().equals(clazz)) { return next; } } @@ -1772,11 +1763,11 @@ for (int i = 0; i < PRIN_ARRAY.size(); i++) { Prin next = PRIN_ARRAY.get(i); if (fullClassName) { - if (next.FULL_CLASS.equals(clazz)) { + if (next.getName().equals(clazz)) { return next; } } else { - if (next.CLASS.equals(clazz)) { + if (next.getSimpleName().equals(clazz)) { return next; } } @@ -2170,7 +2161,7 @@ choice.getAccessibleContext().setAccessibleName(PRIN_TYPE); for (int i = 0; i < PRIN_ARRAY.size(); i++) { Prin next = PRIN_ARRAY.get(i); - choice.addItem(next.CLASS); + choice.addItem(next.getSimpleName()); } if (edit) { @@ -2180,7 +2171,7 @@ } else { Prin inputPrin = getPrin(editMe.getPrincipalClass(), true); if (inputPrin != null) { - choice.setSelectedItem(inputPrin.CLASS); + choice.setSelectedItem(inputPrin.getSimpleName()); } } } @@ -2286,7 +2277,7 @@ choice.getAccessibleContext().setAccessibleName(PERM); for (int i = 0; i < PERM_ARRAY.size(); i++) { Perm next = PERM_ARRAY.get(i); - choice.addItem(next.CLASS); + choice.addItem(next.getSimpleName()); } tw.addNewComponent(newTD, choice, PD_PERM_CHOICE, 0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.BOTH, @@ -2300,7 +2291,7 @@ if (edit) { Perm inputPerm = getPerm(editMe.permission, true); if (inputPerm != null) { - choice.setSelectedItem(inputPerm.CLASS); + choice.setSelectedItem(inputPerm.getSimpleName()); } } tw.addNewComponent(newTD, tf, PD_PERM_TEXTFIELD, @@ -2417,7 +2408,7 @@ "\t'" + pname + "' will be interpreted " + "as a key store alias.\n" + "\tThe final principal class will be " + - ToolDialog.X500_PRIN_CLASS + ".\n" + + X500Principal.class.getName() + ".\n" + "\tThe final principal name will be " + "determined by the following:\n" + "\n" + @@ -2452,7 +2443,7 @@ if (tf.getText().trim().equals("") == false) name = new String(tf.getText().trim()); if (permission.equals("") || - (!permission.equals(ALL_PERM_CLASS) && name == null)) { + (!permission.equals(AllPermission.class.getName()) && name == null)) { throw new InvalidParameterException(PolicyTool.getMessage ("Permission.and.Target.Name.must.have.a.value")); } @@ -2467,7 +2458,8 @@ // \\server\share 0, legal // \\\\server\share 2, illegal - if (permission.equals(FILE_PERM_CLASS) && name.lastIndexOf("\\\\") > 0) { + if (permission.equals(FilePermission.class.getName()) + && name.lastIndexOf("\\\\") > 0) { char result = tw.displayYesNoDialog(this, PolicyTool.getMessage("Warning"), PolicyTool.getMessage( @@ -3645,7 +3637,7 @@ if (prinField.getText() != null && prinField.getText().length() > 0) { Prin inputPrin = ToolDialog.getPrin(prinField.getText(), true); - prin.setSelectedItem(inputPrin.CLASS); + prin.setSelectedItem(inputPrin.getSimpleName()); } return; } @@ -3660,7 +3652,7 @@ // set of names and actions Prin inputPrin = ToolDialog.getPrin((String)e.getItem(), false); if (inputPrin != null) { - prinField.setText(inputPrin.FULL_CLASS); + prinField.setText(inputPrin.getName()); } } } @@ -3711,7 +3703,7 @@ Perm inputPerm = ToolDialog.getPerm(permField.getText(), true); if (inputPerm != null) { - perms.setSelectedItem(inputPerm.CLASS); + perms.setSelectedItem(inputPerm.getSimpleName()); } } return; @@ -3732,7 +3724,7 @@ if (inputPerm == null) { permField.setText(""); } else { - permField.setText(inputPerm.FULL_CLASS); + permField.setText(inputPerm.getName()); } td.setPermissionNames(inputPerm, names, nameField); td.setPermissionActions(inputPerm, actions, actionsField); @@ -4082,26 +4074,30 @@ */ class Prin { - public final String CLASS; - public final String FULL_CLASS; - - public Prin(String clazz, String fullClass) { + final Class CLASS; + + Prin(Class clazz) { this.CLASS = clazz; - this.FULL_CLASS = fullClass; + } + + String getName() { + return CLASS.getName(); + } + + String getSimpleName() { + return CLASS.getSimpleName(); } } class KrbPrin extends Prin { - public KrbPrin() { - super("KerberosPrincipal", - "javax.security.auth.kerberos.KerberosPrincipal"); + KrbPrin() { + super(javax.security.auth.kerberos.KerberosPrincipal.class); } } class X500Prin extends Prin { - public X500Prin() { - super("X500Principal", - "javax.security.auth.x500.X500Principal"); + X500Prin() { + super(javax.security.auth.x500.X500Principal.class); } } @@ -4110,44 +4106,48 @@ */ class Perm { - public final String CLASS; - public final String FULL_CLASS; - public final String[] TARGETS; - public final String[] ACTIONS; - - public Perm(String clazz, String fullClass, + final Class CLASS; + final String[] TARGETS; + final String[] ACTIONS; + + Perm(Class clazz, String[] targets, String[] actions) { this.CLASS = clazz; - this.FULL_CLASS = fullClass; this.TARGETS = targets; this.ACTIONS = actions; } + + String getName() { + return CLASS.getName(); + } + + String getSimpleName() { + return CLASS.getSimpleName(); + } } class AllPerm extends Perm { - public AllPerm() { - super("AllPermission", "java.security.AllPermission", null, null); + AllPerm() { + super(java.security.AllPermission.class, null, null); } } class AudioPerm extends Perm { - public AudioPerm() { - super("AudioPermission", - "javax.sound.sampled.AudioPermission", - new String[] { + AudioPerm() { + super(javax.sound.sampled.AudioPermission.class, + new String[] { "play", "record" }, - null); + null); } } class AuthPerm extends Perm { - public AuthPerm() { - super("AuthPermission", - "javax.security.auth.AuthPermission", - new String[] { + AuthPerm() { + super(javax.security.auth.AuthPermission.class, + new String[] { "doAs", "doAsPrivileged", "getSubject", @@ -4165,15 +4165,14 @@ PolicyTool.getMessage("configuration.type") + ">", "refreshLoginConfiguration" }, - null); + null); } } class AWTPerm extends Perm { - public AWTPerm() { - super("AWTPermission", - "java.awt.AWTPermission", - new String[] { + AWTPerm() { + super(java.awt.AWTPermission.class, + new String[] { "accessClipboard", "accessEventQueue", "accessSystemTray", @@ -4187,30 +4186,28 @@ "showWindowWithoutWarningBanner", "toolkitModality", "watchMousePointer" - }, - null); + }, + null); } } class DelegationPerm extends Perm { - public DelegationPerm() { - super("DelegationPermission", - "javax.security.auth.kerberos.DelegationPermission", - new String[] { + DelegationPerm() { + super(javax.security.auth.kerberos.DelegationPermission.class, + new String[] { // allow user input }, - null); + null); } } class FilePerm extends Perm { - public FilePerm() { - super("FilePermission", - "java.io.FilePermission", - new String[] { + FilePerm() { + super(java.io.FilePermission.class, + new String[] { "<>" }, - new String[] { + new String[] { "read", "write", "delete", @@ -4220,64 +4217,59 @@ } class URLPerm extends Perm { - public URLPerm() { - super("URLPermission", - "java.net.URLPermission", - new String[] { - "<"+ PolicyTool.getMessage("url") + ">", - }, - new String[] { - "<" + PolicyTool.getMessage("method.list") + ">:<" - + PolicyTool.getMessage("request.headers.list") + ">", - }); + URLPerm() { + super(java.net.URLPermission.class, + new String[] { + "<"+ PolicyTool.getMessage("url") + ">", + }, + new String[] { + "<" + PolicyTool.getMessage("method.list") + ">:<" + + PolicyTool.getMessage("request.headers.list") + ">", + }); } } class InqSecContextPerm extends Perm { - public InqSecContextPerm() { - super("InquireSecContextPermission", - "com.sun.security.jgss.InquireSecContextPermission", - new String[] { + InqSecContextPerm() { + super(com.sun.security.jgss.InquireSecContextPermission.class, + new String[] { "KRB5_GET_SESSION_KEY", "KRB5_GET_TKT_FLAGS", "KRB5_GET_AUTHZ_DATA", "KRB5_GET_AUTHTIME" }, - null); + null); } } class LogPerm extends Perm { - public LogPerm() { - super("LoggingPermission", - "java.util.logging.LoggingPermission", - new String[] { + LogPerm() { + super(java.util.logging.LoggingPermission.class, + new String[] { "control" }, - null); + null); } } class MgmtPerm extends Perm { - public MgmtPerm() { - super("ManagementPermission", - "java.lang.management.ManagementPermission", - new String[] { + MgmtPerm() { + super(java.lang.management.ManagementPermission.class, + new String[] { "control", "monitor" }, - null); + null); } } class MBeanPerm extends Perm { - public MBeanPerm() { - super("MBeanPermission", - "javax.management.MBeanPermission", - new String[] { + MBeanPerm() { + super(javax.management.MBeanPermission.class, + new String[] { // allow user input }, - new String[] { + new String[] { "addNotificationListener", "getAttribute", "getClassLoader", @@ -4300,35 +4292,32 @@ } class MBeanSvrPerm extends Perm { - public MBeanSvrPerm() { - super("MBeanServerPermission", - "javax.management.MBeanServerPermission", - new String[] { + MBeanSvrPerm() { + super(javax.management.MBeanServerPermission.class, + new String[] { "createMBeanServer", "findMBeanServer", "newMBeanServer", "releaseMBeanServer" }, - null); + null); } } class MBeanTrustPerm extends Perm { - public MBeanTrustPerm() { - super("MBeanTrustPermission", - "javax.management.MBeanTrustPermission", - new String[] { + MBeanTrustPerm() { + super(javax.management.MBeanTrustPermission.class, + new String[] { "register" }, - null); + null); } } class NetPerm extends Perm { - public NetPerm() { - super("NetPermission", - "java.net.NetPermission", - new String[] { + NetPerm() { + super(java.net.NetPermission.class, + new String[] { "allowHttpTrace", "setDefaultAuthenticator", "requestPasswordAuthentication", @@ -4341,43 +4330,40 @@ "setResponseCache", "getResponseCache" }, - null); + null); } } class NetworkPerm extends Perm { - public NetworkPerm() { - super("NetworkPermission", - "jdk.net.NetworkPermission", - new String[] { + NetworkPerm() { + super(jdk.net.NetworkPermission.class, + new String[] { "setOption.SO_FLOW_SLA", "getOption.SO_FLOW_SLA" }, - null); + null); } } class PrivCredPerm extends Perm { - public PrivCredPerm() { - super("PrivateCredentialPermission", - "javax.security.auth.PrivateCredentialPermission", - new String[] { + PrivCredPerm() { + super(javax.security.auth.PrivateCredentialPermission.class, + new String[] { // allow user input }, - new String[] { + new String[] { "read" }); } } class PropPerm extends Perm { - public PropPerm() { - super("PropertyPermission", - "java.util.PropertyPermission", - new String[] { + PropPerm() { + super(java.util.PropertyPermission.class, + new String[] { // allow user input }, - new String[] { + new String[] { "read", "write" }); @@ -4385,21 +4371,19 @@ } class ReflectPerm extends Perm { - public ReflectPerm() { - super("ReflectPermission", - "java.lang.reflect.ReflectPermission", - new String[] { + ReflectPerm() { + super(java.lang.reflect.ReflectPermission.class, + new String[] { "suppressAccessChecks" }, - null); + null); } } class RuntimePerm extends Perm { - public RuntimePerm() { - super("RuntimePermission", - "java.lang.RuntimePermission", - new String[] { + RuntimePerm() { + super(java.lang.RuntimePermission.class, + new String[] { "createClassLoader", "getClassLoader", "setContextClassLoader", @@ -4432,15 +4416,14 @@ "usePolicy", // "inheritedChannel" }, - null); + null); } } class SecurityPerm extends Perm { - public SecurityPerm() { - super("SecurityPermission", - "java.security.SecurityPermission", - new String[] { + SecurityPerm() { + super(java.security.SecurityPermission.class, + new String[] { "createAccessControlContext", "getDomainCombiner", "getPolicy", @@ -4470,30 +4453,28 @@ //"getSignerPrivateKey", //"setSignerKeyPair" }, - null); + null); } } class SerialPerm extends Perm { - public SerialPerm() { - super("SerializablePermission", - "java.io.SerializablePermission", - new String[] { + SerialPerm() { + super(java.io.SerializablePermission.class, + new String[] { "enableSubclassImplementation", "enableSubstitution" }, - null); + null); } } class ServicePerm extends Perm { - public ServicePerm() { - super("ServicePermission", - "javax.security.auth.kerberos.ServicePermission", - new String[] { + ServicePerm() { + super(javax.security.auth.kerberos.ServicePermission.class, + new String[] { // allow user input }, - new String[] { + new String[] { "initiate", "accept" }); @@ -4501,13 +4482,12 @@ } class SocketPerm extends Perm { - public SocketPerm() { - super("SocketPermission", - "java.net.SocketPermission", - new String[] { + SocketPerm() { + super(java.net.SocketPermission.class, + new String[] { // allow user input }, - new String[] { + new String[] { "accept", "connect", "listen", @@ -4517,38 +4497,35 @@ } class SQLPerm extends Perm { - public SQLPerm() { - super("SQLPermission", - "java.sql.SQLPermission", - new String[] { + SQLPerm() { + super(java.sql.SQLPermission.class, + new String[] { "setLog", "callAbort", "setSyncFactory", "setNetworkTimeout", }, - null); + null); } } class SSLPerm extends Perm { - public SSLPerm() { - super("SSLPermission", - "javax.net.ssl.SSLPermission", - new String[] { + SSLPerm() { + super(javax.net.ssl.SSLPermission.class, + new String[] { "setHostnameVerifier", "getSSLSessionContext" }, - null); + null); } } class SubjDelegPerm extends Perm { - public SubjDelegPerm() { - super("SubjectDelegationPermission", - "javax.management.remote.SubjectDelegationPermission", - new String[] { + SubjDelegPerm() { + super(javax.management.remote.SubjectDelegationPermission.class, + new String[] { // allow user input }, - null); + null); } } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/ProblemList.txt Wed Jul 05 20:43:22 2017 +0200 @@ -154,17 +154,6 @@ ############################################################################ -# jdk_math - -############################################################################ - -# jdk_other - -# 6988950 -demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java generic-all - -############################################################################ - # jdk_net # 7148829 @@ -390,10 +379,4 @@ # 8064572 8060736 8062938 sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all -# 8079273 -demo/jvmti/hprof/CpuOldTest.java generic-all -demo/jvmti/hprof/CpuTimesTest.java generic-all -demo/jvmti/hprof/OptionsTest.java generic-all -demo/jvmti/hprof/StackMapTableTest.java generic-all - ############################################################################ diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/TEST.groups --- a/jdk/test/TEST.groups Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/TEST.groups Wed Jul 05 20:43:22 2017 +0200 @@ -42,7 +42,8 @@ :jdk_svc tier3 = \ - :jdk_rmi + :jdk_rmi \ + :jdk_beans ############################################################################### # diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/Context.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/DemoRun.java --- a/jdk/test/demo/jvmti/DemoRun.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/demo/jvmti/DemoRun.java Wed Jul 05 20:43:22 2017 +0200 @@ -122,7 +122,6 @@ String libprefix = os_name.contains("Windows")?"":"lib"; String libsuffix = os_name.contains("Windows")?".dll": os_name.contains("OS X")?".dylib":".so"; - boolean hprof = demo_name.equals("hprof"); String java = sdk_home + File.separator + "bin" + File.separator + "java"; @@ -155,22 +154,15 @@ cmdLine += (cmd[i++] = "-Xcheck:jni"); cmdLine += " "; cmdLine += (cmd[i++] = "-Xverify:all"); - if ( hprof ) { - /* Load hprof with -agentlib since it's part of jre */ - cmdLine += " "; - cmdLine += (cmd[i++] = "-agentlib:" + demo_name - + (demo_options.equals("")?"":("="+demo_options))); - } else { - String libname = sdk_home - + File.separator + "demo" - + File.separator + "jvmti" - + File.separator + demo_name - + File.separator + "lib" - + File.separator + libprefix + demo_name + libsuffix; - cmdLine += " "; - cmdLine += (cmd[i++] = "-agentpath:" + libname - + (demo_options.equals("")?"":("="+demo_options))); - } + String libname = sdk_home + + File.separator + "demo" + + File.separator + "jvmti" + + File.separator + demo_name + + File.separator + "lib" + + File.separator + libprefix + demo_name + libsuffix; + cmdLine += " "; + cmdLine += (cmd[i++] = "-agentpath:" + libname + + (demo_options.equals("") ? "" : ("=" + demo_options))); /* Add any special VM options */ for ( j = 0; j < nvm_options; j++ ) { cmdLine += " "; diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/HeapUser.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/Hello.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/gctest/BigHello.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/gctest/Gctest.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/heapTracker/HeapTrackerTest.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/heapViewer/HeapViewerTest.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/CpuOldTest.java --- a/jdk/test/demo/jvmti/hprof/CpuOldTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 6299047 - * @summary Test jvmti hprof - * - * @compile -g HelloWorld.java ../DemoRun.java - * @build CpuOldTest - * @run main CpuOldTest HelloWorld - */ - -public class CpuOldTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with cpu=old */ - hprof = new DemoRun("hprof", "cpu=old,file=cpuold.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/CpuSamplesTest.java --- a/jdk/test/demo/jvmti/hprof/CpuSamplesTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 - * @summary Test jvmti hprof - * - * @compile -g:lines HelloWorld.java ../DemoRun.java - * @build CpuSamplesTest - * @run main CpuSamplesTest HelloWorld - */ - -public class CpuSamplesTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with cpu=samples */ - hprof = new DemoRun("hprof", "cpu=samples,file=cpusamples.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/CpuTimesDefineClassTest.java --- a/jdk/test/demo/jvmti/hprof/CpuTimesDefineClassTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5097131 6299047 - * @summary Test jvmti hprof - * - * @compile -g HelloWorld.java DefineClass.java ../DemoRun.java - * @build CpuTimesDefineClassTest - * @run main CpuTimesDefineClassTest DefineClass - * - * - */ - -public class CpuTimesDefineClassTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with cpu=times */ - hprof = new DemoRun("hprof", "cpu=times,file=cputimedefineclass.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/CpuTimesTest.java --- a/jdk/test/demo/jvmti/hprof/CpuTimesTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 6299047 - * @summary Test jvmti hprof - * - * @compile -g HelloWorld.java ../DemoRun.java - * @build CpuTimesTest - * @run main CpuTimesTest HelloWorld - */ - -public class CpuTimesTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with cpu=times */ - hprof = new DemoRun("hprof", "cpu=times,file=cputimes.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/DefineClass.java --- a/jdk/test/demo/jvmti/hprof/DefineClass.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - - -/* Testcase that does a defineClass with a NULL name on HelloWorld.class */ - -import java.io.*; - -public class DefineClass extends ClassLoader { - public static void main(String args[]) { - DefineClass t = new DefineClass(); - t.run(args); - } - public void run(String args[]) { - Class n; - byte b[] = new byte[10000]; - int len = 0; - String cdir; - String cfile; - - /* Class is found here: */ - cdir = System.getProperty("test.classes", "."); - cfile = cdir + java.io.File.separator + "HelloWorld.class"; - - try { - /* Construct byte array with complete class image in it. */ - FileInputStream fis = new FileInputStream(cfile); - int nbytes; - do { - nbytes = fis.read(b, len, b.length-len); - if ( nbytes > 0 ) { - len += nbytes; - } - } while ( nbytes > 0 ); - } catch ( Throwable x ) { - System.err.println("Cannot find " + cfile); - x.printStackTrace(); - } - - /* Define the class with null for the name */ - n = defineClass(null, b, 0, len); - - /* Try to create an instance of it */ - try { - n.newInstance(); - } catch ( Throwable x ) { - x.printStackTrace(); - } - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/HeapAllTest.java --- a/jdk/test/demo/jvmti/hprof/HeapAllTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 6299047 - * @summary Test jvmti hprof - * - * @compile -g HelloWorld.java ../DemoRun.java - * @build HeapAllTest - * @run main HeapAllTest HelloWorld - */ - -public class HeapAllTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with heap=all */ - hprof = new DemoRun("hprof", "heap=all,file=heapall.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/HeapBinaryFormatTest.java --- a/jdk/test/demo/jvmti/hprof/HeapBinaryFormatTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 4965057 6313381 - * @summary Test jvmti hprof format=b - * - * @compile -g:source HelloWorld.java ../DemoRun.java - * @build HeapBinaryFormatTest - * @run main HeapBinaryFormatTest HelloWorld - */ - -public class HeapBinaryFormatTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent to get binary format dump */ - hprof = new DemoRun("hprof", "heap=dump,format=b,logflags=4,file=heapbinaryformat.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Try a variation */ - String vm_opts[] = new String[1]; - vm_opts[0] = "-Xmx2100m"; - /* Crashes on small Linux machines: (like fyi) - How can I tell how much real memory is on a machine? - hprof.runit(args[0], vm_opts); - */ - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/HeapDumpTest.java --- a/jdk/test/demo/jvmti/hprof/HeapDumpTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 6299047 - * @summary Test jvmti hprof - * - * @compile -g:source HelloWorld.java ../DemoRun.java - * @build HeapDumpTest - * @run main HeapDumpTest HelloWorld - */ - -public class HeapDumpTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with heap=dump */ - hprof = new DemoRun("hprof", "heap=dump,file=heapdump.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/HeapSitesTest.java --- a/jdk/test/demo/jvmti/hprof/HeapSitesTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 6299047 - * @summary Test jvmti hprof - * - * @compile -g:vars HelloWorld.java ../DemoRun.java - * @build HeapSitesTest - * @run main HeapSitesTest HelloWorld - */ - -public class HeapSitesTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with heap=sites */ - hprof = new DemoRun("hprof", "heap=sites,file=heapsites.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/HelloWorld.java --- a/jdk/test/demo/jvmti/hprof/HelloWorld.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - - -/* HelloWorld: - * - * Sample target application for HPROF tests - * - */ - -/* Just some classes that create a variety of references */ - -class AAAA { - public int AAAA_i; - public static int AAAA_si; - public Object AAAA_j; - public static Object AAAA_sj; - public long AAAA_k; - public static long AAAA_sk; -} - -interface IIII { - Object o = new Object(); -} - -class BBBB extends AAAA implements IIII { - public byte BBBB_ii; - public static byte BBBB_sii; - public Object BBBB_jj; - public static Object BBBB_sjj; - public short BBBB_kk; - public static short BBBB_skk; -} - -class REFS { - private static String s1 = new String("REFS_string1"); - private String is2 = new String("REFS_string2"); - private static String s3 = new String("REFS_string3"); - private static String s4 = new String("REFS_string4"); - private String is5 = new String("REFS_string5"); - - private AAAA aaaa; - private BBBB bbbb; - - public void test() { - aaaa = new AAAA(); - bbbb = new BBBB(); - - aaaa.AAAA_i = 1; - AAAA.AAAA_si = 2; - aaaa.AAAA_j = s1; - AAAA.AAAA_sj = is2; - aaaa.AAAA_k = 5; - AAAA.AAAA_sk = 6; - - bbbb.BBBB_ii = 11; - BBBB.BBBB_sii = 22; - bbbb.BBBB_jj = s3; - BBBB.BBBB_sjj = s4; - bbbb.BBBB_kk = 55; - BBBB.BBBB_skk = 66; - - bbbb.AAAA_i = 111; - bbbb.AAAA_j = is5; - bbbb.AAAA_k = 555; - } -} - -/* Fairly simple hello world program that does some exercises first. */ - -public class HelloWorld { - public static void main(String args[]) { - - /* References exercise. */ - REFS r = new REFS(); - r.test(); - - /* Use a generic type exercise. */ - java.util.List l = new java.util.ArrayList(); - String.format("%s", ""); - - /* Create a class that has lots of different bytecodes exercise. */ - /* (Don't run it!) */ - UseAllBytecodes x = new UseAllBytecodes(1,2); - - /* Just some code with branches exercise. */ - try { - if ( args.length == 0 ) { - System.out.println("No arguments passed in (doesn't matter)"); - } else { - System.out.println("Arguments passed in (doesn't matter)"); - } - } catch ( Throwable e ) { - System.out.println("ERROR: System.out.println() did a throw"); - } finally { - System.out.println("Hello, world!"); - } - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/MonitorTest.java --- a/jdk/test/demo/jvmti/hprof/MonitorTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5012882 - * @summary Test jvmti hprof - * - * @compile -g ../Context.java ../DemoRun.java - * @build MonitorTest - * @run main MonitorTest Context 25 200 1000 - */ - -/* To create monitor contention, increase the default configuration. - * Hprof seems to have historically not output anything unless certain - * limits have been reached on the total contention time. - */ - -public class MonitorTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - - /* Run JVMTI hprof agent with monitor=y */ - hprof = new DemoRun("hprof", "monitor=y,file=monitor.txt"); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/OptionsTest.java --- a/jdk/test/demo/jvmti/hprof/OptionsTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5083441 6299047 - * @summary Test jvmti hprof - * - * @compile -g:lines HelloWorld.java ../DemoRun.java - * @build OptionsTest - * @run main OptionsTest HelloWorld - */ - -import java.util.*; - -public class OptionsTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - List options = new LinkedList(); - - options.add("cpu=samples,depth=0,file=options0.txt"); - options.add("cpu=times,depth=0,file=options1.txt"); - options.add("cpu=old,depth=0,file=options2.txt"); - options.add("depth=0,file=options3.txt"); - - for(String option: options) { - /* Run JVMTI hprof agent with various options */ - hprof = new DemoRun("hprof", option); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed with " + option - + " - ERROR seen in output"); - } - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/StackMapTableTest.java --- a/jdk/test/demo/jvmti/hprof/StackMapTableTest.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 6266289 6299047 6855180 6855551 - * @summary Test jvmti hprof and java_crw_demo with StackMapTable attributes - * - * @compile ../DemoRun.java - * @compile -g:lines HelloWorld.java - * @build StackMapTableTest - * @run main StackMapTableTest HelloWorld - */ - -import java.util.*; - -public class StackMapTableTest { - - public static void main(String args[]) throws Exception { - DemoRun hprof; - List options = new LinkedList(); - - options.add("cpu=samples,file=stackmaptable0.txt"); - options.add("cpu=times,file=stackmaptable1.txt"); - options.add("heap=sites,file=stackmaptable2.txt"); - options.add("file=stackmaptable3.txt"); - - for(String option: options) { - /* Run JVMTI hprof agent with various options */ - hprof = new DemoRun("hprof", option); - hprof.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (hprof.output_contains("ERROR")) { - throw new RuntimeException("Test failed with " + option - + " - ERROR seen in output"); - } - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/hprof/UseAllBytecodes.java --- a/jdk/test/demo/jvmti/hprof/UseAllBytecodes.java Wed Jul 05 20:42:40 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,309 +0,0 @@ -/* - * Copyright (c) 1996, 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. - */ -/* - A simple Java class definition that helps self-test the runtime - interpreter. Used for getfield/putfield, invoke* opcodes and - their _quick variants. - - See src/share/java/runtime/selftest.c for details of the test - environment. -*/ - -/* Used to be sun/misc/SelfTest.java */ - -interface UseAllBytecodesInterface -{ - public void test_an_interface(int p1); -} - -public class UseAllBytecodes implements UseAllBytecodesInterface -{ - public int i1, i2; - public float f1, f2; - public double d1, d2; - public long l1, l2; - - public static int si1, si2; - public static float sf1, sf2; - public static double sd1, sd2; - public static long sl1, sl2; - - public UseAllBytecodesInterface interfaceObject; - - public int multi[][][]; - - public UseAllBytecodes() - { - /* This constructor is not intended to ever be run. It is here - to force CONSTANT_Methodref constants into the CP */ - set_i1(11); - set_i2(22); - set_f1(1.1f); - set_f2(2.2f); - set_d1(1.0); - set_d2(2.0); - set_l1(3); - set_l2(4); - - set_si1(33); - set_si2(44); - set_sf1(3.3f); - set_sf2(4.4f); - set_sd1(3.0); - set_sd2(4.0); - set_sl1(5); - set_sl2(6); - - test_areturn(); - test_athrow1(); - test_athrow2(); - test_athrow3(); - test_athrow4(); - - /* This puts a CONSTANT_InterfaceMethodref into the CP */ - interfaceObject.test_an_interface(1234); - - /* This creates an array and puts it into the CP */ - multi = new int[2][3][4]; - } - - public UseAllBytecodes(int p1) - { - i1 = p1; - i2 = 12345678; /* This puts a CONSTANT_Integer into the CP */ - d1 = (double) p1; - d2 = 1.2e234; /* This puts a CONSTANT_Double into the CP */ - } - - public UseAllBytecodes(int p1, int p2) - { - i1 = p1; - i2 = p2; - } - - /* These methods should return something other than their - arguments, so the self test can easily determine that - the correct value was returned. */ - public int set_i1(int p1) - { - i1 = p1; - return i1 + 1; - } - - public int set_i2(int p2) - { - i2 = p2; - return i2 + 1; - } - - public float set_f1(float p1) - { - f1 = p1; - return f1 + 1.0e34f; - } - - public float set_f2(float p2) - { - f2 = p2; - return f2 + 1.0e34f; - } - - public double set_d1(double p1) - { - d1 = p1; - return d1 + 1.0e234; - } - - public double set_d2(double p2) - { - d2 = p2; - return d2 + 1.0e234; - } - - public long set_l1(long p1) - { - l1 = p1; - return l1 + 1; - } - - public long set_l2(long p2) - { - l2 = p2; - return l2 + 1; - } - - public static void set_si1(int p1) - { - si1 = p1; - } - - public static void set_si2(int p2) - { - si2 = p2; - } - - public static void set_sf1(float p1) - { - sf1 = p1; - } - - public static void set_sf2(float p2) - { - sf2 = p2; - } - - public static void set_sd1(double p1) - { - sd1 = p1; - } - - public static void set_sd2(double p2) - { - sd2 = p2; - } - - public static void set_sl1(long p1) - { - sl1 = p1; - } - - public static void set_sl2(long p2) - { - sl2 = p2; - } - - public UseAllBytecodes test_areturn() - { - return this; - } - - /* This method does the same thing as set_i1. - It is here to test the invokeinterface opcode. */ - public void test_an_interface(int p1) - { - i1 = p1; - } - - /* The following 10 methods test various permutations of - try-and-catch. */ - public static void test_athrow1() throws NullPointerException - { - try - { - si1 = -1; - throw new NullPointerException(); - } - catch (Exception e) - { - si1 = 1; - } - } - - public static void test_athrow2() - { - int i = 1; - try - { - si1 = -1; - test_athrow1(); - } - catch (Exception e) - { - // This should *not* catch the exception; - // should be caught in test_athrow1. - si1 = i + 1; - } - } - - public static void test_athrow3() - { - int i = 1; - try - { - // Ultimately throws NullPointerException - si1 = -1; - si2 = -1; - test_athrow5(); - } - catch (NullPointerException np) - { - si1 = i + 1; - } - catch (NoSuchMethodException e) - { - si2 = i + 1; - } - si1++; // total is 3 - } - - public static void test_athrow4() - { - int i = 2; - try - { - // Ultimately throws NoSuchMethodException - si1 = -1; - si2 = -1; - test_athrow7(); - } - catch (NullPointerException e) - { - si1 = i + 1; - } - catch (NoSuchMethodException nsm) - { - si2 = i + 1; - } - si2++; // total is 4 - } - - public static void test_throw_nosuchmethod() throws NoSuchMethodException - { - throw new NoSuchMethodException(); - } - - public static void test_throw_nullpointer() throws NullPointerException - { - throw new NullPointerException(); - } - - public static void test_athrow5() throws NullPointerException, NoSuchMethodException - { - test_athrow6(); - } - - public static void test_athrow6() throws NullPointerException, NoSuchMethodException - { - test_throw_nullpointer(); - } - - public static void test_athrow7() throws NullPointerException, NoSuchMethodException - { - test_athrow8(); - } - - public static void test_athrow8() throws NullPointerException, NoSuchMethodException - { - test_throw_nosuchmethod(); - } -} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/minst/MinstExample.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/minst/MinstTest.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/versionCheck/FailsWhenJvmtiVersionDiffers.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/demo/jvmti/waiters/WaitersTest.java diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java --- a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Jul 05 20:43:22 2017 +0200 @@ -168,6 +168,11 @@ try { returned = target.invokeWithArguments(args); } catch (Throwable ex) { + if (CodeCacheOverflowProcessor.isThrowableCausedByVME(ex)) { + // This error will be treated by CodeCacheOverflowProcessor + // to prevent the test from failing because of code cache overflow. + throw new Error(ex); + } testCase.assertCatch(ex); returned = ex; } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java --- a/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java Wed Jul 05 20:43:22 2017 +0200 @@ -123,7 +123,7 @@ public static void main(String[] args) throws Exception { test(0, 0, false); - test(50, 500, false); + test(50, 5000, false); test(500, 50, true); } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/security/SecureClassLoader/DefineClass.java --- a/jdk/test/java/security/SecureClassLoader/DefineClass.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/java/security/SecureClassLoader/DefineClass.java Wed Jul 05 20:43:22 2017 +0200 @@ -21,28 +21,44 @@ * questions. */ +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; import java.io.IOException; +import java.io.OutputStream; import java.net.URL; import java.security.CodeSource; +import java.security.Key; +import java.security.KeyStoreException; +import java.security.KeyStoreSpi; +import java.security.NoSuchAlgorithmException; import java.security.Permission; import java.security.Policy; import java.security.ProtectionDomain; +import java.security.Provider; import java.security.SecureClassLoader; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.URIParameter; import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.Collections; +import java.util.Date; +import java.util.Enumeration; import java.util.List; import java.util.PropertyPermission; /* * @test - * @bug 6826789 + * @bug 6826789 8131486 * @summary Make sure equivalent ProtectionDomains are granted the same * permissions when the CodeSource URLs are different but resolve * to the same ip address after name service resolution. - * @run main/othervm/java.security.policy=DefineClass.policy DefineClass + * @run main/othervm DefineClass */ public class DefineClass { @@ -53,42 +69,100 @@ new PropertyPermission("user.name", "read") }; - // Base64 encoded bytes of a simple class: "public class Foo {}" + // Base64 encoded bytes of simple class: "package foo; public class Foo {}" private final static String FOO_CLASS = + "yv66vgAAADMADQoAAwAKBwALBwAMAQAGPGluaXQ+AQADKClWAQAEQ29kZQEA" + + "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhGb28uamF2YQwABAAF" + + "AQAHZm9vL0ZvbwEAEGphdmEvbGFuZy9PYmplY3QAIQACAAMAAAAAAAEAAQAE" + + "AAUAAQAGAAAAHQABAAEAAAAFKrcAAbEAAAABAAcAAAAGAAEAAAABAAEACAAA" + + "AAIACQ=="; + + // Base64 encoded bytes of simple class: "package bar; public class Bar {}" + private final static String BAR_CLASS = + "yv66vgAAADMADQoAAwAKBwALBwAMAQAGPGluaXQ+AQADKClWAQAEQ29kZQEA" + + "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhCYXIuamF2YQwABAAF" + + "AQAHYmFyL0JhcgEAEGphdmEvbGFuZy9PYmplY3QAIQACAAMAAAAAAAEAAQAE" + + "AAUAAQAGAAAAHQABAAEAAAAFKrcAAbEAAAABAAcAAAAGAAEAAAABAAEACAAA" + + "AAIACQ=="; + + // Base64 encoded bytes of simple class: "package baz; public class Baz {}" + private final static String BAZ_CLASS = "yv66vgAAADQADQoAAwAKBwALBwAMAQAGPGluaXQ+AQADKClWAQAEQ29kZQEA" + - "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhGb28uamF2YQwABAAF" + - "AQADRm9vAQAQamF2YS9sYW5nL09iamVjdAAhAAIAAwAAAAAAAQABAAQABQAB" + - "AAYAAAAdAAEAAQAAAAUqtwABsQAAAAEABwAAAAYAAQAAAAEAAQAIAAAAAgAJ"; + "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhCYXouamF2YQwABAAF" + + "AQAHYmF6L0JhegEAEGphdmEvbGFuZy9PYmplY3QAIQACAAMAAAAAAAEAAQAE" + + "AAUAAQAGAAAAHQABAAEAAAAFKrcAAbEAAAABAAcAAAAGAAEAAAABAAEACAAA" + + "AAIACQ=="; - // Base64 encoded bytes of a simple class: "public class Bar {}" - private final static String BAR_CLASS = - "yv66vgAAADQADQoAAwAKBwALBwAMAQAGPGluaXQ+AQADKClWAQAEQ29kZQEA" + - "D0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAAhCYXIuamF2YQwABAAF" + - "AQADQmFyAQAQamF2YS9sYW5nL09iamVjdAAhAAIAAwAAAAAAAQABAAQABQAB" + - "AAYAAAAdAAEAAQAAAAUqtwABsQAAAAEABwAAAAYAAQAAAAEAAQAIAAAAAgAJ"; + private final static String BAZ_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIEFzCCA8OgAwIBAgIESpPf8TANBglghkgBZQMEAwIFADAOMQwwCgYDVQQDEwNG\n" + + "b28wHhcNMTUwNzE1MTY1ODM5WhcNMTUxMDEzMTY1ODM5WjAOMQwwCgYDVQQDEwNG\n" + + "b28wggNCMIICNQYHKoZIzjgEATCCAigCggEBAI95Ndm5qum/q+2Ies9JUbbzLsWe\n" + + "O683GOjqxJYfPv02BudDUanEGDM5uAnnwq4cU5unR1uF0BGtuLR5h3VJhGlcrA6P\n" + + "FLM2CCiiL/onEQo9YqmTRTQJoP5pbEZY+EvdIIGcNwmgEFexla3NACM9ulSEtikf\n" + + "nWSO+INEhneXnOwEtDSmrC516Zhd4j2wKS/BEYyf+p2BgeczjbeStzDXueNJWS9o\n" + + "CZhyFTkV6j1ri0ZTxjNFj4A7MqTC4PJykCVuTj+KOwg4ocRQ5OGMGimjfd9eoUPe\n" + + "S2b/BJA+1c8WI+FY1IfGCOl/IRzYHcojy244B2X4IuNCvkhMBXY5OWAc1mcCHQC6\n" + + "9pamhXj3397n+mfJd8eF7zKyM7rlgMC81WldAoIBABamXFggSFBwTnUCo5dXBA00\n" + + "2jo0eMFU1OSlwC0kLuBPluYeS9CQSr2sjzfuseCfMYLSPJBDy2QviABBYO35ygmz\n" + + "IHannDKmJ/JHPpGHm6LE50S9IIFUTLVbgCw2jR+oPtSJ6U4PoGiOMkKKXHjEeMaN\n" + + "BSe3HJo6uwsL4SxEaJY559POdNsQGmWqK4f2TGgm2z7HL0tVmYNLtO2wL3yQ6aSW\n" + + "06VdU1vr/EXU9hn2Pz3tu4c5JcLyJOB3MSltqIfsHkdI+H77X963VIQxayIy3uVT\n" + + "3a8CESsNHwLaMJcyJP4nrtqLnUspItm6i+Oe2eEDpjxSgQvGiLfi7UMW4e8X294D\n" + + "ggEFAAKCAQBsGeU8/STExzQsJ8kFM9xarA/2VAFMzyUpd3IQ2UGHQC5rEnGh/RiU\n" + + "T20y7a2hCpQ1f/qgLnY8hku9GRVY3z8WamBzWLzCAEAx67EsS58mf4o8R3sUbkH5\n" + + "/mRaZoNVSPUy+tXoLmTzIetU4W+JT8Rq4OcXXU9uo9TreeBehhVexS3vpVgQeUIn\n" + + "MmMma8WHpovIJQQlp4cyjalX7Beda/tqX/HPLkAS4TRqQAz7hFr3FqFrVMKFSGo4\n" + + "fTS06GGdQ4tw9c6NQLuQ9WF9BxYSwSk9yENQvKDZaBNarqPMnsh1Gi/QcKMRBVhM\n" + + "RT/9vb4QUi/pOowhhKCDBLgjY60QgX3HoyEwHzAdBgNVHQ4EFgQUa787CE+3ZNAb\n" + + "g1ql9yJVVrRCdx0wDQYJYIZIAWUDBAMCBQADPwAwPAIcCUkZIRrBlKdTzhKYBEOm\n" + + "E1i45MMum1RuHc28agIcfHQkkjBA4FfH5UMRgKpIyRR8V/dVboxDj4hKOA==\n" + + "-----END CERTIFICATE-----"; public static void main(String[] args) throws Exception { + Security.addProvider(new TestProvider()); + MySecureClassLoader scl = new MySecureClassLoader(); - Policy p = Policy.getPolicy(); + + File policyFile = new File(System.getProperty("test.src", "."), + "DefineClass.policy"); + Policy p = Policy.getInstance("JavaPolicy", + new URIParameter(policyFile.toURI())); + Policy.setPolicy(p); + + System.setSecurityManager(new SecurityManager()); ArrayList perms1 = getPermissions(scl, p, "http://localhost/", - "Foo", FOO_CLASS); + "foo.Foo", FOO_CLASS, + null); checkPerms(perms1, GRANTED_PERMS); ArrayList perms2 = getPermissions(scl, p, "http://127.0.0.1/", - "Bar", BAR_CLASS); + "bar.Bar", BAR_CLASS, + null); checkPerms(perms2, GRANTED_PERMS); assert(perms1.equals(perms2)); + + // check that class signed by baz is granted an additional permission + Certificate[] chain = new Certificate[] {getCert(BAZ_CERT)}; + ArrayList perms3 = getPermissions(scl, p, + "http://localhost/", + "baz.Baz", BAZ_CLASS, + chain); + List perms = new ArrayList<>(Arrays.asList(GRANTED_PERMS)); + perms.add(new PropertyPermission("user.dir", "read")); + checkPerms(perms3, perms.toArray(new Permission[0])); } // returns the permissions granted to the codebase URL private static ArrayList getPermissions(MySecureClassLoader scl, Policy p, String url, String className, - String classBytes) + String classBytes, + Certificate[] chain) throws IOException { - CodeSource cs = new CodeSource(new URL(url), (Certificate[])null); + CodeSource cs = new CodeSource(new URL(url), chain); Base64.Decoder bd = Base64.getDecoder(); byte[] bytes = bd.decode(classBytes); Class c = scl.defineMyClass(className, bytes, cs); @@ -105,10 +179,125 @@ } } + private static Certificate getCert(String base64Cert) throws Exception { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + InputStream is = new ByteArrayInputStream(base64Cert.getBytes("UTF-8")); + return cf.generateCertificate(is); + } + // A SecureClassLoader that allows the test to define its own classes private static class MySecureClassLoader extends SecureClassLoader { Class defineMyClass(String name, byte[] b, CodeSource cs) { return super.defineClass(name, b, 0, b.length, cs); } } + + private static class TestProvider extends Provider { + TestProvider() { + super("Test8131486", 0.0, "For testing only"); + putService(new Provider.Service(this, "KeyStore", "Test8131486", + "DefineClass$TestKeyStore", null, null)); + } + } + + /** + * A KeyStore containing a single certificate entry named "baz". + */ + public static class TestKeyStore extends KeyStoreSpi { + private final String baz = "baz"; + private final List aliases = Collections.singletonList(baz); + private final Certificate bazCert; + + public TestKeyStore() { + try { + this.bazCert = getCert(BAZ_CERT); + } catch (Exception e) { + throw new Error(); + } + } + + @Override + public Enumeration engineAliases() { + return Collections.enumeration(aliases); + } + + @Override + public boolean engineContainsAlias(String alias) { + return alias.equals(baz); + } + + @Override + public void engineDeleteEntry(String alias) throws KeyStoreException { + throw new KeyStoreException(); + } + + @Override + public Certificate engineGetCertificate(String alias) { + return alias.equals(baz) ? bazCert : null; + } + + @Override + public String engineGetCertificateAlias(Certificate cert) { + return cert.equals(bazCert) ? baz : null; + } + + @Override + public Certificate[] engineGetCertificateChain(String alias) { + return alias.equals(baz) ? new Certificate[] {bazCert} : null; + } + + @Override + public Date engineGetCreationDate(String alias) { + return alias.equals(baz) ? new Date() : null; + } + + @Override + public Key engineGetKey(String alias, char[] password) + throws NoSuchAlgorithmException, UnrecoverableKeyException { + return null; + } + + @Override + public boolean engineIsCertificateEntry(String alias) { + return alias.equals(baz); + } + + @Override + public boolean engineIsKeyEntry(String alias) { + return false; + } + + @Override + public void engineLoad(InputStream stream, char[] password) + throws IOException, NoSuchAlgorithmException, CertificateException { + } + + @Override + public void engineSetCertificateEntry(String alias, Certificate cert) + throws KeyStoreException { + throw new KeyStoreException(); + } + + @Override + public void engineSetKeyEntry(String alias, byte[] key, + Certificate[] chain) + throws KeyStoreException { + throw new KeyStoreException(); + } + + @Override + public void engineSetKeyEntry(String alias, Key key, char[] password, + Certificate[] chain) + throws KeyStoreException { + throw new KeyStoreException(); + } + + @Override + public int engineSize() { return 1; } + + @Override + public void engineStore(OutputStream stream, char[] password) + throws IOException, NoSuchAlgorithmException, CertificateException { + } + } } diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/security/SecureClassLoader/DefineClass.policy --- a/jdk/test/java/security/SecureClassLoader/DefineClass.policy Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/java/security/SecureClassLoader/DefineClass.policy Wed Jul 05 20:43:22 2017 +0200 @@ -1,7 +1,7 @@ +keystore "NONE", "Test8131486", "Test8131486"; + grant { - permission java.lang.RuntimePermission "createClassLoader"; permission java.lang.RuntimePermission "getProtectionDomain"; - permission java.security.SecurityPermission "getPolicy"; }; grant codebase "http://localhost/" { permission java.util.PropertyPermission "user.home", "read"; @@ -9,3 +9,6 @@ grant codebase "http://127.0.0.1/" { permission java.util.PropertyPermission "user.name", "read"; }; +grant codebase "http://localhost/", signedby "baz" { + permission java.util.PropertyPermission "user.dir", "read"; +}; diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java --- a/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java Wed Jul 05 20:43:22 2017 +0200 @@ -120,7 +120,8 @@ } }; - int ps = Runtime.getRuntime().availableProcessors(); + // Bound concurrency to avoid degenerate performance + int ps = Math.min(Runtime.getRuntime().availableProcessors(), 32); Stream runners = IntStream.range(0, ps) .mapToObj(i -> sr.get()) .map(CompletableFuture::runAsync); diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/util/zip/TestExtraTime.java --- a/jdk/test/java/util/zip/TestExtraTime.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/java/util/zip/TestExtraTime.java Wed Jul 05 20:43:22 2017 +0200 @@ -23,7 +23,7 @@ /** * @test - * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 + * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914 * @summary Test ZOS and ZIS timestamp in extra field correctly */ @@ -54,8 +54,12 @@ for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) { test(mtime, null, null, null, extra); + // ms-dos 1980 epoch problem test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra); + // negative epoch time + test(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra); + // non-default tz test(mtime, null, null, tz, extra); diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/java/util/zip/TestLocalTime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/zip/TestLocalTime.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8075526 + * @summary Test timestamp via ZipEntry.get/setTimeLocal() + */ + +import java.io.*; +import java.nio.file.*; +import java.time.*; +import java.util.*; +import java.util.zip.*; + +public class TestLocalTime { + private static TimeZone tz0 = TimeZone.getDefault(); + + public static void main(String[] args) throws Throwable{ + try { + LocalDateTime ldt = LocalDateTime.now(); + test(getBytes(ldt), ldt); // now + ldt = ldt.withYear(1968); test(getBytes(ldt), ldt); + ldt = ldt.withYear(1970); test(getBytes(ldt), ldt); + ldt = ldt.withYear(1982); test(getBytes(ldt), ldt); + ldt = ldt.withYear(2037); test(getBytes(ldt), ldt); + ldt = ldt.withYear(2100); test(getBytes(ldt), ldt); + ldt = ldt.withYear(2106); test(getBytes(ldt), ldt); + + TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); + // dos time does not support < 1980, have to use + // utc in mtime. + testWithTZ(tz, ldt.withYear(1982)); + testWithTZ(tz, ldt.withYear(2037)); + testWithTZ(tz, ldt.withYear(2100)); + testWithTZ(tz, ldt.withYear(2106)); + } finally { + TimeZone.setDefault(tz0); + } + } + + static byte[] getBytes(LocalDateTime mtime) throws Throwable { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ZipOutputStream zos = new ZipOutputStream(baos); + ZipEntry ze = new ZipEntry("TestLocalTime.java"); + ze.setTimeLocal(mtime); + check(ze, mtime); + + zos.putNextEntry(ze); + zos.write(new byte[] { 1, 2, 3, 4}); + zos.close(); + return baos.toByteArray(); + } + + static void testWithTZ(TimeZone tz, LocalDateTime ldt) throws Throwable { + TimeZone.setDefault(tz); + byte[] zbytes = getBytes(ldt); + TimeZone.setDefault(tz0); + test(zbytes, ldt); + } + + static void test(byte[] zbytes, LocalDateTime expected) throws Throwable { + System.out.printf("--------------------%nTesting: [%s]%n", expected); + // ZipInputStream + ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zbytes)); + ZipEntry ze = zis.getNextEntry(); + zis.close(); + check(ze, expected); + + // ZipFile + Path zpath = Paths.get(System.getProperty("test.dir", "."), + "TestLocalTime.zip"); + try { + Files.copy(new ByteArrayInputStream(zbytes), zpath); + ZipFile zf = new ZipFile(zpath.toFile()); + ze = zf.getEntry("TestLocalTime.java"); + check(ze, expected); + zf.close(); + } finally { + Files.deleteIfExists(zpath); + } + } + + static void check(ZipEntry ze, LocalDateTime expected) { + LocalDateTime ldt = ze.getTimeLocal(); + if (ldt.atOffset(ZoneOffset.UTC).toEpochSecond() >> 1 + != expected.atOffset(ZoneOffset.UTC).toEpochSecond() >> 1) { + throw new RuntimeException("Timestamp: storing mtime failed!"); + } + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/javax/net/ssl/TLS/TestJSSE.java --- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java Wed Jul 05 20:43:22 2017 +0200 @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it under @@ -72,7 +72,6 @@ * -DCLIENT_PROTOCOL=DEFAULT -Djdk.tls.client.protocols=TLSv1.2 * -DCIPHER=SSL_RSA_WITH_RC4_128_MD5 * TestJSSE javax.net.ssl.SSLHandshakeException - * @key intermittent * */ diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/management/HotspotRuntimeMBean/GetTotalSafepointTime.java --- a/jdk/test/sun/management/HotspotRuntimeMBean/GetTotalSafepointTime.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/sun/management/HotspotRuntimeMBean/GetTotalSafepointTime.java Wed Jul 05 20:43:22 2017 +0200 @@ -26,7 +26,7 @@ * @bug 4858522 * @modules java.management/sun.management * @summary Basic unit test of HotspotRuntimeMBean.getTotalSafepointTime() - * @author Steve Bohne + * @run main/othervm -XX:+UsePerfData GetTotalSafepointTime */ /* diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/BogusKDC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BogusKDC.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +/* + * @test + * @bug 4515853 8075297 + * @summary Checks that Kerberos client tries slave KDC + * if master KDC is not responding + * @run main/othervm BogusKDC + */ +public class BogusKDC { + + static final String TEST_SRC = System.getProperty("test.src", "."); + static final String HOST = "localhost"; + static final String NOT_EXISTING_HOST = "not.existing.host"; + static final String REALM = "TEST.REALM"; + static final String USER = "USER"; + static final String USER_PRINCIPAL = USER + "@" + REALM; + static final String USER_PASSWORD = "password"; + static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM; + static final String KRB5_CONF = "krb5.conf"; + static final int WRONG_KDC_PORT = 21; + + static final String KRB5_CONF_TEMPLATE = "" + + "[libdefaults]\n" + + "default_realm = TEST.REALM\n" + + "max_retries = 1\n" + + "\n" + + "[realms]\n" + + "TEST.REALM = {\n" + + " kdc = %s\n" + + " kdc = localhost:%d\n" + + "}"; + + public static void main(String[] args) throws LoginException, IOException { + Map principals = new HashMap<>(); + principals.put(USER_PRINCIPAL, USER_PASSWORD); + principals.put(KRBTGT_PRINCIPAL, null); + + System.setProperty("java.security.krb5.conf", KRB5_CONF); + + // start a local KDC + KDC kdc = KDC.startKDC(HOST, KRB5_CONF, REALM, principals, null, null); + + System.setProperty("java.security.auth.login.config", + TEST_SRC + File.separator + "refreshKrb5Config.jaas"); + + CallbackHandler handler = new Helper.UserPasswordHandler( + USER, USER_PASSWORD); + + // create a krb5 config with non-existing host for master KDC, + // and wrong port for slave KDC + try (PrintWriter w = new PrintWriter(new FileWriter(KRB5_CONF))) { + w.write(String.format(KRB5_CONF_TEMPLATE, + KDC.KDCNameService.NOT_EXISTING_HOST, WRONG_KDC_PORT)); + w.flush(); + } + + // login with not-refreshable config + try { + new LoginContext("NotRefreshable", handler).login(); + throw new RuntimeException("Expected exception not thrown"); + } catch (LoginException le) { + System.out.println("Expected login failure: " + le); + } + + // create a krb5 config with non-existing host for master KDC, + // but correct port for slave KDC + try (PrintWriter w = new PrintWriter(new FileWriter(KRB5_CONF))) { + w.write(String.format(KRB5_CONF_TEMPLATE, + KDC.KDCNameService.NOT_EXISTING_HOST, kdc.getPort())); + w.flush(); + } + + // login with not-refreshable config + try { + new LoginContext("NotRefreshable", handler).login(); + throw new RuntimeException("Expected exception not thrown"); + } catch (LoginException le) { + System.out.println("Expected login failure: " + le); + } + + // login with refreshable config + new LoginContext("Refreshable", handler).login(); + + System.out.println("Test passed"); + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/Helper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/Helper.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class Helper { + + static class UserPasswordHandler implements CallbackHandler { + + private final String name; + private final String password; + + UserPasswordHandler(String name, String password) { + this.name = name; + this.password = password; + } + + @Override + public void handle(Callback[] callbacks) + throws UnsupportedCallbackException { + for (Callback callback : callbacks) { + if (callback instanceof PasswordCallback) { + ((PasswordCallback) callback).setPassword( + password.toCharArray()); + } else if (callback instanceof NameCallback) { + ((NameCallback)callback).setName(name); + } else { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/KDC.java --- a/jdk/test/sun/security/krb5/auto/KDC.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/sun/security/krb5/auto/KDC.java Wed Jul 05 20:43:22 2017 +0200 @@ -28,6 +28,10 @@ import java.io.*; import java.lang.reflect.Method; import java.security.SecureRandom; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalUnit; import java.util.*; import java.util.concurrent.*; @@ -939,6 +943,13 @@ } else if (till.isZero()) { till = new KerberosTime( new Date().getTime() + 1000 * DEFAULT_LIFETIME); + } else if (till.greaterThan(new KerberosTime(Instant.now() + .plus(1, ChronoUnit.DAYS)))) { + // If till is more than 1 day later, make it renewable + till = new KerberosTime( + new Date().getTime() + 1000 * DEFAULT_LIFETIME); + body.kdcOptions.set(KDCOptions.RENEWABLE, true); + if (rtime == null) rtime = till; } if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) { rtime = new KerberosTime( @@ -1320,14 +1331,17 @@ } } - public static void startKDC(final String host, final String krbConfFileName, + public static KDC startKDC(final String host, final String krbConfFileName, final String realm, final Map principals, final String ktab, final KtabMode mode) { + KDC kdc; try { - KDC kdc = KDC.create(realm, host, 0, true); + kdc = KDC.create(realm, host, 0, true); kdc.setOption(KDC.Option.PREAUTH_REQUIRED, Boolean.FALSE); - KDC.saveConfig(krbConfFileName, kdc); + if (krbConfFileName != null) { + KDC.saveConfig(krbConfFileName, kdc); + } // Add principals if (principals != null) { @@ -1379,6 +1393,7 @@ throw new RuntimeException("KDC: unexpected exception", e); } + return kdc; } /** @@ -1428,13 +1443,20 @@ } public static class KDCNameService implements NameServiceDescriptor { + + public static String NOT_EXISTING_HOST = "not.existing.host"; + @Override public NameService createNameService() throws Exception { NameService ns = new NameService() { @Override public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException { - // Everything is localhost + // Everything is localhost except NOT_EXISTING_HOST + if (NOT_EXISTING_HOST.equals(host)) { + throw new UnknownHostException("Unknown host name: " + + NOT_EXISTING_HOST); + } return new InetAddress[]{ InetAddress.getByAddress(host, new byte[]{127,0,0,1}) }; diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/LongLife.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/LongLife.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8131051 + * @summary KDC might issue a renewable ticket even if not requested + * @compile -XDignore.symbol.file LongLife.java + * @run main/othervm LongLife + */ + +import sun.security.krb5.Config; + +public class LongLife { + + public static void main(String[] args) throws Exception { + + OneKDC kdc = new OneKDC(null).writeJAASConf(); + + // A lifetime 2d will make it renewable + KDC.saveConfig(OneKDC.KRB5_CONF, kdc, + "ticket_lifetime = 2d"); + Config.refresh(); + + Context.fromJAAS("client"); + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/OneKDC.java --- a/jdk/test/sun/security/krb5/auto/OneKDC.java Wed Jul 05 20:42:40 2017 +0200 +++ b/jdk/test/sun/security/krb5/auto/OneKDC.java Wed Jul 05 20:43:22 2017 +0200 @@ -95,7 +95,7 @@ * entries with names using existing OneKDC principals. * @throws java.lang.Exception if anything goes wrong */ - public void writeJAASConf() throws IOException { + public OneKDC writeJAASConf() throws IOException { System.setProperty("java.security.auth.login.config", JAAS_CONF); File f = new File(JAAS_CONF); FileOutputStream fos = new FileOutputStream(f); @@ -123,6 +123,7 @@ " isInitiator=false;\n};\n" ).getBytes()); fos.close(); + return this; } /** diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/RefreshKrb5Config.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/RefreshKrb5Config.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +/* + * @test + * @bug 4745056 8075297 + * @summary Checks if refreshKrb5Config is set to true for Krb5LoginModule, + * then configuration will be refreshed before login() method is called + * @run main/othervm RefreshKrb5Config + */ +public class RefreshKrb5Config { + + static final String TEST_SRC = System.getProperty("test.src", "."); + static final String HOST = "localhost"; + static final String NOT_EXISTING_HOST = "not.existing.host"; + static final String REALM = "TEST.REALM"; + static final String USER = "USER"; + static final String USER_PRINCIPAL = USER + "@" + REALM; + static final String USER_PASSWORD = "password"; + static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM; + static final String KRB5_CONF_FILENAME = "krb5.conf"; + + public static void main(String[] args) throws LoginException, IOException { + Map principals = new HashMap<>(); + principals.put(USER_PRINCIPAL, USER_PASSWORD); + principals.put(KRBTGT_PRINCIPAL, null); + + System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME); + + // start a local KDC, and save krb5 config + KDC kdc = KDC.startKDC(HOST, null, REALM, principals, null, null); + KDC.saveConfig(KRB5_CONF_FILENAME, kdc, "max_retries = 1"); + + System.setProperty("java.security.auth.login.config", + TEST_SRC + File.separator + "refreshKrb5Config.jaas"); + + CallbackHandler handler = new Helper.UserPasswordHandler( + USER, USER_PASSWORD); + + // set incorrect KDC + System.out.println("java.security.krb5.kdc = " + NOT_EXISTING_HOST); + System.setProperty("java.security.krb5.kdc", NOT_EXISTING_HOST); + System.out.println("java.security.krb5.realm = " + REALM); + System.setProperty("java.security.krb5.realm", REALM); + try { + new LoginContext("Refreshable", handler).login(); + throw new RuntimeException("Expected exception not thrown"); + } catch (LoginException le) { + System.out.println("Expected login failure: " + le); + } + + // reset properties + System.out.println("Reset java.security.krb5.kdc"); + System.clearProperty("java.security.krb5.kdc"); + System.out.println("Reset java.security.krb5.realm"); + System.clearProperty("java.security.krb5.realm"); + + // login with not-refreshable config + try { + new LoginContext("NotRefreshable", handler).login(); + throw new RuntimeException("Expected exception not thrown"); + } catch (LoginException le) { + System.out.println("Expected login failure: " + le); + } + + // login with refreshable config + new LoginContext("Refreshable", handler).login(); + + System.out.println("Test passed"); + } + +} diff -r f4b5bcf49fa3 -r f55df5cfe11c jdk/test/sun/security/krb5/auto/refreshKrb5Config.jaas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/refreshKrb5Config.jaas Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,11 @@ +Refreshable { + com.sun.security.auth.module.Krb5LoginModule required + useTicketCache=false + refreshKrb5Config=true; +}; + +NotRefreshable { + com.sun.security.auth.module.Krb5LoginModule required + useTicketCache=false + refreshKrb5Config=false; +}; diff -r f4b5bcf49fa3 -r f55df5cfe11c langtools/.hgtags --- a/langtools/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/langtools/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -316,3 +316,4 @@ dc35e315436d21eab68ef44909922fb3424917f3 jdk9-b71 832e51533706b633d37a77282ae94d016b95e649 jdk9-b72 1fccc38cd6f56cb2173195e317ba2784b484c2d1 jdk9-b73 +02681b7c4232ba5d43ccba794492db9502211ff0 jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java Wed Jul 05 20:42:40 2017 +0200 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java Wed Jul 05 20:43:22 2017 +0200 @@ -151,32 +151,57 @@ * directed graph in linear time. Works on TarjanNode. */ public static > List> tarjan(Iterable nodes) { - ListBuffer> cycles = new ListBuffer<>(); - ListBuffer stack = new ListBuffer<>(); + Tarjan tarjan = new Tarjan<>(); + return tarjan.findSCC(nodes); + } + //where + private static class Tarjan> { + + /** Unique node identifier. */ int index = 0; - for (N node: nodes) { - if (node.index == -1) { - index += tarjan(node, index, stack, cycles); + + /** List of SCCs found fso far. */ + ListBuffer> sccs = new ListBuffer<>(); + + /** Stack of all reacheable nodes from given root. */ + ListBuffer stack = new ListBuffer<>(); + + private List> findSCC(Iterable nodes) { + for (N node : nodes) { + if (node.index == -1) { + findSCC(node); + } + } + return sccs.toList(); + } + + private void findSCC(N v) { + visitNode(v); + for (N n: v.getAllDependencies()) { + if (n.index == -1) { + //it's the first time we see this node + findSCC(n); + v.lowlink = Math.min(v.lowlink, n.lowlink); + } else if (stack.contains(n)) { + //this node is already reachable from current root + v.lowlink = Math.min(v.lowlink, n.index); + } + } + if (v.lowlink == v.index) { + //v is the root of a SCC + addSCC(v); } } - return cycles.toList(); - } - private static > int tarjan(N v, int index, ListBuffer stack, ListBuffer> cycles) { - v.index = index; - v.lowlink = index; - index++; - stack.prepend(v); - v.active = true; - for (N n: v.getAllDependencies()) { - if (n.index == -1) { - tarjan(n, index, stack, cycles); - v.lowlink = Math.min(v.lowlink, n.lowlink); - } else if (stack.contains(n)) { - v.lowlink = Math.min(v.lowlink, n.index); - } + private void visitNode(N n) { + n.index = index; + n.lowlink = index; + index++; + stack.prepend(n); + n.active = true; } - if (v.lowlink == v.index) { + + private void addSCC(N v) { N n; ListBuffer cycle = new ListBuffer<>(); do { @@ -184,9 +209,8 @@ n.active = false; cycle.add(n); } while (n != v); - cycles.add(cycle.toList()); + sccs.add(cycle.toList()); } - return index; } /** diff -r f4b5bcf49fa3 -r f55df5cfe11c langtools/test/tools/javac/generics/inference/8130304/T8130304.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/8130304/T8130304.java Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8130304 + * @summary Inference: NodeNotFoundException thrown with deep generic method call chain + * @compile T8130304.java + */ +class T8130304 { + + void test() { + outer( + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner()); + } + + void outer(T... ts) { } + + T inner() { + return null; + } +} diff -r f4b5bcf49fa3 -r f55df5cfe11c make/jprt.properties --- a/make/jprt.properties Wed Jul 05 20:42:40 2017 +0200 +++ b/make/jprt.properties Wed Jul 05 20:43:22 2017 +0200 @@ -121,10 +121,11 @@ ${jprt.fastdebugOpen.build.configure.args} jprt.i586.productOpen.build.configure.args= \ ${my.i586.default.build.configure.args} \ - ${jprt.productOpen.build.configure.args}jprt.windows_i586.build.configure.args= \ - --with-devkit=$VS2013_HOME \ + ${jprt.productOpen.build.configure.args} +jprt.windows_i586.build.configure.args= \ + --with-devkit=$VS2013_HOME \ ${jprt.i586.build.configure.args} -jprt.windows_x64.build.configure.args= \ +jprt.windows_x64.build.configure.args= \ --with-devkit=$VS2013_HOME ######## diff -r f4b5bcf49fa3 -r f55df5cfe11c modules.xml --- a/modules.xml Wed Jul 05 20:42:40 2017 +0200 +++ b/modules.xml Wed Jul 05 20:43:22 2017 +0200 @@ -1777,6 +1777,11 @@ jdk.policytool java.base java.desktop + java.logging + java.management + java.security.jgss + java.sql + jdk.security.jgss jdk.rmic diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/.hgtags --- a/nashorn/.hgtags Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/.hgtags Wed Jul 05 20:43:22 2017 +0200 @@ -307,3 +307,4 @@ 7066af6e7b06f3c6ebf449c88fc1064d2181237a jdk9-b71 d017877b3b8cd39337f1bdc00d958f821433c4c3 jdk9-b72 548f1eb2c3c89e024ef3805f48ceed9de503588f jdk9-b73 +2e8bb16872d7b15dc0a4f8e45c6ad65f762c1b04 jdk9-b74 diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/make/build.xml --- a/nashorn/make/build.xml Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/make/build.xml Wed Jul 05 20:43:22 2017 +0200 @@ -48,7 +48,9 @@ - + + + @@ -484,7 +486,7 @@ - + @@ -514,7 +516,7 @@ - + @@ -542,7 +544,7 @@ - + @@ -561,7 +563,7 @@ - + @@ -585,7 +587,7 @@ - + @@ -604,7 +606,7 @@ - + - + @@ -746,7 +748,7 @@ - + @@ -758,7 +760,7 @@ - + diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Wed Jul 05 20:43:22 2017 +0200 @@ -783,12 +783,13 @@ // If this is a declared variable or a function parameter, delete always fails (except for globals). final String name = ident.getName(); final Symbol symbol = ident.getSymbol(); - final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); - if (failDelete && symbol.isThis()) { + if (symbol.isThis()) { + // Can't delete "this", ignore and return true return LiteralNode.newInstance(unaryNode, true).accept(this); } final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); + final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); if (!failDelete) { args.add(compilerConstantIdentifier(SCOPE)); @@ -798,6 +799,8 @@ if (failDelete) { request = Request.FAIL_DELETE; + } else if (symbol.isGlobal() && !symbol.isFunctionDeclaration()) { + request = Request.SLOW_DELETE; } } else if (rhs instanceof AccessNode) { final Expression base = ((AccessNode)rhs).getBase(); diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java Wed Jul 05 20:43:22 2017 +0200 @@ -56,6 +56,8 @@ REFERENCE_ERROR, /** Delete operator */ DELETE(TokenType.DELETE, Type.BOOLEAN, 1), + /** Delete operator for slow scopes */ + SLOW_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** Delete operator that always fails -- see Lower */ FAIL_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false), /** === operator with at least one object */ diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Jul 05 20:43:22 2017 +0200 @@ -27,6 +27,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.util.Collection; import java.util.List; /** @@ -72,11 +73,6 @@ } @Override - boolean isRecompilable() { - return false; - } - - @Override protected boolean needsCallee() { final boolean needsCallee = code.getFirst().needsCallee(); assert allNeedCallee(needsCallee); @@ -93,6 +89,20 @@ } @Override + CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { + assert isValidCallSite(callSiteType) : callSiteType; + + CompiledFunction best = null; + for (final CompiledFunction candidate: code) { + if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) { + best = candidate; + } + } + + return best; + } + + @Override MethodType getGenericType() { // We need to ask the code for its generic type. We can't just rely on this function data's arity, as it's not // actually correct for lots of built-ins. E.g. ECMAScript 5.1 section 15.5.3.2 prescribes that diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jul 05 20:43:22 2017 +0200 @@ -617,6 +617,7 @@ private CompiledFunction addCode(final MethodHandle target, final Map invalidatedProgramPoints, final MethodType callSiteType, final int fnFlags) { final CompiledFunction cfn = new CompiledFunction(target, this, invalidatedProgramPoints, callSiteType, fnFlags); + assert noDuplicateCode(cfn) : "duplicate code"; code.add(cfn); return cfn; } @@ -683,14 +684,17 @@ @Override synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { - CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden); + assert isValidCallSite(callSiteType) : callSiteType; + + CompiledFunction existingBest = pickFunction(callSiteType, false); + if (existingBest == null) { + existingBest = pickFunction(callSiteType, true); // try vararg last + } if (existingBest == null) { existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType); } assert existingBest != null; - //we are calling a vararg method with real args - boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType); //if the best one is an apply to call, it has to match the callsite exactly //or we need to regenerate @@ -699,27 +703,18 @@ if (best != null) { return best; } - varArgWithRealArgs = true; - } - if (varArgWithRealArgs) { // special case: we had an apply to call, but we failed to make it fit. // Try to generate a specialized one for this callsite. It may // be another apply to call specialization, or it may not, but whatever // it is, it is a specialization that is guaranteed to fit - final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false); - existingBest = addCode(fnInit, callSiteType); + existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, false), callSiteType); } return existingBest; } @Override - boolean isRecompilable() { - return true; - } - - @Override public boolean needsCallee() { return getFunctionFlag(FunctionNode.NEEDS_CALLEE); } @@ -827,6 +822,16 @@ return newFn; } + // Make sure code does not contain a compiled function with the same signature as compiledFunction + private boolean noDuplicateCode(final CompiledFunction compiledFunction) { + for (final CompiledFunction cf : code) { + if (cf.type().equals(compiledFunction.type())) { + return false; + } + } + return true; + } + private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); createLogger(); diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jul 05 20:43:22 2017 +0200 @@ -359,31 +359,13 @@ * scope is not known, but that might cause compilation of code that will need more deoptimization passes. * @return the best function for the specified call site type. */ - CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { - assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this) - assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function - - if (isRecompilable()) { - final CompiledFunction candidate = pickFunction(callSiteType, false); - if (candidate != null) { - return candidate; - } - return pickFunction(callSiteType, true); //try vararg last - } + abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden); - CompiledFunction best = null; - for (final CompiledFunction candidate: code) { - if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) { - best = candidate; - } - } - - return best; + boolean isValidCallSite(final MethodType callSiteType) { + return callSiteType.parameterCount() >= 2 && // Must have at least (callee, this) + callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class); // Callee must be assignable from script function } - - abstract boolean isRecompilable(); - CompiledFunction getGeneric(final ScriptObject runtimeScope) { return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS); } diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 05 20:42:40 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 05 20:43:22 2017 +0200 @@ -685,6 +685,33 @@ } /** + * ECMA 11.4.1 - delete operator, implementation for slow scopes + * + * This implementation of 'delete' walks the scope chain to find the scope that contains the + * property to be deleted, then invokes delete on it. + * + * @param obj top scope object + * @param property property to delete + * @param strict are we in strict mode + * + * @return true if property was successfully found and deleted + */ + public static boolean SLOW_DELETE(final Object obj, final Object property, final Object strict) { + if (obj instanceof ScriptObject) { + ScriptObject sobj = (ScriptObject) obj; + final String key = property.toString(); + while (sobj != null && sobj.isScope()) { + final FindProperty find = sobj.findProperty(key, false); + if (find != null) { + return sobj.delete(key, Boolean.TRUE.equals(strict)); + } + sobj = sobj.getProto(); + } + } + return DELETE(obj, property, strict); + } + + /** * ECMA 11.4.1 - delete operator, special case * * This is 'delete' that always fails. We have to check strict mode and throw error. diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/test/script/basic/JDK-8131340.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8131340.js Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8131340: Varargs function is recompiled each time it is linked + * + * @test + * @run + */ + +// This is an indirect test. If repeated calls were to cause recompilation +// this would trigger an assertion in RecompilableScriptFunctionData. + +function varargs() { + return arguments; +} + +varargs(1); +varargs(2); +varargs(3); +varargs(4); +varargs(5); +varargs(6); diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/test/script/basic/JDK-8131683.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8131683.js Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8131683: Delete fails over multiple scopes + * + * @test + * @run + */ + +a = 1; +b = 2; +c = 3; + +var A = 1; +var B = 2; +var C = 3; +function D() {} + +print((function() { + var x; // force creation of scope + (function() { x; })(); + return delete a; +})()); + +print((function() { + eval(""); + return delete b; +})()); + +print((function() { + return eval("delete c"); +})()); + +print((function() { + eval("d = 4"); + return eval("delete d"); +})()); + +print(typeof a); +print(typeof b); +print(typeof c); +print(typeof d); + +print((function() { + var x; // force creation of scope + (function() { x; })(); + return delete A; +})()); + +print((function() { + eval(""); + return delete B; +})()); + +print((function() { + return eval("delete C"); +})()); + +print((function() { + eval(""); + return delete D; +})()); + +print(typeof A); +print(typeof B); +print(typeof C); +print(typeof D); + diff -r f4b5bcf49fa3 -r f55df5cfe11c nashorn/test/script/basic/JDK-8131683.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8131683.js.EXPECTED Wed Jul 05 20:43:22 2017 +0200 @@ -0,0 +1,16 @@ +true +true +true +true +undefined +undefined +undefined +undefined +false +false +false +false +number +number +number +function diff -r f4b5bcf49fa3 -r f55df5cfe11c test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java --- a/test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java Wed Jul 05 20:42:40 2017 +0200 +++ b/test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java Wed Jul 05 20:43:22 2017 +0200 @@ -276,10 +276,8 @@ fakeClasses.clear(); weakReferenceClass = findClass("java.lang.ref.Reference"); - if (weakReferenceClass == null) { // JDK 1.1.x - weakReferenceClass = findClass("sun.misc.Ref"); - referentFieldIndex = 0; - } else { + referentFieldIndex = 0; + if (weakReferenceClass != null) { JavaField[] fields = weakReferenceClass.getFieldsForInstance(); for (int i = 0; i < fields.length; i++) { if ("referent".equals(fields[i].getName())) {