Merge
authorduke
Wed, 05 Jul 2017 20:43:09 +0200
changeset 31831 1f975d9fd5fe
parent 31830 1e145ba49d48 (current diff)
parent 31825 55e7eb625b01 (diff)
child 31835 3ca6df6cfef3
Merge
hotspot/test/serviceability/hprof/cpu002.java
jdk/test/demo/jvmti/hprof/CpuOldTest.java
jdk/test/demo/jvmti/hprof/CpuSamplesTest.java
jdk/test/demo/jvmti/hprof/CpuTimesDefineClassTest.java
jdk/test/demo/jvmti/hprof/CpuTimesTest.java
jdk/test/demo/jvmti/hprof/DefineClass.java
jdk/test/demo/jvmti/hprof/HeapAllTest.java
jdk/test/demo/jvmti/hprof/HeapBinaryFormatTest.java
jdk/test/demo/jvmti/hprof/HeapDumpTest.java
jdk/test/demo/jvmti/hprof/HeapSitesTest.java
jdk/test/demo/jvmti/hprof/HelloWorld.java
jdk/test/demo/jvmti/hprof/MonitorTest.java
jdk/test/demo/jvmti/hprof/OptionsTest.java
jdk/test/demo/jvmti/hprof/StackMapTableTest.java
jdk/test/demo/jvmti/hprof/UseAllBytecodes.java
--- a/.hgtags-top-repo	Thu Jul 23 15:28:32 2015 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 20:43:09 2017 +0200
@@ -316,3 +316,4 @@
 c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71
 8582c35016fb6211b373810b6b172feccf9c483b jdk9-b72
 4c2cbaae528bce970dabbb5676005d379357f4b6 jdk9-b73
+57f3134853ecdd4a3ee2d4d26f22ba981d653d79 jdk9-b74
--- a/corba/.hgtags	Thu Jul 23 15:28:32 2015 -0700
+++ b/corba/.hgtags	Wed Jul 05 20:43:09 2017 +0200
@@ -316,3 +316,4 @@
 cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71
 f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72
 29096b78d93b01a2f8882509cd40755e3d6b8cd9 jdk9-b73
+622fe934e351e89107edf3c667d6b57f543f58f1 jdk9-b74
--- a/hotspot/.hgignore	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/.hgignore	Wed Jul 05 20:43:09 2017 +0200
@@ -10,3 +10,4 @@
 .igv.log
 ^.hgtip
 .DS_Store
+\.class$
--- a/hotspot/.hgtags	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 20:43:09 2017 +0200
@@ -476,3 +476,4 @@
 07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71
 c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72
 e37d432868be0aa7cb5e0f3d7caff1e825d8ead3 jdk9-b73
+fff6b54e9770ac4c12c2fb4cab5aa7672affa4bd jdk9-b74
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Wed Jul 05 20:43:09 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);
 
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp	Wed Jul 05 20:43:09 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();
--- a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp	Wed Jul 05 20:43:09 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);
 }
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Wed Jul 05 20:43:09 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);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Wed Jul 05 20:43:09 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
   //
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/cpu/ppc/vm/ppc.ad	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Wed Jul 05 20:43:09 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 %{
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Wed Jul 05 20:43:09 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:
--- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp	Wed Jul 05 20:43:09 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.
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Jul 05 20:43:09 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.
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 20:43:09 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);
 
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Jul 05 20:43:09 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 ;
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Jul 05 20:43:09 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);
   }
 
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 20:43:09 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);
 
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jul 05 20:43:09 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
 
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Jul 05 20:43:09 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;
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Wed Jul 05 20:43:09 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;
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Wed Jul 05 20:43:09 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);
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 20:43:09 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;
-  }
 }
 
 
--- a/hotspot/src/share/tools/LogCompilation/Makefile	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/Makefile	Wed Jul 05 20:43:09 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
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java	Wed Jul 05 20:43:09 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);
 }
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java	Wed Jul 05 20:43:09 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<CallSite> 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<UncommonTrap> 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<CallSite>());
+            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<CallSite> calls) {
-        this.calls = calls;
+    public List<UncommonTrap> 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<UncommonTrap>();
+        }
+        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<CallSite> 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<CallSite> findCallSite2(CallSite site) {
         if (calls == null) {
             return null;
@@ -260,7 +347,7 @@
 
         for (CallSite c : calls) {
             if (c.matches(site)) {
-                ArrayDeque<CallSite> stack = new ArrayDeque<CallSite>();
+                ArrayDeque<CallSite> stack = new ArrayDeque<>();
                 stack.push(c);
                 return stack;
             } else {
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java	Wed Jul 05 20:43:09 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<Phase> phases = new ArrayList<Phase>(4);
+
+    /**
+     * The phases through which this compilation goes.
+     */
+    private ArrayList<Phase> 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<Phase>(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;
         }
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java	Wed Jul 05 20:43:09 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;
             }
 
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java	Wed Jul 05 20:43:09 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<LogEvent> defaultSort = LogParser.sortByStart;
+        Comparator<LogEvent> 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<LogEvent> events = LogParser.parse(args[index], cleanup);
+            ArrayList<LogEvent> 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<LogEvent> 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<String, Double> phaseTime = new LinkedHashMap<String, Double>(7);
-        LinkedHashMap<String, Integer> phaseNodes = new LinkedHashMap<String, Integer>(7);
+        // track time spent in compiler phases
+        LinkedHashMap<String, Double> phaseTime = new LinkedHashMap<>(7);
+        // track nodes created per phase
+        LinkedHashMap<String, Integer> 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<MethodBCIPair,MethodBCIPair> methods = new HashMap<>();
+        ArrayList<HashMap<MethodBCIPair,Object>> 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<LogEvent> events = LogParser.parse(args[index], false);
+            HashMap<MethodBCIPair,Object> 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<Object> l = new LinkedList<>();
+                            l.add(other);
+                            l.add(comp);
+                            compiles.put(key, l);
+                        } else {
+                            List<Object> l = (List<Object>) 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<MethodBCIPair,Object> 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<Object>) e).size();
+                    lastc = (Compilation) ((List<Object>) 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<LogEvent> events, PrintStream out) {
+        // map method names to a list of log events
+        LinkedHashMap<String, ArrayList<LogEvent>> traps = new LinkedHashMap<>();
+        // map compilation IDs to compilations
+        HashMap<Integer, Compilation> 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<LogEvent> 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<LogEvent> elist = traps.get(name);
+                if (elist == null) {
+                    elist = new ArrayList<LogEvent>();
+                    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<LogEvent> 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();
+        }
+    }
+
 }
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java	Wed Jul 05 20:43:09 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);
 }
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Wed Jul 05 20:43:09 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<String, String> typeMap;
+    /**
+     * Map internal array type descriptors to Java names.
+     */
+    static final HashMap<String, String> type2printableMap;
+
+    /**
+     * Map Java primitive type names to internal type descriptors.
+     */
+    static final HashMap<String, String> type2vmtypeMap;
+
     static {
-        typeMap = new HashMap<String, String>();
-        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<LogEvent> sortByStart = new Comparator<LogEvent>() {
 
         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<LogEvent> sortByNameAndStart = new Comparator<LogEvent>() {
 
         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<LogEvent> sortByElapsed = new Comparator<LogEvent>() {
 
         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> jvms = new ArrayList<Jvms>(1);
+        /**
+         * Track all locations from which this lock was eliminated.
+         */
+        ArrayList<Jvms> 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<LogEvent> events = new ArrayList<LogEvent>();
+    /**
+     * A list of log events. This is populated with the events found in the
+     * compilation log file during parsing.
+     */
+    private ArrayList<LogEvent> events = new ArrayList<>();
+
+    /**
+     * Map compilation log IDs to type names.
+     */
+    private HashMap<String, String> types = new HashMap<>();
 
-    private HashMap<String, String> types = new HashMap<String, String>();
-    private HashMap<String, Method> methods = new HashMap<String, Method>();
-    private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<String, NMethod>();
-    private HashMap<String, Compilation> compiles = new HashMap<String, Compilation>();
+    /**
+     * Map compilation log IDs to methods.
+     */
+    private HashMap<String, Method> methods = new HashMap<>();
+
+    /**
+     * Map compilation IDs ({@see #makeId()}) to newly created nmethods.
+     */
+    private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<>();
+
+    /**
+     * Map compilation task IDs {@see #makeId()}) to {@link Compilation}
+     * objects.
+     */
+    private HashMap<String, Compilation> compiles = new HashMap<>();
+
+    /**
+     * Track compilation failure reasons.
+     */
     private String failureReason;
-    private int bci;
-    private Stack<CallSite> scopes = new Stack<CallSite>();
+
+    /**
+     * 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<CallSite> 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<Phase> phaseStack = new Stack<Phase>();
+
+    /**
+     * Keep track of potentially nested compiler {@linkplain Phase phases}.
+     */
+    private Deque<Phase> 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<CallSite> 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<CallSite> 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<LogEvent> 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<LogEvent> 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.<ul>
+     * <li><b>phase:</b> record the beginning of a compilation phase, pushing
+     * it on the {@linkplain #phaseStack phase stack} and collecting
+     * information about the compiler graph.</li>
+     * <li><b>phase_done:</b> 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).</li>
+     * <li><b>task:</b> register the start of a new compilation.</li>
+     * <li><b>type:</b> register a type.</li>
+     * <li><b>bc:</b> note the current bytecode index and instruction name,
+     * updating {@link #current_bci} and {@link #current_bytecode}.</li>
+     * <li><b>klass:</b> register a type (class).</li>
+     * <li><b>method:</b> register a Java method.</li>
+     * <li><b>call:</b> process a call, populating {@link #site} with the
+     * appropriate data.</li>
+     * <li><b>regalloc:</b> record the register allocator's trip count in the
+     * {@linkplain #compile current compilation}.</li>
+     * <li><b>inline_fail:</b> record the reason for a failed inline
+     * operation.</li>
+     * <li><b>inline_success:</b> record a successful inlining operation,
+     * noting the success reason in the {@linkplain #site call site}.</li>
+     * <li><b>failure:</b> note a compilation failure, storing the reason
+     * description in {@link #failureReason}.</li>
+     * <li><b>task_done:</b> register the end of a compilation, recording time
+     * stamp and success information.</li>
+     * <li><b>make_not_entrant:</b> 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).</li>
+     * <li><b>uncommon_trap:</b> process an uncommon trap, setting the
+     * {@link #currentTrap} field.</li>
+     * <li><b>eliminate_lock:</b> record the start of a lock elimination,
+     * setting the {@link #currentLockElimination} event.</li>
+     * <li><b>late_inline:</b> 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()}.</li>
+     * <li><b>jvms:</b> 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.</li>
+     * <li><b>inline_id:</b> set the inline ID in the
+     * {@linkplain #site current call site}.</li>
+     * <li><b>nmethod:</b> record the creation of a new {@link NMethod} and
+     * store it in the {@link #nmethods} map.</li>
+     * <li><b>parse:</b> begin parsing a Java method's bytecode and
+     * transforming it into an initial compiler IR graph.</li>
+     * <li><b>parse_done:</b> finish parsing a Java method's bytecode.</li>
+     * </ul>
+     */
     @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<CallSite>();
-            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")) {
             // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
             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 <eliminate_allocation type='667'>,
@@ -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:
                     //   ...
                     //   <method id="813" holder="694" name="toString" return="695" flags="1" bytes="36" iicount="1"/>
                     //   <call method="813" instr="invokevirtual"/>
@@ -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.<ul>
+     * <li><b>parse:</b> finish transforming a Java method's bytecode
+     * instructions to an initial compiler IR graph.</li>
+     * <li><b>uncommon_trap:</b> record the end of processing an uncommon trap,
+     * resetting {@link #currentTrap}.</li>
+     * <li><b>eliminate_lock:</b> record the end of a lock elimination,
+     * resetting {@link #currentLockElimination}.</li>
+     * <li><b>late_inline:</b> 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.)</li>
+     * <li><b>task:</b> perform cleanup at the end of a compilation. Note that
+     * the explicit {@code task_done} event is handled in
+     * {@link #startElement()}.</li>
+     * </ul>
+     */
     @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<CallSite> thisCallScopes = new ArrayDeque<CallSite>();
-            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<CallSite> 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<CallSite> 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<CallSite> 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());
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java	Wed Jul 05 20:43:09 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 {
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java	Wed Jul 05 20:43:09 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();
+    }
 }
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java	Wed Jul 05 20:43:09 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();
     }
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java	Wed Jul 05 20:43:09 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.");
     }
 }
--- /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:09 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();
+    }
+}
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Wed Jul 05 20:43:09 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<String> jvmsMethods = new ArrayList<>();
+
+    private List<Integer> 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<UncommonTrap> 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 = "<unknown>";
+        }
     }
 
-    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;
-    }
 }
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 20:43:09 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());
 
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 20:43:09 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 "<init>" methods must return void
         if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) {
           return args_size;
         }
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 20:43:09 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;
 }
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 20:43:09 2017 +0200
@@ -2846,7 +2846,7 @@
   if (sig_stream.type() != T_VOID) {
     if (method_name == vmSymbols::object_initializer_name()) {
       // <init> method must have a void return type
-      /* Unreachable?  Class file parser verifies that methods with '<' have
+      /* Unreachable?  Class file parser verifies that <init> methods have
        * void return */
       verify_error(ErrorContext::bad_code(bci),
           "Return type must be void in <init> method");
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Jul 05 20:43:09 2017 +0200
@@ -501,8 +501,8 @@
   methodHandle method(thread, this->method());
   ResourceMark rm(thread);
 
-  // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
-  log->print(" compile_id='%d'", _compile_id);
+  // <task compiler='Cx' id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
+  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'
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp	Wed Jul 05 20:43:09 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());
 }
 
 
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Jul 05 20:43:09 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.");
 
   {
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Jul 05 20:43:09 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 {
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Wed Jul 05 20:43:09 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;
--- a/hotspot/src/share/vm/oops/markOop.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/oops/markOop.cpp	Wed Jul 05 20:43:09 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("??");
     }
--- a/hotspot/src/share/vm/oops/method.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Jul 05 20:43:09 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<Method*> because
+// the Method may be garbage collected. Let's roll our own hash table.
+class TouchedMethodRecord : CHeapObj<mtTracing> {
+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) {
--- a/hotspot/src/share/vm/oops/method.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Jul 05 20:43:09 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       ); }
--- a/hotspot/src/share/vm/oops/symbol.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/oops/symbol.hpp	Wed Jul 05 20:43:09 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");
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 20:43:09 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() )
--- a/hotspot/src/share/vm/opto/loopUnswitch.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopUnswitch.cpp	Wed Jul 05 20:43:09 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.
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 20:43:09 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);
 
--- a/hotspot/src/share/vm/opto/loopnode.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.hpp	Wed Jul 05 20:43:09 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; }
--- a/hotspot/src/share/vm/opto/superword.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 20:43:09 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---------------------------
--- a/hotspot/src/share/vm/opto/superword.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/opto/superword.hpp	Wed Jul 05 20:43:09 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; }
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 20:43:09 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) }
 };
 
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:43:09 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")                                   \
                                                                             \
--- a/hotspot/src/share/vm/runtime/java.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Wed Jul 05 20:43:09 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);
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/share/vm/runtime/objectMonitor.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp	Wed Jul 05 20:43:09 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;
--- a/hotspot/src/share/vm/runtime/objectMonitor.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp	Wed Jul 05 20:43:09 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
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jul 05 20:43:09 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);
     }
   }
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 20:43:09 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");
   }
--- a/hotspot/src/share/vm/runtime/vframe.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.cpp	Wed Jul 05 20:43:09 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 <no object reference available>", 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<MonitorInfo*>* 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();
         }
--- a/hotspot/src/share/vm/runtime/vframe.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.hpp	Wed Jul 05 20:43:09 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<MonitorInfo*>* 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); }
 
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Wed Jul 05 20:43:09 2017 +0200
@@ -101,6 +101,7 @@
   template(WhiteBoxOperation)                     \
   template(ClassLoaderStatsOperation)             \
   template(DumpHashtable)                         \
+  template(DumpTouchedMethods)                    \
   template(MarkActiveNMethods)                    \
   template(PrintCompileQueue)                     \
   template(PrintCodeList)                         \
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Jul 05 20:43:09 2017 +0200
@@ -74,6 +74,7 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(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;
+}
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Wed Jul 05 20:43:09 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:
--- a/hotspot/test/compiler/codegen/7184394/TestAESBase.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/compiler/codegen/7184394/TestAESBase.java	Wed Jul 05 20:43:09 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);
+
+
+    }
   }
 }
--- a/hotspot/test/compiler/codegen/7184394/TestAESDecode.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/compiler/codegen/7184394/TestAESDecode.java	Wed Jul 05 20:43:09 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);
--- a/hotspot/test/compiler/codegen/7184394/TestAESEncode.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/compiler/codegen/7184394/TestAESEncode.java	Wed Jul 05 20:43:09 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);
       }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/PrintTouchedMethods.java	Wed Jul 05 20:43:09 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<String> 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");
+      }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/TestLogTouchedMethods.java	Wed Jul 05 20:43:09 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
+}
--- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java	Wed Jul 05 20:43:09 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");
         }
--- a/hotspot/test/runtime/ErrorHandling/TestOnError.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/runtime/ErrorHandling/TestOnError.java	Wed Jul 05 20:43:09 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());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/BadInitMethod.java	Wed Jul 05 20:43:09 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 <clinit> methods with return values
+ * @compile ignoredClinit.jasm
+ * @compile badInit.jasm
+ * @run main/othervm -Xverify:all BadInitMethod
+ */
+
+// Test that a non-void <clinit> method does not cause an exception to be
+// thrown.  But that a non-void <init> 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");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/EnclosingMethod.java	Wed Jul 05 20:43:09 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");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/badEnclMthd.jcod	Wed Jul 05 20:43:09 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/badInit.jasm	Wed Jul 05 20:43:09 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 <init> method has a non-void signature.  It should cause a
+// ClassFormatError exception.
+Method "<init>":"(I)I"
+    stack 1 locals 2
+{
+    aload_0;
+    invokespecial    Method java/lang/Object."<init>":"()V";
+    iconst_4;
+    ireturn;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+    stack 0 locals 1
+{
+    return;
+}
+
+} // end Class badInit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm	Wed Jul 05 20:43:09 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 <clinit> method with signature: ()I.  The JVM should
+// not complain about this because methods named <clinit> that have arguments
+// and/or are not void should be ignored by the JVM.
+
+public class ignoredClinit version 51:0
+{
+
+    public static Method "<clinit>":"()I"
+    stack 1 locals 1
+    {
+        iconst_0;
+        ireturn;
+    }
+
+} // end Class ignoredClinit
--- a/hotspot/test/runtime/memory/ReserveMemory.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/runtime/memory/ReserveMemory.java	Wed Jul 05 20:43:09 2017 +0200
@@ -60,6 +60,7 @@
           "-XX:+UnlockDiagnosticVMOptions",
           "-XX:+WhiteBoxAPI",
           "-XX:-TransmitErrorReport",
+          "-XX:-CreateCoredumpOnCrash",
           "-Xmx32m",
           "ReserveMemory",
           "test");
--- a/hotspot/test/serviceability/hprof/cpu002.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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;
-    }
-}
--- a/hotspot/test/serviceability/sa/TestStackTrace.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java	Wed Jul 05 20:43:09 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
--- a/jdk/.hgtags	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/.hgtags	Wed Jul 05 20:43:09 2017 +0200
@@ -316,3 +316,4 @@
 e47d3bfbc61accc3fbd372a674fdce2933b54f31 jdk9-b71
 f376824d4940f45719d91838f3f6249f873440db jdk9-b72
 1c8bca2ebba13948199de33a1b71e2d6f1c7a8a6 jdk9-b73
+6dd82d2e4a104f4d204b2890f33ef11ec3e3f8d0 jdk9-b74
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed Jul 05 20:43:09 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)
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Jul 05 20:43:09 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,U> T castReference(Class<? extends T> 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",
--- a/jdk/src/java.base/share/classes/java/security/CodeSource.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java	Wed Jul 05 20:43:09 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;
 
--- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Wed Jul 05 20:43:09 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<String, ProtectionDomain> pdcache
+    private final Map<CodeSourceKey, ProtectionDomain> 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 = "<null>";
-        }
+        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);
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java	Wed Jul 05 20:43:09 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.
+     *
+     * <p> 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.
+     *
+     * <p> {@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.
+     *
+     * <p> 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}.
+     *
+     * <p> 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.
      *
      * <p> 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;
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java	Wed Jul 05 20:43:09 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));
+    }
 }
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java	Wed Jul 05 20:43:09 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
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java	Wed Jul 05 20:43:09 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);
         }
     }
 }
--- a/jdk/src/java.base/share/native/libjava/Image.c	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.base/share/native/libjava/Image.c	Wed Jul 05 20:43:09 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);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java	Wed Jul 05 20:43:09 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);
         }
 
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/Krb5KeyExchangeService.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/Krb5KeyExchangeService.java	Wed Jul 05 20:43:09 2017 +0200
@@ -83,6 +83,12 @@
                     (PrivilegedExceptionAction<ServiceCreds>)
                             () -> 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");
             }
--- a/jdk/src/jdk.policytool/share/classes/sun/security/tools/policytool/PolicyTool.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/src/jdk.policytool/share/classes/sun/security/tools/policytool/PolicyTool.java	Wed Jul 05 20:43:09 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<? extends Principal> CLASS;
+
+    Prin(Class<? extends Principal> 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<? extends Permission> CLASS;
+    final String[] TARGETS;
+    final String[] ACTIONS;
+
+    Perm(Class<? extends Permission> 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[]    {
                 "<<ALL FILES>>"
                 },
-        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);
     }
 }
--- a/jdk/test/ProblemList.txt	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 20:43:09 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
-
 ############################################################################
--- a/jdk/test/TEST.groups	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/TEST.groups	Wed Jul 05 20:43:09 2017 +0200
@@ -42,7 +42,8 @@
     :jdk_svc
 
 tier3 = \
-    :jdk_rmi
+    :jdk_rmi \
+    :jdk_beans
 
 ###############################################################################
 #
--- a/jdk/test/demo/jvmti/DemoRun.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/demo/jvmti/DemoRun.java	Wed Jul 05 20:43:09 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 += " ";
--- a/jdk/test/demo/jvmti/hprof/CpuOldTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/CpuSamplesTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/CpuTimesDefineClassTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/CpuTimesTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/DefineClass.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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();
-        }
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/HeapAllTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/HeapBinaryFormatTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/HeapDumpTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/HeapSitesTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/HelloWorld.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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<String> l = new java.util.ArrayList<String>();
-        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!");
-        }
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/MonitorTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/OptionsTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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<String> options = new LinkedList<String>();
-
-        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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/StackMapTableTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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<String> options = new LinkedList<String>();
-
-        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");
-    }
-}
--- a/jdk/test/demo/jvmti/hprof/UseAllBytecodes.java	Thu Jul 23 15:28:32 2015 -0700
+++ /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();
-        }
-}
--- a/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java	Wed Jul 05 20:43:09 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;
         }
--- a/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/AdaptServerSocket.java	Wed Jul 05 20:43:09 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);
     }
 
--- a/jdk/test/java/security/SecureClassLoader/DefineClass.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/java/security/SecureClassLoader/DefineClass.java	Wed Jul 05 20:43:09 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<Permission> perms1 = getPermissions(scl, p,
                                                       "http://localhost/",
-                                                      "Foo", FOO_CLASS);
+                                                      "foo.Foo", FOO_CLASS,
+                                                      null);
         checkPerms(perms1, GRANTED_PERMS);
         ArrayList<Permission> 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<Permission> perms3 = getPermissions(scl, p,
+                                                      "http://localhost/",
+                                                      "baz.Baz", BAZ_CLASS,
+                                                      chain);
+        List<Permission> 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<Permission> 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<String> 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<String> 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 {
+        }
+    }
 }
--- a/jdk/test/java/security/SecureClassLoader/DefineClass.policy	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/java/security/SecureClassLoader/DefineClass.policy	Wed Jul 05 20:43:09 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";
+};
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java	Wed Jul 05 20:43:09 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<CompletableFuture> runners = IntStream.range(0, ps)
                 .mapToObj(i -> sr.get())
                 .map(CompletableFuture::runAsync);
--- a/jdk/test/java/util/zip/TestExtraTime.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/java/util/zip/TestExtraTime.java	Wed Jul 05 20:43:09 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);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestLocalTime.java	Wed Jul 05 20:43:09 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!");
+        }
+    }
+}
--- a/jdk/test/javax/net/ssl/TLS/TestJSSE.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/javax/net/ssl/TLS/TestJSSE.java	Wed Jul 05 20:43:09 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
  *
  */
 
--- a/jdk/test/sun/management/HotspotRuntimeMBean/GetTotalSafepointTime.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/sun/management/HotspotRuntimeMBean/GetTotalSafepointTime.java	Wed Jul 05 20:43:09 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
  */
 
 /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/BogusKDC.java	Wed Jul 05 20:43:09 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<String, String> 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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/Helper.java	Wed Jul 05 20:43:09 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);
+                }
+            }
+        }
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 20:43:09 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<String, String> 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})
                     };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/LongLife.java	Wed Jul 05 20:43:09 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");
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/OneKDC.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/jdk/test/sun/security/krb5/auto/OneKDC.java	Wed Jul 05 20:43:09 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;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/RefreshKrb5Config.java	Wed Jul 05 20:43:09 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<String, String> 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");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/refreshKrb5Config.jaas	Wed Jul 05 20:43:09 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;
+};
--- a/make/jprt.properties	Thu Jul 23 15:28:32 2015 -0700
+++ b/make/jprt.properties	Wed Jul 05 20:43:09 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
 
 ########
--- a/modules.xml	Thu Jul 23 15:28:32 2015 -0700
+++ b/modules.xml	Wed Jul 05 20:43:09 2017 +0200
@@ -1777,6 +1777,11 @@
     <name>jdk.policytool</name>
     <depend>java.base</depend>
     <depend>java.desktop</depend>
+    <depend>java.logging</depend>
+    <depend>java.management</depend>
+    <depend>java.security.jgss</depend>
+    <depend>java.sql</depend>
+    <depend>jdk.security.jgss</depend>
   </module>
   <module>
     <name>jdk.rmic</name>
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java	Thu Jul 23 15:28:32 2015 -0700
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java	Wed Jul 05 20:43:09 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())) {