# HG changeset patch # User herrick # Date 1569889588 14400 # Node ID 18e27ee2276beae264b4db649c5241266bacae9b # Parent 7cd20dbeee362639b2d1948d53f1ff7570b57ca3# Parent cece7402158018330c3418e76a45d86c1c4b8b43 Merge diff -r 7cd20dbeee36 -r 18e27ee2276b .hgtags --- a/.hgtags Mon Sep 30 20:16:48 2019 -0400 +++ b/.hgtags Mon Sep 30 20:26:28 2019 -0400 @@ -588,3 +588,4 @@ cddef3bde924f3ff4f17f3d369280cf69d0450e5 jdk-14+14 9c250a7600e12bdb1e611835250af3204d4aa152 jdk-13-ga 778fc2dcbdaa8981e07e929a2cacef979c72261e jdk-14+15 +d29f0181ba424a95d881aba5eabf2e393abcc70f jdk-14+16 diff -r 7cd20dbeee36 -r 18e27ee2276b make/common/NativeCompilation.gmk --- a/make/common/NativeCompilation.gmk Mon Sep 30 20:16:48 2019 -0400 +++ b/make/common/NativeCompilation.gmk Mon Sep 30 20:26:28 2019 -0400 @@ -759,34 +759,6 @@ endif endif - # Create a rule to collect all the individual make dependency files into a - # single makefile. - $1_DEPS_FILE := $$($1_OBJECT_DIR)/$1.d - - $$($1_DEPS_FILE): $$($1_ALL_OBJS) - $(RM) $$@ - # CD into dir to reduce risk of hitting command length limits, which - # could otherwise happen if TOPDIR is a very long path. - $(CD) $$($1_OBJECT_DIR) && $(CAT) *.d > $$@.tmp - $(CD) $$($1_OBJECT_DIR) && $(CAT) *.d.targets | $(SORT) -u >> $$@.tmp - # After generating the file, which happens after all objects have been - # compiled, copy it to .old extension. On the next make invocation, this - # .old file will be included by make. - $(CP) $$@.tmp $$@.old - $(MV) $$@.tmp $$@ - - $1 += $$($1_DEPS_FILE) - - # The include must be on the .old file, which represents the state from the - # previous invocation of make. The file being included must not have a rule - # defined for it as otherwise make will think it has to run the rule before - # being able to include the file, which would be wrong since we specifically - # need the file as it was generated by a previous make invocation. - ifneq ($$(wildcard $$($1_DEPS_FILE).old), ) - $1_DEPS_FILE_LOADED := true - -include $$($1_DEPS_FILE).old - endif - # Now call SetupCompileNativeFile for each source file we are going to compile. $$(foreach file, $$($1_SRCS), \ $$(eval $$(call SetupCompileNativeFile, $1_$$(notdir $$(file)),\ @@ -849,6 +821,34 @@ endif endif + # Create a rule to collect all the individual make dependency files into a + # single makefile. + $1_DEPS_FILE := $$($1_OBJECT_DIR)/$1.d + + $$($1_DEPS_FILE): $$($1_ALL_OBJS) $$($1_RES) + $(RM) $$@ + # CD into dir to reduce risk of hitting command length limits, which + # could otherwise happen if TOPDIR is a very long path. + $(CD) $$($1_OBJECT_DIR) && $(CAT) *.d > $$@.tmp + $(CD) $$($1_OBJECT_DIR) && $(CAT) *.d.targets | $(SORT) -u >> $$@.tmp + # After generating the file, which happens after all objects have been + # compiled, copy it to .old extension. On the next make invocation, this + # .old file will be included by make. + $(CP) $$@.tmp $$@.old + $(MV) $$@.tmp $$@ + + $1 += $$($1_DEPS_FILE) + + # The include must be on the .old file, which represents the state from the + # previous invocation of make. The file being included must not have a rule + # defined for it as otherwise make will think it has to run the rule before + # being able to include the file, which would be wrong since we specifically + # need the file as it was generated by a previous make invocation. + ifneq ($$(wildcard $$($1_DEPS_FILE).old), ) + $1_DEPS_FILE_LOADED := true + -include $$($1_DEPS_FILE).old + endif + ifneq ($(DISABLE_MAPFILES), true) $1_REAL_MAPFILE := $$($1_MAPFILE) ifeq ($(call isTargetOs, windows), false) diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -211,9 +211,14 @@ if (borrow_reg) { // No free registers available. Make one useful. tmp = rscratch1; + if (tmp == dst) { + tmp = rscratch2; + } __ push(RegSet::of(tmp), sp); } + assert_different_registers(tmp, dst); + Label done; __ ldr(tmp, Address(dst, oopDesc::mark_offset_in_bytes())); __ eon(tmp, tmp, zr); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp --- a/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ //} if (r_2->is_Register() && (type == T_LONG || type == T_DOUBLE)) { opr = as_long_opr(reg); - } else if (type == T_OBJECT || type == T_ARRAY) { + } else if (is_reference_type(type)) { opr = as_oop_opr(reg); } else { opr = as_opr(reg); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1237,7 +1237,7 @@ } else { ShouldNotReachHere(); } - if (to_reg->type() == T_OBJECT || to_reg->type() == T_ARRAY) { + if (is_reference_type(to_reg->type())) { __ verify_oop(to_reg->as_register()); } } @@ -1253,7 +1253,7 @@ Register disp_reg = noreg; int disp_value = addr->disp(); bool needs_patching = (patch_code != lir_patch_none); - bool compress_oop = (type == T_ARRAY || type == T_OBJECT) && UseCompressedOops && !wide && + bool compress_oop = (is_reference_type(type)) && UseCompressedOops && !wide && CompressedOops::mode() != CompressedOops::UnscaledNarrowOop; bool load_disp = addr->index()->is_illegal() && !Assembler::is_simm16(disp_value); bool use_R29 = compress_oop && load_disp; // Avoid register conflict, also do null check before killing R29. @@ -1473,7 +1473,7 @@ } } else { assert(opr1->type() != T_ADDRESS && opr2->type() != T_ADDRESS, "currently unsupported"); - if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { + if (is_reference_type(opr1->type())) { // There are only equal/notequal comparisons on objects. assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "oops"); __ cmpd(BOOL_RESULT, opr1->as_register(), opr2->as_register()); @@ -2315,8 +2315,8 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { LP64_ONLY( __ extsw(op->len()->as_register(), op->len()->as_register()); ) if (UseSlowPath || - (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || - (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { + (!UseFastNewObjectArray && (is_reference_type(op->type()))) || + (!UseFastNewTypeArray && (!is_reference_type(op->type())))) { __ b(*op->stub()->entry()); } else { __ allocate_array(op->obj()->as_register(), diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017, SAP SE. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -648,7 +648,7 @@ __ membar_release(); } - if (type == T_OBJECT || type == T_ARRAY) { + if (is_reference_type(type)) { if (UseCompressedOops) { t1 = new_register(T_OBJECT); t2 = new_register(T_OBJECT); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/c2_globals_ppc.hpp --- a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -82,9 +82,9 @@ define_pd_global(bool, IdealizeClearArrayNode, true); define_pd_global(uintx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(uintx, ReservedCodeCacheSize, 256*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 125*M); -define_pd_global(uintx, ProfiledCodeHeapSize, 126*M); +define_pd_global(uintx, ReservedCodeCacheSize, 48*M); +define_pd_global(uintx, NonProfiledCodeHeapSize, 21*M); +define_pd_global(uintx, ProfiledCodeHeapSize, 22*M); define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M ); define_pd_global(uintx, CodeCacheExpansionSize, 64*K); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, SAP SE. All rights reserved. + * Copyright (c) 2018, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -305,7 +305,7 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register base, RegisterOrConstant ind_or_offs, Register dst, Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null) { - bool on_oop = type == T_OBJECT || type == T_ARRAY; + bool on_oop = is_reference_type(type); bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; bool on_reference = on_weak || on_phantom; diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp --- a/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, SAP SE. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register base, RegisterOrConstant ind_or_offs, Register val, Register tmp1, Register tmp2, Register tmp3, bool needs_frame) { - if (type == T_OBJECT || type == T_ARRAY) { + if (is_reference_type(type)) { oop_store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame); } else { BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp --- a/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, SAP SE. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1142,7 +1142,7 @@ } if (!r_2->is_valid()) { // Not sure we need to do this but it shouldn't hurt. - if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ADDRESS || sig_bt[i] == T_ARRAY) { + if (is_reference_type(sig_bt[i]) || sig_bt[i] == T_ADDRESS) { __ ld(r, ld_offset, ld_ptr); ld_offset-=wordSize; } else { @@ -1739,8 +1739,7 @@ Register temp_reg = R19_method; // not part of any compiled calling seq if (VerifyOops) { for (int i = 0; i < method->size_of_parameters(); i++) { - if (sig_bt[i] == T_OBJECT || - sig_bt[i] == T_ARRAY) { + if (is_reference_type(sig_bt[i])) { VMReg r = regs[i].first(); assert(r->is_valid(), "bad oop arg"); if (r->is_stack()) { @@ -2602,7 +2601,7 @@ // Unbox oop result, e.g. JNIHandles::resolve value. // -------------------------------------------------------------------------- - if (ret_type == T_OBJECT || ret_type == T_ARRAY) { + if (is_reference_type(ret_type)) { __ resolve_jobject(R3_RET, r_temp_1, r_temp_2, /* needs_frame */ false); } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/s390/c1_FrameMap_s390.cpp --- a/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ Register reg = r_1->as_Register(); if (r_2->is_Register() && (type == T_LONG || type == T_DOUBLE)) { opr = as_long_opr(reg); - } else if (type == T_OBJECT || type == T_ARRAY) { + } else if (is_reference_type(type)) { opr = as_oop_opr(reg); } else if (type == T_METADATA) { opr = as_metadata_opr(reg); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -972,6 +972,7 @@ } else { __ z_lg(dest->as_register(), disp_value, disp_reg, src); } + __ verify_oop(dest->as_register()); break; } case T_FLOAT: @@ -991,9 +992,6 @@ case T_LONG : __ z_lg(dest->as_register_lo(), disp_value, disp_reg, src); break; default : ShouldNotReachHere(); } - if (type == T_ARRAY || type == T_OBJECT) { - __ verify_oop(dest->as_register()); - } if (patch != NULL) { patching_epilog(patch, patch_code, src, info); @@ -1006,7 +1004,7 @@ assert(dest->is_register(), "should not call otherwise"); if (dest->is_single_cpu()) { - if (type == T_ARRAY || type == T_OBJECT) { + if (is_reference_type(type)) { __ mem2reg_opt(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix()), true); __ verify_oop(dest->as_register()); } else if (type == T_METADATA) { @@ -1034,7 +1032,7 @@ if (src->is_single_cpu()) { const Address dst = frame_map()->address_for_slot(dest->single_stack_ix()); - if (type == T_OBJECT || type == T_ARRAY) { + if (is_reference_type(type)) { __ verify_oop(src->as_register()); __ reg2mem_opt(src->as_register(), dst, true); } else if (type == T_METADATA) { @@ -1080,7 +1078,7 @@ } else { ShouldNotReachHere(); } - if (to_reg->type() == T_OBJECT || to_reg->type() == T_ARRAY) { + if (is_reference_type(to_reg->type())) { __ verify_oop(to_reg->as_register()); } } @@ -1131,7 +1129,7 @@ assert(disp_reg != Z_R0 || Immediate::is_simm20(disp_value), "should have set this up"); - if (type == T_ARRAY || type == T_OBJECT) { + if (is_reference_type(type)) { __ verify_oop(from->as_register()); } @@ -1294,10 +1292,10 @@ Register reg1 = opr1->as_register(); if (opr2->is_single_cpu()) { // cpu register - cpu register - if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { + if (is_reference_type(opr1->type())) { __ z_clgr(reg1, opr2->as_register()); } else { - assert(opr2->type() != T_OBJECT && opr2->type() != T_ARRAY, "cmp int, oop?"); + assert(!is_reference_type(opr2->type()), "cmp int, oop?"); if (unsigned_comp) { __ z_clr(reg1, opr2->as_register()); } else { @@ -1306,7 +1304,7 @@ } } else if (opr2->is_stack()) { // cpu register - stack - if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { + if (is_reference_type(opr1->type())) { __ z_cg(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); } else { if (unsigned_comp) { @@ -1324,7 +1322,7 @@ } else { __ z_cfi(reg1, c->as_jint()); } - } else if (c->type() == T_OBJECT || c->type() == T_ARRAY) { + } else if (is_reference_type(c->type())) { // In 64bit oops are single register. jobject o = c->as_jobject(); if (o == NULL) { @@ -1767,7 +1765,7 @@ } } else { Register r_lo; - if (right->type() == T_OBJECT || right->type() == T_ARRAY) { + if (is_reference_type(right->type())) { r_lo = right->as_register(); } else { r_lo = right->as_register_lo(); @@ -2413,8 +2411,8 @@ __ move_reg_if_needed(len, T_LONG, len, T_INT); // sign extend if (UseSlowPath || - (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || - (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { + (!UseFastNewObjectArray && (is_reference_type(op->type()))) || + (!UseFastNewTypeArray && (!is_reference_type(op->type())))) { __ z_brul(*op->stub()->entry()); } else { __ allocate_array(op->obj()->as_register(), diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, SAP SE. All rights reserved. + * Copyright (c) 2018, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,7 +100,7 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, const Address& src, Register dst, Register tmp1, Register tmp2, Label *L_handle_null) { - bool on_oop = type == T_OBJECT || type == T_ARRAY; + bool on_oop = is_reference_type(type); bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; bool on_reference = on_weak || on_phantom; diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp --- a/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, SAP SE. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,14 +36,14 @@ void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) { - if (type == T_OBJECT || type == T_ARRAY) { + if (is_reference_type(type)) { gen_write_ref_array_pre_barrier(masm, decorators, dst, count); } } void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register dst, Register count, bool do_return) { - if (type == T_OBJECT || type == T_ARRAY) { + if (is_reference_type(type)) { gen_write_ref_array_post_barrier(masm, decorators, dst, count, do_return); } else { if (do_return) { __ z_br(Z_R14); } @@ -52,7 +52,7 @@ void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) { - if (type == T_OBJECT || type == T_ARRAY) { + if (is_reference_type(type)) { oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); } else { BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/s390/sharedRuntime_s390.cpp --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2018 SAP SE. All rights reserved. + * Copyright (c) 2016, 2019, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -883,7 +883,7 @@ if (!VerifyOops) { return; } for (int i = 0; i < total_args_passed; i++) { - if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ARRAY) { + if (is_reference_type(sig_bt[i])) { VMReg r = regs[i].first(); assert(r->is_valid(), "bad oop arg"); @@ -2318,7 +2318,7 @@ __ reset_last_Java_frame(); // Unpack oop result, e.g. JNIHandles::resolve result. - if (ret_type == T_OBJECT || ret_type == T_ARRAY) { + if (is_reference_type(ret_type)) { __ resolve_jobject(Z_RET, /* tmp1 */ Z_R13, /* tmp2 */ Z_R7); } @@ -2621,7 +2621,7 @@ } else { if (!r_2->is_valid()) { // Not sure we need to do this but it shouldn't hurt. - if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ADDRESS || sig_bt[i] == T_ARRAY) { + if (is_reference_type(sig_bt[i]) || sig_bt[i] == T_ADDRESS) { __ z_lg(r_1->as_Register(), ld_offset, ld_ptr); } else { __ z_l(r_1->as_Register(), ld_offset, ld_ptr); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -271,9 +271,14 @@ if (borrow_reg) { // No free registers available. Make one useful. tmp = LP64_ONLY(rscratch1) NOT_LP64(rdx); + if (tmp == dst) { + tmp = LP64_ONLY(rscratch2) NOT_LP64(rcx); + } __ push(tmp); } + assert_different_registers(dst, tmp); + Label done; __ movptr(tmp, Address(dst, oopDesc::mark_offset_in_bytes())); __ notptr(tmp); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/os/aix/os_aix.cpp --- a/src/hotspot/os/aix/os_aix.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/os/aix/os_aix.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1027,17 +1027,15 @@ // Time since start-up in seconds to a fine granularity. // Used by VMSelfDestructTimer and the MemProfiler. double os::elapsedTime() { - return (double)(os::elapsed_counter()) * 0.000001; + return ((double)os::elapsed_counter()) / os::elapsed_frequency(); // nanosecond resolution } jlong os::elapsed_counter() { - timeval time; - int status = gettimeofday(&time, NULL); - return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count; + return javaTimeNanos() - initial_time_count; } jlong os::elapsed_frequency() { - return (1000 * 1000); + return NANOSECS_PER_SEC; // nanosecond resolution } bool os::supports_vtime() { return true; } @@ -3498,7 +3496,7 @@ // _main_thread points to the thread that created/loaded the JVM. Aix::_main_thread = pthread_self(); - initial_time_count = os::elapsed_counter(); + initial_time_count = javaTimeNanos(); os::Posix::init(); } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/ci/ciEnv.cpp --- a/src/hotspot/share/ci/ciEnv.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/ci/ciEnv.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -154,6 +154,7 @@ _the_null_string = NULL; _the_min_jint_string = NULL; + _jvmti_redefinition_count = 0; _jvmti_can_hotswap_or_post_breakpoint = false; _jvmti_can_access_local_variables = false; _jvmti_can_post_on_exceptions = false; @@ -209,6 +210,7 @@ _the_null_string = NULL; _the_min_jint_string = NULL; + _jvmti_redefinition_count = 0; _jvmti_can_hotswap_or_post_breakpoint = false; _jvmti_can_access_local_variables = false; _jvmti_can_post_on_exceptions = false; @@ -231,6 +233,7 @@ VM_ENTRY_MARK; // Get Jvmti capabilities under lock to get consistant values. MutexLocker mu(JvmtiThreadState_lock); + _jvmti_redefinition_count = JvmtiExport::redefinition_count(); _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint(); _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables(); _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions(); @@ -238,6 +241,11 @@ } bool ciEnv::jvmti_state_changed() const { + // Some classes were redefined + if (_jvmti_redefinition_count != JvmtiExport::redefinition_count()) { + return true; + } + if (!_jvmti_can_access_local_variables && JvmtiExport::can_access_local_variables()) { return true; @@ -254,6 +262,7 @@ JvmtiExport::can_pop_frame()) { return true; } + return false; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/ci/ciEnv.hpp --- a/src/hotspot/share/ci/ciEnv.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/ci/ciEnv.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -68,6 +68,7 @@ int _name_buffer_len; // Cache Jvmti state + uint64_t _jvmti_redefinition_count; bool _jvmti_can_hotswap_or_post_breakpoint; bool _jvmti_can_access_local_variables; bool _jvmti_can_post_on_exceptions; diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/classfile/classLoaderData.cpp --- a/src/hotspot/share/classfile/classLoaderData.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/classfile/classLoaderData.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -129,8 +129,8 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous) : _metaspace(NULL), - _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, - Monitor::_safepoint_check_never)), + _metaspace_lock(new Mutex(Mutex::leaf+1, "Metaspace allocation lock", true, + Mutex::_safepoint_check_never)), _unloading(false), _is_unsafe_anonymous(is_unsafe_anonymous), _modified_oops(true), _accumulated_modified_oops(false), // An unsafe anonymous class loader data doesn't have anything to keep diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/code/nmethod.cpp --- a/src/hotspot/share/code/nmethod.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/code/nmethod.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1293,7 +1293,6 @@ */ bool nmethod::make_not_entrant_or_zombie(int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); - assert(!is_zombie(), "should not already be a zombie"); if (Atomic::load(&_state) >= state) { // Avoid taking the lock if already in required state. @@ -1316,20 +1315,18 @@ // This flag is used to remember whether we need to later lock and unregister. bool nmethod_needs_unregister = false; - // invalidate osr nmethod before acquiring the patching lock since - // they both acquire leaf locks and we don't want a deadlock. - // This logic is equivalent to the logic below for patching the - // verified entry point of regular methods. We check that the - // nmethod is in use to ensure that it is invalidated only once. - if (is_osr_method() && is_in_use()) { - // this effectively makes the osr nmethod not entrant - invalidate_osr_method(); - } - { // Enter critical section. Does not block for safepoint. MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock, Mutex::_no_safepoint_check_flag); + // This logic is equivalent to the logic below for patching the + // verified entry point of regular methods. We check that the + // nmethod is in use to ensure that it is invalidated only once. + if (is_osr_method() && is_in_use()) { + // this effectively makes the osr nmethod not entrant + invalidate_osr_method(); + } + if (Atomic::load(&_state) >= state) { // another thread already performed this transition so nothing // to do, but return false to indicate this. @@ -2192,6 +2189,17 @@ virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; +class VerifyMetadataClosure: public MetadataClosure { + public: + void do_metadata(Metadata* md) { + if (md->is_method()) { + Method* method = (Method*)md; + assert(!method->is_old(), "Should not be installing old methods"); + } + } +}; + + void nmethod::verify() { // Hmm. OSR methods can be deopted but not marked as zombie or not_entrant @@ -2255,6 +2263,10 @@ Universe::heap()->verify_nmethod(this); verify_scopes(); + + CompiledICLocker nm_verify(this); + VerifyMetadataClosure vmc; + metadata_do(&vmc); } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/compiler/compilerDefinitions.cpp --- a/src/hotspot/share/compiler/compilerDefinitions.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -188,14 +188,6 @@ #endif // TIERED void CompilerConfig::set_tiered_flags() { - // With tiered, set default policy to SimpleThresholdPolicy, which is 2. - if (FLAG_IS_DEFAULT(CompilationPolicyChoice)) { - FLAG_SET_DEFAULT(CompilationPolicyChoice, 2); - } - if (CompilationPolicyChoice < 2) { - vm_exit_during_initialization( - "Incompatible compilation policy selected", NULL); - } // Increase the code cache size - tiered compiles a lot more. if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) { FLAG_SET_ERGO(ReservedCodeCacheSize, @@ -420,17 +412,6 @@ if (TieredCompilation) { set_tiered_flags(); } else { - int max_compilation_policy_choice = 1; -#ifdef COMPILER2 - if (is_server_compilation_mode_vm()) { - max_compilation_policy_choice = 2; - } -#endif - // Check if the policy is valid. - if (CompilationPolicyChoice >= max_compilation_policy_choice) { - vm_exit_during_initialization( - "Incompatible compilation policy selected", NULL); - } // Scale CompileThreshold // CompileThresholdScaling == 0.0 is equivalent to -Xint and leaves CompileThreshold unchanged. if (!FLAG_IS_DEFAULT(CompileThresholdScaling) && CompileThresholdScaling > 0.0) { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/g1/g1RootProcessor.cpp --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -71,7 +71,7 @@ _g1h(g1h), _process_strong_tasks(G1RP_PS_NumElements), _srs(n_workers), - _lock(Mutex::leaf, "G1 Root Scan barrier lock", false, Monitor::_safepoint_check_never), + _lock(Mutex::leaf, "G1 Root Scan barrier lock", false, Mutex::_safepoint_check_never), _n_workers_discovered_strong_classes(0) {} void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_id) { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/g1/heapRegionRemSet.cpp --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -428,7 +428,7 @@ HeapRegion* hr) : _bot(bot), _code_roots(), - _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrm_index()), true, Monitor::_safepoint_check_never), + _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrm_index()), true, Mutex::_safepoint_check_never), _other_regions(&_m), _hr(hr), _state(Untracked) diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -38,6 +38,7 @@ #include "opto/movenode.hpp" #include "opto/narrowptrnode.hpp" #include "opto/rootnode.hpp" +#include "opto/runtime.hpp" ShenandoahBarrierSetC2* ShenandoahBarrierSetC2::bsc2() { return reinterpret_cast(BarrierSet::barrier_set()->barrier_set_c2()); @@ -461,11 +462,9 @@ } const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() { - const Type **fields = TypeTuple::fields(3); - fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // src - fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // dst - fields[TypeFunc::Parms+2] = TypeInt::INT; // length - const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3, fields); + const Type **fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeOopPtr::NOTNULL; // src oop + const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); // create result type (range) fields = TypeTuple::fields(0); @@ -796,8 +795,6 @@ return false; } -#define XTOP LP64_ONLY(COMMA phase->top()) - void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const { Node* ctrl = ac->in(TypeFunc::Control); Node* mem = ac->in(TypeFunc::Memory); @@ -807,14 +804,66 @@ Node* dest_offset = ac->in(ArrayCopyNode::DestPos); Node* length = ac->in(ArrayCopyNode::Length); assert (src_offset == NULL && dest_offset == NULL, "for clone offsets should be null"); + assert (src->is_AddP(), "for clone the src should be the interior ptr"); + assert (dest->is_AddP(), "for clone the dst should be the interior ptr"); + if (ShenandoahCloneBarrier && clone_needs_barrier(src, phase->igvn())) { - Node* call = phase->make_leaf_call(ctrl, mem, + // Check if heap is has forwarded objects. If it does, we need to call into the special + // routine that would fix up source references before we can continue. + + enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT }; + Node* region = new RegionNode(PATH_LIMIT); + Node* mem_phi = new PhiNode(region, Type::MEMORY, TypeRawPtr::BOTTOM); + + Node* thread = phase->transform_later(new ThreadLocalNode()); + Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + Node* gc_state_addr = phase->transform_later(new AddPNode(phase->C->top(), thread, offset)); + + uint gc_state_idx = Compile::AliasIdxRaw; + const TypePtr* gc_state_adr_type = NULL; // debug-mode-only argument + debug_only(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx)); + + Node* gc_state = phase->transform_later(new LoadBNode(ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered)); + Node* stable_and = phase->transform_later(new AndINode(gc_state, phase->igvn().intcon(ShenandoahHeap::HAS_FORWARDED))); + Node* stable_cmp = phase->transform_later(new CmpINode(stable_and, phase->igvn().zerocon(T_INT))); + Node* stable_test = phase->transform_later(new BoolNode(stable_cmp, BoolTest::ne)); + + IfNode* stable_iff = phase->transform_later(new IfNode(ctrl, stable_test, PROB_UNLIKELY(0.999), COUNT_UNKNOWN))->as_If(); + Node* stable_ctrl = phase->transform_later(new IfFalseNode(stable_iff)); + Node* unstable_ctrl = phase->transform_later(new IfTrueNode(stable_iff)); + + // Heap is stable, no need to do anything additional + region->init_req(_heap_stable, stable_ctrl); + mem_phi->init_req(_heap_stable, mem); + + // Heap is unstable, call into clone barrier stub + Node* call = phase->make_leaf_call(unstable_ctrl, mem, ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(), CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier), "shenandoah_clone", TypeRawPtr::BOTTOM, - src, dest, length); + src->in(AddPNode::Base)); call = phase->transform_later(call); + + ctrl = phase->transform_later(new ProjNode(call, TypeFunc::Control)); + mem = phase->transform_later(new ProjNode(call, TypeFunc::Memory)); + region->init_req(_heap_unstable, ctrl); + mem_phi->init_req(_heap_unstable, mem); + + // Wire up the actual arraycopy stub now + ctrl = phase->transform_later(region); + mem = phase->transform_later(mem_phi); + + const char* name = "arraycopy"; + call = phase->make_leaf_call(ctrl, mem, + OptoRuntime::fast_arraycopy_Type(), + phase->basictype2arraycopy(T_LONG, NULL, NULL, true, name, true), + name, TypeRawPtr::BOTTOM, + src, dest, length + LP64_ONLY(COMMA phase->top())); + call = phase->transform_later(call); + + // Hook up the whole thing into the graph phase->igvn().replace_node(ac, call); } else { BarrierSetC2::clone_at_expansion(phase, ac); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1272,6 +1272,18 @@ } if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) { CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava(); + if (call->entry_point() == OptoRuntime::rethrow_stub()) { + // The rethrow call may have too many projections to be + // properly handled here. Given there's no reason for a + // barrier to depend on the call, move it above the call + if (phase->get_ctrl(val) == ctrl) { + assert(val->Opcode() == Op_DecodeN, "unexpected node"); + assert(phase->is_dominator(phase->get_ctrl(val->in(1)), call->in(0)), "Load is too low"); + phase->set_ctrl(val, call->in(0)); + } + phase->set_ctrl(lrb, call->in(0)); + continue; + } CallProjections projs; call->extract_projections(&projs, false, false); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahBarrierSetClone.inline.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" @@ -283,3 +284,10 @@ return load_reference_barrier_not_null(obj); } + +void ShenandoahBarrierSet::clone_barrier_runtime(oop src) { + if (_heap->has_forwarded_objects()) { + clone_barrier(src); + } +} + diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -71,6 +71,7 @@ inline void arraycopy_update(oop* src, size_t count); inline void arraycopy_update(narrowOop* src, size_t count); inline void clone_barrier(oop src); + void clone_barrier_runtime(oop src); // We export this to make it available in cases where the static // type of the barrier set is known. Note that it is non-virtual. diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -186,7 +186,7 @@ template void ShenandoahBarrierSet::AccessBarrier::clone_in_heap(oop src, oop dst, size_t size) { if (ShenandoahCloneBarrier) { - ShenandoahBarrierSet::barrier_set()->clone_barrier(src); + ShenandoahBarrierSet::barrier_set()->clone_barrier_runtime(src); } Raw::clone(src, dst, size); } @@ -273,67 +273,4 @@ arraycopy_update_impl(src, count); } -template -class ShenandoahUpdateRefsForOopClosure: public BasicOopIterateClosure { -private: - ShenandoahHeap* const _heap; - ShenandoahBarrierSet* const _bs; - const ShenandoahCollectionSet* const _cset; - Thread* const _thread; - - template - inline void do_oop_work(T* p) { - T o = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(o)) { - oop obj = CompressedOops::decode_not_null(o); - if (_cset->is_in((HeapWord *)obj)) { - oop fwd = _bs->resolve_forwarded_not_null(obj); - if (EVAC && obj == fwd) { - fwd = _heap->evacuate_object(obj, _thread); - } - if (ENQUEUE) { - _bs->enqueue(fwd); - } - assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded"); - ShenandoahHeap::cas_oop(fwd, p, o); - } - - } - } -public: - ShenandoahUpdateRefsForOopClosure() : - _heap(ShenandoahHeap::heap()), - _bs(ShenandoahBarrierSet::barrier_set()), - _cset(_heap->collection_set()), - _thread(Thread::current()) { - } - - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } -}; - -void ShenandoahBarrierSet::clone_barrier(oop obj) { - assert(ShenandoahCloneBarrier, "only get here with clone barriers enabled"); - if (!_heap->has_forwarded_objects()) return; - - // This is called for cloning an object (see jvm.cpp) after the clone - // has been made. We are not interested in any 'previous value' because - // it would be NULL in any case. But we *are* interested in any oop* - // that potentially need to be updated. - - shenandoah_assert_correct(NULL, obj); - if (_heap->is_evacuation_in_progress()) { - ShenandoahEvacOOMScope evac_scope; - ShenandoahUpdateRefsForOopClosure cl; - obj->oop_iterate(&cl); - } else if (_heap->is_concurrent_traversal_in_progress()) { - ShenandoahEvacOOMScope evac_scope; - ShenandoahUpdateRefsForOopClosure cl; - obj->oop_iterate(&cl); - } else { - ShenandoahUpdateRefsForOopClosure cl; - obj->oop_iterate(&cl); - } -} - #endif // SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSETCLONE_INLINE_HPP +#define SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSETCLONE_INLINE_HPP + +#include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" +#include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" +#include "gc/shenandoah/shenandoahEvacOOMHandler.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "memory/iterator.hpp" +#include "oops/access.hpp" +#include "oops/compressedOops.hpp" + +template +class ShenandoahUpdateRefsForOopClosure: public BasicOopIterateClosure { +private: + ShenandoahHeap* const _heap; + ShenandoahBarrierSet* const _bs; + const ShenandoahCollectionSet* const _cset; + Thread* const _thread; + + template + inline void do_oop_work(T* p) { + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); + if (_cset->is_in((HeapWord *)obj)) { + oop fwd = _bs->resolve_forwarded_not_null(obj); + if (EVAC && obj == fwd) { + fwd = _heap->evacuate_object(obj, _thread); + } + if (ENQUEUE) { + _bs->enqueue(fwd); + } + assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded"); + ShenandoahHeap::cas_oop(fwd, p, o); + } + + } + } +public: + ShenandoahUpdateRefsForOopClosure() : + _heap(ShenandoahHeap::heap()), + _bs(ShenandoahBarrierSet::barrier_set()), + _cset(_heap->collection_set()), + _thread(Thread::current()) { + } + + virtual void do_oop(oop* p) { do_oop_work(p); } + virtual void do_oop(narrowOop* p) { do_oop_work(p); } +}; + +void ShenandoahBarrierSet::clone_barrier(oop obj) { + assert(ShenandoahCloneBarrier, "only get here with clone barriers enabled"); + assert(_heap->has_forwarded_objects(), "only when heap is unstable"); + + // This is called for cloning an object (see jvm.cpp) after the clone + // has been made. We are not interested in any 'previous value' because + // it would be NULL in any case. But we *are* interested in any oop* + // that potentially need to be updated. + + shenandoah_assert_correct(NULL, obj); + if (_heap->is_evacuation_in_progress()) { + ShenandoahEvacOOMScope evac_scope; + ShenandoahUpdateRefsForOopClosure cl; + obj->oop_iterate(&cl); + } else if (_heap->is_concurrent_traversal_in_progress()) { + ShenandoahEvacOOMScope evac_scope; + ShenandoahUpdateRefsForOopClosure cl; + obj->oop_iterate(&cl); + } else { + ShenandoahUpdateRefsForOopClosure cl; + obj->oop_iterate(&cl); + } +} + +#endif // SHARE_GC_SHENANDOAH_SHENANDOAHBARRIERSETCLONE_INLINE_HPP diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -23,10 +23,12 @@ #include "precompiled.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" +#include "gc/shenandoah/shenandoahBarrierSetClone.inline.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "oops/oop.inline.hpp" +#include "utilities/copy.hpp" void ShenandoahRuntime::write_ref_array_pre_oop_entry(oop* src, oop* dst, size_t length) { ShenandoahBarrierSet *bs = ShenandoahBarrierSet::barrier_set(); @@ -74,13 +76,10 @@ // Shenandoah clone barrier: makes sure that references point to to-space // in cloned objects. -JRT_LEAF(void, ShenandoahRuntime::shenandoah_clone_barrier(oopDesc* s, oopDesc* d, size_t length)) - oop src = oop(s); - oop dst = oop(d); - shenandoah_assert_correct(NULL, src); - shenandoah_assert_correct(NULL, dst); - ShenandoahBarrierSet::barrier_set()->clone_barrier(src); - RawAccessBarrier::clone(src, dst, length); +JRT_LEAF(void, ShenandoahRuntime::shenandoah_clone_barrier(oopDesc* src)) + oop s = oop(src); + shenandoah_assert_correct(NULL, s); + ShenandoahBarrierSet::barrier_set()->clone_barrier(s); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_native(oopDesc * src)) diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -44,7 +44,7 @@ static oopDesc* load_reference_barrier_native(oopDesc* src); - static void shenandoah_clone_barrier(oopDesc* s, oopDesc* d, size_t length); + static void shenandoah_clone_barrier(oopDesc* src); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHRUNTIME_HPP diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/gc/z/zNMethod.cpp --- a/src/hotspot/share/gc/z/zNMethod.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/gc/z/zNMethod.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -294,13 +294,14 @@ return; } - ZLocker locker(ZNMethod::lock_for_nmethod(nm)); - if (nm->is_unloading()) { + ZLocker locker(ZNMethod::lock_for_nmethod(nm)); unlink(nm); return; } + ZLocker locker(ZNMethod::lock_for_nmethod(nm)); + // Heal oops and disarm ZNMethodOopClosure cl; ZNMethod::nmethod_oops_do(nm, &cl); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/include/jmm.h --- a/src/hotspot/share/include/jmm.h Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/include/jmm.h Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,8 +50,9 @@ JMM_VERSION_1_2 = 0x20010200, // JDK 7 JMM_VERSION_1_2_1 = 0x20010201, // JDK 7 GA JMM_VERSION_1_2_2 = 0x20010202, - JMM_VERSION_2 = 0x20020000, // JDK 10 - JMM_VERSION = 0x20020000 + JMM_VERSION_2 = 0x20020000, // JDK 10 + JMM_VERSION_3 = 0x20030000, // JDK 14 + JMM_VERSION = JMM_VERSION_3 }; typedef struct { @@ -239,6 +240,9 @@ jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool); jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool); + jlong (JNICALL *GetOneThreadAllocatedMemory) + (JNIEnv *env, + jlong thread_id); void (JNICALL *GetThreadAllocatedMemory) (JNIEnv *env, jlongArray ids, diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/jvmci/jvmciEnv.cpp --- a/src/hotspot/share/jvmci/jvmciEnv.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -44,6 +44,7 @@ _failure_reason_on_C_heap(false) { // Get Jvmti capabilities under lock to get consistent values. MutexLocker mu(JvmtiThreadState_lock); + _jvmti_redefinition_count = JvmtiExport::redefinition_count(); _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0; _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables() ? 1 : 0; _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0; @@ -51,6 +52,10 @@ } bool JVMCICompileState::jvmti_state_changed() const { + // Some classes were redefined + if (jvmti_redefinition_count() != JvmtiExport::redefinition_count()) { + return true; + } if (!jvmti_can_access_local_variables() && JvmtiExport::can_access_local_variables()) { return true; diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/jvmci/jvmciEnv.hpp --- a/src/hotspot/share/jvmci/jvmciEnv.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -94,6 +94,7 @@ // Cache JVMTI state. Defined as bytes so that reading them from Java // via Unsafe is well defined (the C++ type for bool is implementation // defined and may not be the same as a Java boolean). + uint64_t _jvmti_redefinition_count; jbyte _jvmti_can_hotswap_or_post_breakpoint; jbyte _jvmti_can_access_local_variables; jbyte _jvmti_can_post_on_exceptions; @@ -113,6 +114,7 @@ CompileTask* task() { return _task; } bool jvmti_state_changed() const; + uint64_t jvmti_redefinition_count() const { return _jvmti_redefinition_count; } bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint != 0; } bool jvmti_can_access_local_variables() const { return _jvmti_can_access_local_variables != 0; } bool jvmti_can_post_on_exceptions() const { return _jvmti_can_post_on_exceptions != 0; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/oops/instanceKlass.cpp --- a/src/hotspot/share/oops/instanceKlass.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/oops/instanceKlass.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1101,7 +1101,7 @@ void InstanceKlass::set_implementor(Klass* k) { - assert_lock_strong(Compile_lock); + assert_locked_or_safepoint(Compile_lock); assert(is_interface(), "not interface"); Klass* volatile* addr = adr_implementor(); assert(addr != NULL, "null addr"); @@ -2333,8 +2333,8 @@ // being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()). _init_state = allocated; - { - MutexLocker ml(Compile_lock); + { // Otherwise this needs to take out the Compile_lock. + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); init_implementor(); } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/oops/methodData.cpp --- a/src/hotspot/share/oops/methodData.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/oops/methodData.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1212,7 +1212,7 @@ // Initialize the MethodData* corresponding to a given method. MethodData::MethodData(const methodHandle& method, int size, TRAPS) - : _extra_data_lock(Monitor::leaf, "MDO extra data lock"), + : _extra_data_lock(Mutex::leaf, "MDO extra data lock"), _parameters_type_data_di(parameters_uninitialized) { // Set the method back-pointer. _method = method(); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/oops/methodData.hpp --- a/src/hotspot/share/oops/methodData.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/oops/methodData.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -2011,7 +2011,7 @@ MethodData(const methodHandle& method, int size, TRAPS); public: static MethodData* allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS); - MethodData() : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {}; // For ciMethodData + MethodData() : _extra_data_lock(Mutex::leaf, "MDO extra data lock") {}; // For ciMethodData bool is_methodData() const volatile { return true; } void initialize(); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/callnode.cpp --- a/src/hotspot/share/opto/callnode.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/callnode.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1397,6 +1397,18 @@ _is_allocation_MemBar_redundant = true; } } +Node *AllocateNode::make_ideal_mark(PhaseGVN *phase, Node* obj, Node* control, Node* mem) { + Node* mark_node = NULL; + // For now only enable fast locking for non-array types + if (UseBiasedLocking && Opcode() == Op_Allocate) { + Node* klass_node = in(AllocateNode::KlassNode); + Node* proto_adr = phase->transform(new AddPNode(klass_node, klass_node, phase->MakeConX(in_bytes(Klass::prototype_header_offset())))); + mark_node = LoadNode::make(*phase, control, mem, proto_adr, TypeRawPtr::BOTTOM, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); + } else { + mark_node = phase->MakeConX(markWord::prototype().value()); + } + return mark_node; +} //============================================================================= Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/callnode.hpp --- a/src/hotspot/share/opto/callnode.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/callnode.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -936,6 +936,8 @@ // allocation node. void compute_MemBar_redundancy(ciMethod* initializer); bool is_allocation_MemBar_redundant() { return _is_allocation_MemBar_redundant; } + + Node* make_ideal_mark(PhaseGVN *phase, Node* obj, Node* control, Node* mem); }; //------------------------------AllocateArray--------------------------------- diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/loopPredicate.cpp --- a/src/hotspot/share/opto/loopPredicate.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/loopPredicate.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1381,7 +1381,6 @@ } // end while } - Node_List if_proj_list_freq(area); if (follow_branches) { PathFrequency pf(loop->_head, this); @@ -1399,6 +1398,7 @@ // And look into all branches Node_Stack stack(0); VectorSet seen(Thread::current()->resource_area()); + Node_List if_proj_list_freq(area); while (regions.size() > 0) { Node* c = regions.pop(); loop_predication_follow_branches(c, loop, loop_trip_cnt, pf, stack, seen, if_proj_list_freq); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/loopTransform.cpp --- a/src/hotspot/share/opto/loopTransform.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/loopTransform.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -671,76 +671,50 @@ loop->record_for_igvn(); } -// The Estimated Loop Unroll Size: UnrollFactor * (106% * BodySize + BC) + CC, -// where BC and CC are (totally) ad-hoc/magic "body" and "clone" constants, -// respectively, used to ensure that node usage estimates made are on the safe -// side, for the most part. This is a simplified version of the loop clone -// size calculation in est_loop_clone_sz(), defined for unroll factors larger -// than one (>1), performing an overflow check and returning 'UINT_MAX' in -// case of an overflow. -static uint est_loop_unroll_sz(uint factor, uint size) { - precond(0 < factor); - - uint const bc = 5; - uint const cc = 7; - uint const sz = size + (size + 15) / 16; - uint estimate = factor * (sz + bc) + cc; - - return (estimate - cc) / factor == sz + bc ? estimate : UINT_MAX; -} - -#define EMPTY_LOOP_SIZE 7 // Number of nodes in an empty loop. - //------------------------------policy_maximally_unroll------------------------ // Calculate the exact loop trip-count and return TRUE if loop can be fully, // i.e. maximally, unrolled, otherwise return FALSE. When TRUE, the estimated // node budget is also requested. -bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop *phase) const { - CountedLoopNode *cl = _head->as_CountedLoop(); +bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop* phase) const { + CountedLoopNode* cl = _head->as_CountedLoop(); assert(cl->is_normal_loop(), ""); if (!cl->is_valid_counted_loop()) { - return false; // Malformed counted loop + return false; // Malformed counted loop. } if (!cl->has_exact_trip_count()) { - // Trip count is not exact. - return false; + return false; // Trip count is not exact. } uint trip_count = cl->trip_count(); // Note, max_juint is used to indicate unknown trip count. assert(trip_count > 1, "one iteration loop should be optimized out already"); - assert(trip_count < max_juint, "exact trip_count should be less than max_uint."); + assert(trip_count < max_juint, "exact trip_count should be less than max_juint."); // If nodes are depleted, some transform has miscalculated its needs. assert(!phase->exceeding_node_budget(), "sanity"); - // Real policy: if we maximally unroll, does it get too big? - // Allow the unrolled mess to get larger than standard loop - // size. After all, it will no longer be a loop. - uint body_size = _body.size(); + // Allow the unrolled body to get larger than the standard loop size limit. uint unroll_limit = (uint)LoopUnrollLimit * 4; assert((intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits"); - if (trip_count > unroll_limit || body_size > unroll_limit) { + if (trip_count > unroll_limit || _body.size() > unroll_limit) { return false; } - // Take into account that after unroll conjoined heads and tails will fold, - // otherwise policy_unroll() may allow more unrolling than max unrolling. - uint new_body_size = est_loop_unroll_sz(trip_count, body_size - EMPTY_LOOP_SIZE); + uint new_body_size = est_loop_unroll_sz(trip_count); if (new_body_size == UINT_MAX) { // Check for bad estimate (overflow). return false; } - // Fully unroll a loop with few iterations regardless next conditions since - // following loop optimizations will split such loop anyway (pre-main-post). + // Fully unroll a loop with few iterations, regardless of other conditions, + // since the following (general) loop optimizations will split such loop in + // any case (into pre-main-post). if (trip_count <= 3) { return phase->may_require_nodes(new_body_size); } - if (new_body_size > unroll_limit || - // Unrolling can result in a large amount of node construction - phase->exceeding_node_budget(new_body_size)) { + // Reject if unrolling will result in too much node construction. + if (new_body_size > unroll_limit || phase->exceeding_node_budget(new_body_size)) { return false; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/loopnode.cpp --- a/src/hotspot/share/opto/loopnode.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/loopnode.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -2471,6 +2471,39 @@ assert((estimate - cc) / factor == sz + bc, "overflow"); + return estimate + est_loop_flow_merge_sz(); +} + +// The Estimated Loop (full-) Unroll Size: +// UnrollFactor * (~106% * BodySize) + CC + FanOutTerm, +// where CC is a (totally) ad-hoc/magic "clone" constant, used to ensure that +// node usage estimates made are on the safe side, for the most part. This is +// a "light" version of the loop clone size calculation (above), based on the +// assumption that most of the loop-construct overhead will be unraveled when +// (fully) unrolled. Defined for unroll factors larger or equal to one (>=1), +// including an overflow check and returning UINT_MAX in case of an overflow. +uint IdealLoopTree::est_loop_unroll_sz(uint factor) const { + + precond(factor > 0); + + // Take into account that after unroll conjoined heads and tails will fold. + uint const b0 = _body.size() - EMPTY_LOOP_SIZE; + uint const cc = 7; + uint const sz = b0 + (b0 + 15) / 16; + uint estimate = factor * sz + cc; + + if ((estimate - cc) / factor != sz) { + return UINT_MAX; + } + + return estimate + est_loop_flow_merge_sz(); +} + +// Estimate the growth effect (in nodes) of merging control and data flow when +// cloning a loop body, based on the amount of control and data flow reaching +// outside of the (current) loop body. +uint IdealLoopTree::est_loop_flow_merge_sz() const { + uint ctrl_edge_out_cnt = 0; uint data_edge_out_cnt = 0; @@ -2494,24 +2527,21 @@ } } } - // Add data and control count (x2.0) to estimate iff both are > 0. This is + // Use data and control count (x2.0) in estimate iff both are > 0. This is // a rather pessimistic estimate for the most part, in particular for some // complex loops, but still not enough to capture all loops. if (ctrl_edge_out_cnt > 0 && data_edge_out_cnt > 0) { - estimate += 2 * (ctrl_edge_out_cnt + data_edge_out_cnt); + return 2 * (ctrl_edge_out_cnt + data_edge_out_cnt); } - - return estimate; + return 0; } #ifndef PRODUCT //------------------------------dump_head-------------------------------------- // Dump 1 liner for loop header info void IdealLoopTree::dump_head() const { - for (uint i = 0; i < _nest; i++) { - tty->print(" "); - } - tty->print("Loop: N%d/N%d ",_head->_idx,_tail->_idx); + tty->sp(2 * _nest); + tty->print("Loop: N%d/N%d ", _head->_idx, _tail->_idx); if (_irreducible) tty->print(" IRREDUCIBLE"); Node* entry = _head->is_Loop() ? _head->as_Loop()->skip_strip_mined(-1)->in(LoopNode::EntryControl) : _head->in(LoopNode::EntryControl); Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); @@ -4501,69 +4531,67 @@ #ifndef PRODUCT //------------------------------dump------------------------------------------- -void PhaseIdealLoop::dump( ) const { +void PhaseIdealLoop::dump() const { ResourceMark rm; Arena* arena = Thread::current()->resource_area(); Node_Stack stack(arena, C->live_nodes() >> 2); Node_List rpo_list; VectorSet visited(arena); visited.set(C->top()->_idx); - rpo( C->root(), stack, visited, rpo_list ); + rpo(C->root(), stack, visited, rpo_list); // Dump root loop indexed by last element in PO order - dump( _ltree_root, rpo_list.size(), rpo_list ); + dump(_ltree_root, rpo_list.size(), rpo_list); } -void PhaseIdealLoop::dump( IdealLoopTree *loop, uint idx, Node_List &rpo_list ) const { +void PhaseIdealLoop::dump(IdealLoopTree* loop, uint idx, Node_List &rpo_list) const { loop->dump_head(); // Now scan for CFG nodes in the same loop - for( uint j=idx; j > 0; j-- ) { - Node *n = rpo_list[j-1]; - if( !_nodes[n->_idx] ) // Skip dead nodes + for (uint j = idx; j > 0; j--) { + Node* n = rpo_list[j-1]; + if (!_nodes[n->_idx]) // Skip dead nodes continue; - if( get_loop(n) != loop ) { // Wrong loop nest - if( get_loop(n)->_head == n && // Found nested loop? - get_loop(n)->_parent == loop ) - dump(get_loop(n),rpo_list.size(),rpo_list); // Print it nested-ly + + if (get_loop(n) != loop) { // Wrong loop nest + if (get_loop(n)->_head == n && // Found nested loop? + get_loop(n)->_parent == loop) + dump(get_loop(n), rpo_list.size(), rpo_list); // Print it nested-ly continue; } // Dump controlling node - for( uint x = 0; x < loop->_nest; x++ ) - tty->print(" "); + tty->sp(2 * loop->_nest); tty->print("C"); - if( n == C->root() ) { + if (n == C->root()) { n->dump(); } else { Node* cached_idom = idom_no_update(n); - Node *computed_idom = n->in(0); - if( n->is_Region() ) { + Node* computed_idom = n->in(0); + if (n->is_Region()) { computed_idom = compute_idom(n); // computed_idom() will return n->in(0) when idom(n) is an IfNode (or // any MultiBranch ctrl node), so apply a similar transform to // the cached idom returned from idom_no_update. cached_idom = find_non_split_ctrl(cached_idom); } - tty->print(" ID:%d",computed_idom->_idx); + tty->print(" ID:%d", computed_idom->_idx); n->dump(); - if( cached_idom != computed_idom ) { + if (cached_idom != computed_idom) { tty->print_cr("*** BROKEN IDOM! Computed as: %d, cached as: %d", computed_idom->_idx, cached_idom->_idx); } } // Dump nodes it controls - for( uint k = 0; k < _nodes.Size(); k++ ) { + for (uint k = 0; k < _nodes.Size(); k++) { // (k < C->unique() && get_ctrl(find(k)) == n) if (k < C->unique() && _nodes[k] == (Node*)((intptr_t)n + 1)) { - Node *m = C->root()->find(k); - if( m && m->outcnt() > 0 ) { + Node* m = C->root()->find(k); + if (m && m->outcnt() > 0) { if (!(has_ctrl(m) && get_ctrl_no_update(m) == n)) { tty->print_cr("*** BROKEN CTRL ACCESSOR! _nodes[k] is %p, ctrl is %p", _nodes[k], has_ctrl(m) ? get_ctrl_no_update(m) : NULL); } - for( uint j = 0; j < loop->_nest; j++ ) - tty->print(" "); - tty->print(" "); + tty->sp(2 * loop->_nest + 1); m->dump(); } } @@ -4574,7 +4602,7 @@ // Collect a R-P-O for the whole CFG. // Result list is in post-order (scan backwards for RPO) -void PhaseIdealLoop::rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const { +void PhaseIdealLoop::rpo(Node* start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list) const { stk.push(start, 0); visited.set(start->_idx); @@ -4596,7 +4624,7 @@ //============================================================================= -//------------------------------LoopTreeIterator----------------------------------- +//------------------------------LoopTreeIterator------------------------------- // Advance to next loop tree using a preorder, left-to-right traversal. void LoopTreeIterator::next() { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/loopnode.hpp --- a/src/hotspot/share/opto/loopnode.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/loopnode.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -623,6 +623,8 @@ // Estimate the number of nodes required when cloning a loop (body). uint est_loop_clone_sz(uint factor) const; + // Estimate the number of nodes required when unrolling a loop (body). + uint est_loop_unroll_sz(uint factor) const; // Compute loop trip count if possible void compute_trip_count(PhaseIdealLoop* phase); @@ -654,11 +656,16 @@ void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase); #ifndef PRODUCT - void dump_head( ) const; // Dump loop head only + void dump_head() const; // Dump loop head only void dump() const; // Dump this loop recursively void verify_tree(IdealLoopTree *loop, const IdealLoopTree *parent) const; #endif + private: + enum { EMPTY_LOOP_SIZE = 7 }; // Number of nodes in an empty loop. + + // Estimate the number of nodes resulting from control and data flow merge. + uint est_loop_flow_merge_sz() const; }; // -----------------------------PhaseIdealLoop--------------------------------- @@ -675,7 +682,7 @@ PhaseIterGVN &_igvn; // Head of loop tree - IdealLoopTree *_ltree_root; + IdealLoopTree* _ltree_root; // Array of pre-order numbers, plus post-visited bit. // ZERO for not pre-visited. EVEN for pre-visited but not post-visited. @@ -1017,9 +1024,9 @@ bool _has_irreducible_loops; // Per-Node transform - virtual Node *transform( Node *a_node ) { return 0; } + virtual Node* transform(Node* n) { return 0; } - bool is_counted_loop(Node* x, IdealLoopTree*& loop); + bool is_counted_loop(Node* n, IdealLoopTree* &loop); IdealLoopTree* create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, IdealLoopTree* loop, float cl_prob, float le_fcnt, Node*& entry_control, Node*& iffalse); @@ -1034,7 +1041,7 @@ return (IdealLoopTree*)_nodes[n->_idx]; } - IdealLoopTree *ltree_root() const { return _ltree_root; } + IdealLoopTree* ltree_root() const { return _ltree_root; } // Is 'n' a (nested) member of 'loop'? int is_member( const IdealLoopTree *loop, Node *n ) const { @@ -1319,7 +1326,7 @@ // same block. Split thru the Region. void do_split_if( Node *iff ); - // Conversion of fill/copy patterns into intrisic versions + // Conversion of fill/copy patterns into intrinsic versions bool do_intrinsify_fill(); bool intrinsify_fill(IdealLoopTree* lpt); bool match_fill_loop(IdealLoopTree* lpt, Node*& store, Node*& store_value, @@ -1419,18 +1426,18 @@ public: void set_created_loop_node() { _created_loop_node = true; } bool created_loop_node() { return _created_loop_node; } - void register_new_node( Node *n, Node *blk ); + void register_new_node(Node* n, Node* blk); #ifdef ASSERT void dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA); #endif #ifndef PRODUCT - void dump( ) const; - void dump( IdealLoopTree *loop, uint rpo_idx, Node_List &rpo_list ) const; + void dump() const; + void dump(IdealLoopTree* loop, uint rpo_idx, Node_List &rpo_list) const; void verify() const; // Major slow :-) - void verify_compare( Node *n, const PhaseIdealLoop *loop_verify, VectorSet &visited ) const; - IdealLoopTree *get_loop_idx(Node* n) const { + void verify_compare(Node* n, const PhaseIdealLoop* loop_verify, VectorSet &visited) const; + IdealLoopTree* get_loop_idx(Node* n) const { // Dead nodes have no loop, so return the top level loop instead return _nodes[n->_idx] ? (IdealLoopTree*)_nodes[n->_idx] : _ltree_root; } @@ -1439,7 +1446,8 @@ static int _loop_invokes; // Count of PhaseIdealLoop invokes static int _loop_work; // Sum of PhaseIdealLoop x _unique #endif - void rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const; + + void rpo(Node* start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list) const; }; diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/loopopts.cpp --- a/src/hotspot/share/opto/loopopts.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/loopopts.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -653,7 +653,10 @@ } }//for Node* bol = iff->in(1); - assert(bol->Opcode() == Op_Bool, ""); + if (bol->Opcode() == Op_Opaque4) { + return NULL; // Ignore loop predicate checks (the Opaque4 ensures they will go away) + } + assert(bol->Opcode() == Op_Bool, "Unexpected node"); int cmp_op = bol->in(1)->Opcode(); // It is expensive to generate flags from a float compare. // Avoid duplicated float compare. @@ -1443,6 +1446,20 @@ // Such nodes should only have ProjNodes as outs, e.g. IfNode // should only have IfTrueNode and IfFalseNode (4985384). x_ctrl = find_non_split_ctrl(x_ctrl); + + IdealLoopTree* x_loop = get_loop(x_ctrl); + Node* x_head = x_loop->_head; + if (x_head->is_Loop() && (x_head->is_OuterStripMinedLoop() || x_head->as_Loop()->is_strip_mined()) && is_dominator(n_ctrl, x_head)) { + // Anti dependence analysis is sometimes too + // conservative: a store in the outer strip mined loop + // can prevent a load from floating out of the outer + // strip mined loop but the load may not be referenced + // from the safepoint: loop strip mining verification + // code reports a problem in that case. Make sure the + // load is not moved in the outer strip mined loop in + // that case. + x_ctrl = x_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl); + } assert(dom_depth(n_ctrl) <= dom_depth(x_ctrl), "n is later than its clone"); x->set_req(0, x_ctrl); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/macro.cpp --- a/src/hotspot/share/opto/macro.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/macro.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -357,19 +357,38 @@ if (ac->modifies(offset, offset, &_igvn, true)) { assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result"); uint shift = exact_log2(type2aelembytes(bt)); - Node* diff = _igvn.transform(new SubINode(ac->in(ArrayCopyNode::SrcPos), ac->in(ArrayCopyNode::DestPos))); -#ifdef _LP64 - diff = _igvn.transform(new ConvI2LNode(diff)); -#endif - diff = _igvn.transform(new LShiftXNode(diff, intcon(shift))); + Node* src_pos = ac->in(ArrayCopyNode::SrcPos); + Node* dest_pos = ac->in(ArrayCopyNode::DestPos); + const TypeInt* src_pos_t = _igvn.type(src_pos)->is_int(); + const TypeInt* dest_pos_t = _igvn.type(dest_pos)->is_int(); - Node* off = _igvn.transform(new AddXNode(MakeConX(offset), diff)); - Node* base = ac->in(ArrayCopyNode::Src); - Node* adr = _igvn.transform(new AddPNode(base, base, off)); - const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset); - if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) { - // Don't emit a new load from src if src == dst but try to get the value from memory instead - return value_from_mem(ac->in(TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr(), alloc); + Node* adr = NULL; + const TypePtr* adr_type = NULL; + if (src_pos_t->is_con() && dest_pos_t->is_con()) { + intptr_t off = ((src_pos_t->get_con() - dest_pos_t->get_con()) << shift) + offset; + Node* base = ac->in(ArrayCopyNode::Src); + adr = _igvn.transform(new AddPNode(base, base, MakeConX(off))); + adr_type = _igvn.type(base)->is_ptr()->add_offset(off); + if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) { + // Don't emit a new load from src if src == dst but try to get the value from memory instead + return value_from_mem(ac->in(TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr(), alloc); + } + } else { + Node* diff = _igvn.transform(new SubINode(ac->in(ArrayCopyNode::SrcPos), ac->in(ArrayCopyNode::DestPos))); +#ifdef _LP64 + diff = _igvn.transform(new ConvI2LNode(diff)); +#endif + diff = _igvn.transform(new LShiftXNode(diff, intcon(shift))); + + Node* off = _igvn.transform(new AddXNode(MakeConX(offset), diff)); + Node* base = ac->in(ArrayCopyNode::Src); + adr = _igvn.transform(new AddPNode(base, base, off)); + adr_type = _igvn.type(base)->is_ptr()->add_offset(Type::OffsetBot); + if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) { + // Non constant offset in the array: we can't statically + // determine the value + return NULL; + } } res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::UnknownControl); } @@ -1633,14 +1652,11 @@ Node* size_in_bytes) { InitializeNode* init = alloc->initialization(); // Store the klass & mark bits - Node* mark_node = NULL; - // For now only enable fast locking for non-array types - if (UseBiasedLocking && (length == NULL)) { - mark_node = make_load(control, rawmem, klass_node, in_bytes(Klass::prototype_header_offset()), TypeRawPtr::BOTTOM, T_ADDRESS); - } else { - mark_node = makecon(TypeRawPtr::make((address)markWord::prototype().value())); + Node* mark_node = alloc->make_ideal_mark(&_igvn, object, control, rawmem); + if (!mark_node->is_Con()) { + transform_later(mark_node); } - rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, T_ADDRESS); + rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, TypeX_X->basic_type()); rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_METADATA); int header_size = alloc->minimum_header_size(); // conservatively small @@ -2577,15 +2593,36 @@ if (_igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())) { // node is unreachable, so don't try to expand it C->remove_macro_node(n); - } else if (n->is_ArrayCopy()){ - int macro_count = C->macro_count(); + continue; + } + int macro_count = C->macro_count(); + switch (n->class_id()) { + case Node::Class_Lock: + expand_lock_node(n->as_Lock()); + assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + break; + case Node::Class_Unlock: + expand_unlock_node(n->as_Unlock()); + assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + break; + case Node::Class_ArrayCopy: expand_arraycopy_node(n->as_ArrayCopy()); assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + break; } if (C->failing()) return true; macro_idx --; } + // All nodes except Allocate nodes are expanded now. There could be + // new optimization opportunities (such as folding newly created + // load from a just allocated object). Run IGVN. + _igvn.set_delay_transform(false); + _igvn.optimize(); + if (C->failing()) return true; + + _igvn.set_delay_transform(true); + // expand "macro" nodes // nodes are removed from the macro list as they are processed while (C->macro_count() > 0) { @@ -2604,12 +2641,6 @@ case Node::Class_AllocateArray: expand_allocate_array(n->as_AllocateArray()); break; - case Node::Class_Lock: - expand_lock_node(n->as_Lock()); - break; - case Node::Class_Unlock: - expand_unlock_node(n->as_Unlock()); - break; default: assert(false, "unknown node type in macro list"); } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/memnode.cpp --- a/src/hotspot/share/opto/memnode.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/memnode.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1555,6 +1555,22 @@ return phi; } +AllocateNode* LoadNode::is_new_object_mark_load(PhaseGVN *phase) const { + if (Opcode() == Op_LoadX) { + Node* address = in(MemNode::Address); + AllocateNode* alloc = AllocateNode::Ideal_allocation(address, phase); + Node* mem = in(MemNode::Memory); + if (alloc != NULL && mem->is_Proj() && + mem->in(0) != NULL && + mem->in(0) == alloc->initialization() && + alloc->initialization()->proj_out_or_null(0) != NULL) { + return alloc; + } + } + return NULL; +} + + //------------------------------Ideal------------------------------------------ // If the load is from Field memory and the pointer is non-null, it might be possible to // zero out the control input. @@ -1683,6 +1699,13 @@ } } + AllocateNode* alloc = is_new_object_mark_load(phase); + if (alloc != NULL && alloc->Opcode() == Op_Allocate && UseBiasedLocking) { + InitializeNode* init = alloc->initialization(); + Node* control = init->proj_out(0); + return alloc->make_ideal_mark(phase, address, control, mem); + } + return progress ? this : NULL; } @@ -1941,6 +1964,12 @@ return Type::get_zero_type(_type->basic_type()); } } + + Node* alloc = is_new_object_mark_load(phase); + if (alloc != NULL && !(alloc->Opcode() == Op_Allocate && UseBiasedLocking)) { + return TypeX::make(markWord::prototype().value()); + } + return _type; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/memnode.hpp --- a/src/hotspot/share/opto/memnode.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/memnode.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -183,6 +183,8 @@ uint _barrier; // Bit field with barrier information + AllocateNode* is_new_object_mark_load(PhaseGVN *phase) const; + protected: virtual bool cmp(const Node &n) const; virtual uint size_of() const; // Size is bigger diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/superword.cpp --- a/src/hotspot/share/opto/superword.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/superword.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -2045,12 +2045,11 @@ for (uint k = 0; k < use->req(); k++) { Node* n = use->in(k); if (def == n) { - // reductions should only have a Phi use at the the loop - // head and out of loop uses + // Reductions should only have a Phi use at the loop head or a non-phi use + // outside of the loop if it is the last element of the pack (e.g. SafePoint). if (def->is_reduction() && ((use->is_Phi() && use->in(0) == _lpt->_head) || - !_lpt->is_member(_phase->get_loop(_phase->ctrl_or_self(use))))) { - assert(i == p->size()-1, "must be last element of the pack"); + (!_lpt->is_member(_phase->get_loop(_phase->ctrl_or_self(use))) && i == p->size()-1))) { continue; } if (!is_vector_use(use, k)) { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/opto/type.hpp --- a/src/hotspot/share/opto/type.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/opto/type.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -1791,6 +1791,7 @@ #define Op_SubX Op_SubL #define Op_XorX Op_XorL #define Op_URShiftX Op_URShiftL +#define Op_LoadX Op_LoadL // conversions #define ConvI2X(x) ConvI2L(x) #define ConvL2X(x) (x) @@ -1838,6 +1839,7 @@ #define Op_SubX Op_SubI #define Op_XorX Op_XorI #define Op_URShiftX Op_URShiftI +#define Op_LoadX Op_LoadI // conversions #define ConvI2X(x) (x) #define ConvL2X(x) ConvL2I(x) diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/prims/jvmtiExport.cpp --- a/src/hotspot/share/prims/jvmtiExport.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/prims/jvmtiExport.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -304,7 +304,7 @@ bool JvmtiExport::_can_modify_any_class = false; bool JvmtiExport::_can_walk_any_space = false; -bool JvmtiExport::_has_redefined_a_class = false; +uint64_t JvmtiExport::_redefinition_count = 0; bool JvmtiExport::_all_dependencies_are_recorded = false; // diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/prims/jvmtiExport.hpp --- a/src/hotspot/share/prims/jvmtiExport.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/prims/jvmtiExport.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -173,10 +173,10 @@ // one or more classes during the lifetime of the VM. The flag should // only be set by the friend class and can be queried by other sub // systems as needed to relax invariant checks. - static bool _has_redefined_a_class; + static uint64_t _redefinition_count; friend class VM_RedefineClasses; - inline static void set_has_redefined_a_class() { - JVMTI_ONLY(_has_redefined_a_class = true;) + inline static void increment_redefinition_count() { + JVMTI_ONLY(_redefinition_count++;) } // Flag to indicate if the compiler has recorded all dependencies. When the // can_redefine_classes capability is enabled in the OnLoad phase then the compiler @@ -188,10 +188,16 @@ public: inline static bool has_redefined_a_class() { - JVMTI_ONLY(return _has_redefined_a_class); + JVMTI_ONLY(return _redefinition_count != 0); NOT_JVMTI(return false); } + // Only set in safepoint, so no memory ordering needed. + inline static uint64_t redefinition_count() { + JVMTI_ONLY(return _redefinition_count); + NOT_JVMTI(return 0); + } + inline static bool all_dependencies_are_recorded() { return _all_dependencies_are_recorded; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/prims/jvmtiRedefineClasses.cpp --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -232,9 +232,9 @@ ResolvedMethodTable::adjust_method_entries(&trace_name_printed); } - // Set flag indicating that some invariants are no longer true. + // Increment flag indicating that some invariants are no longer true. // See jvmtiExport.hpp for detailed explanation. - JvmtiExport::set_has_redefined_a_class(); + JvmtiExport::increment_redefinition_count(); // check_class() is optionally called for product bits, but is // always called for non-product bits. diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/prims/whitebox.cpp --- a/src/hotspot/share/prims/whitebox.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/prims/whitebox.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1735,16 +1735,30 @@ WB_END WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue)) - Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ? - Monitor::_safepoint_check_always : - Monitor::_safepoint_check_never; - Monitor::SafepointCheckFlag sfpt_check_attempted = attemptedNoSafepointValue ? - Monitor::_no_safepoint_check_flag : - Monitor::_safepoint_check_flag; + Mutex::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ? + Mutex::_safepoint_check_always : + Mutex::_safepoint_check_never; + Mutex::SafepointCheckFlag sfpt_check_attempted = attemptedNoSafepointValue ? + Mutex::_no_safepoint_check_flag : + Mutex::_safepoint_check_flag; MutexLocker ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required), sfpt_check_attempted); WB_END +WB_ENTRY(void, WB_AssertSpecialLock(JNIEnv* env, jobject o, jboolean allowVMBlock, jboolean safepointCheck)) + // Create a special lock violating condition in value + Mutex::SafepointCheckRequired sfpt_check_required = safepointCheck ? + Mutex::_safepoint_check_always : + Mutex::_safepoint_check_never; + Mutex::SafepointCheckFlag safepoint_check = safepointCheck ? + Monitor::_safepoint_check_flag : + Monitor::_no_safepoint_check_flag; + + MutexLocker ml(new Mutex(Mutex::special, "SpecialTest_lock", allowVMBlock, sfpt_check_required), safepoint_check); + // If the lock above succeeds, try to safepoint to test the NSV implied with this special lock. + ThreadBlockInVM tbivm(JavaThread::current()); +WB_END + WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj)) oop obj_oop = JNIHandles::resolve(obj); return (jboolean) obj_oop->mark().has_monitor(); @@ -2322,6 +2336,7 @@ {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V", (void*)&WB_AddModuleExportsToAll }, {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, + {CC"assertSpecialLock", CC"(ZZ)V", (void*)&WB_AssertSpecialLock }, {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, {CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool }, diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/arguments.cpp --- a/src/hotspot/share/runtime/arguments.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/arguments.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -526,7 +526,6 @@ { "MinRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() }, { "UseMembar", JDK_Version::jdk(10), JDK_Version::jdk(12), JDK_Version::undefined() }, - { "CompilationPolicyChoice", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() }, { "AllowJNIEnvProxy", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) }, { "ThreadLocalHandshakes", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) }, { "AllowRedefinitionToAddDeleteMethods", JDK_Version::jdk(13), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -534,6 +533,7 @@ { "FieldsAllocationStyle", JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) }, { "CompactFields", JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) }, { "MonitorBound", JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) }, + { "G1RSetScanBlockSize", JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -547,6 +547,7 @@ { "SharedReadOnlySize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, { "SharedMiscDataSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, { "SharedMiscCodeSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, + { "CompilationPolicyChoice", JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) }, { "FailOverToOldVerifier", JDK_Version::undefined(), JDK_Version::jdk(14), JDK_Version::jdk(15) }, { "BindGCTaskThreadsToCPUs", JDK_Version::undefined(), JDK_Version::jdk(14), JDK_Version::jdk(16) }, { "UseGCTaskAffinity", JDK_Version::undefined(), JDK_Version::jdk(14), JDK_Version::jdk(16) }, diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/compilationPolicy.cpp --- a/src/hotspot/share/runtime/compilationPolicy.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/compilationPolicy.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -36,7 +36,6 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/frame.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/rframe.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.hpp" #include "runtime/tieredThresholdPolicy.hpp" @@ -56,28 +55,16 @@ // Determine compilation policy based on command line argument void compilationPolicy_init() { - switch(CompilationPolicyChoice) { - case 0: + #ifdef TIERED + if (TieredCompilation) { + CompilationPolicy::set_policy(new TieredThresholdPolicy()); + } else { CompilationPolicy::set_policy(new SimpleCompPolicy()); - break; + } + #else + CompilationPolicy::set_policy(new SimpleCompPolicy()); + #endif - case 1: -#ifdef COMPILER2 - CompilationPolicy::set_policy(new StackWalkCompPolicy()); -#else - Unimplemented(); -#endif - break; - case 2: -#ifdef TIERED - CompilationPolicy::set_policy(new TieredThresholdPolicy()); -#else - Unimplemented(); -#endif - break; - default: - fatal("CompilationPolicyChoice must be in the range: [0-2]"); - } CompilationPolicy::policy()->initialize(); } @@ -204,7 +191,7 @@ } #ifndef PRODUCT -void NonTieredCompPolicy::trace_osr_completion(nmethod* osr_nm) { +void SimpleCompPolicy::trace_osr_completion(nmethod* osr_nm) { if (TraceOnStackReplacement) { if (osr_nm == NULL) tty->print_cr("compilation failed"); else tty->print_cr("nmethod " INTPTR_FORMAT, p2i(osr_nm)); @@ -212,7 +199,7 @@ } #endif // !PRODUCT -void NonTieredCompPolicy::initialize() { +void SimpleCompPolicy::initialize() { // Setup the compiler thread numbers if (CICompilerCountPerCPU) { // Example: if CICompilerCountPerCPU is true, then we get @@ -246,7 +233,7 @@ // - with COMPILER2 not defined it should return zero for c2 compilation levels. // - with COMPILER1 not defined it should return zero for c1 compilation levels. // - if neither is defined - always return zero. -int NonTieredCompPolicy::compiler_count(CompLevel comp_level) { +int SimpleCompPolicy::compiler_count(CompLevel comp_level) { assert(!TieredCompilation, "This policy should not be used with TieredCompilation"); if (COMPILER2_PRESENT(is_server_compilation_mode_vm() && is_c2_compile(comp_level) ||) is_client_compilation_mode_vm() && is_c1_compile(comp_level)) { @@ -255,7 +242,7 @@ return 0; } -void NonTieredCompPolicy::reset_counter_for_invocation_event(const methodHandle& m) { +void SimpleCompPolicy::reset_counter_for_invocation_event(const methodHandle& m) { // Make sure invocation and backedge counter doesn't overflow again right away // as would be the case for native methods. @@ -269,7 +256,7 @@ assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed"); } -void NonTieredCompPolicy::reset_counter_for_back_branch_event(const methodHandle& m) { +void SimpleCompPolicy::reset_counter_for_back_branch_event(const methodHandle& m) { // Delay next back-branch event but pump up invocation counter to trigger // whole method compilation. MethodCounters* mcs = m->method_counters(); @@ -327,13 +314,13 @@ } // Called at the end of the safepoint -void NonTieredCompPolicy::do_safepoint_work() { +void SimpleCompPolicy::do_safepoint_work() { if(UseCounterDecay && CounterDecay::is_decay_needed()) { CounterDecay::decay(); } } -void NonTieredCompPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { +void SimpleCompPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { ScopeDesc* sd = trap_scope; MethodCounters* mcs; InvocationCounter* c; @@ -359,7 +346,7 @@ // This method can be called by any component of the runtime to notify the policy // that it's recommended to delay the compilation of this method. -void NonTieredCompPolicy::delay_compilation(Method* method) { +void SimpleCompPolicy::delay_compilation(Method* method) { MethodCounters* mcs = method->method_counters(); if (mcs != NULL) { mcs->invocation_counter()->decay(); @@ -367,7 +354,7 @@ } } -void NonTieredCompPolicy::disable_compilation(Method* method) { +void SimpleCompPolicy::disable_compilation(Method* method) { MethodCounters* mcs = method->method_counters(); if (mcs != NULL) { mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing); @@ -375,11 +362,11 @@ } } -CompileTask* NonTieredCompPolicy::select_task(CompileQueue* compile_queue) { +CompileTask* SimpleCompPolicy::select_task(CompileQueue* compile_queue) { return select_task_helper(compile_queue); } -bool NonTieredCompPolicy::is_mature(Method* method) { +bool SimpleCompPolicy::is_mature(Method* method) { MethodData* mdo = method->method_data(); assert(mdo != NULL, "Should be"); uint current = mdo->mileage_of(method); @@ -394,7 +381,7 @@ return (current >= initial + target); } -nmethod* NonTieredCompPolicy::event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, +nmethod* SimpleCompPolicy::event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, CompiledMethod* nm, JavaThread* thread) { assert(comp_level == CompLevel_none, "This should be only called from the interpreter"); NOT_PRODUCT(trace_frequency_counter_overflow(method, branch_bci, bci)); @@ -453,7 +440,7 @@ } #ifndef PRODUCT -void NonTieredCompPolicy::trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci) { +void SimpleCompPolicy::trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci) { if (TraceInvocationCounterOverflow) { MethodCounters* mcs = m->method_counters(); assert(mcs != NULL, "MethodCounters cannot be NULL for profiling"); @@ -485,7 +472,7 @@ } } -void NonTieredCompPolicy::trace_osr_request(const methodHandle& method, nmethod* osr, int bci) { +void SimpleCompPolicy::trace_osr_request(const methodHandle& method, nmethod* osr, int bci) { if (TraceOnStackReplacement) { ResourceMark rm; tty->print(osr != NULL ? "Reused OSR entry for " : "Requesting OSR entry for "); @@ -495,8 +482,6 @@ } #endif // !PRODUCT -// SimpleCompPolicy - compile current method - void SimpleCompPolicy::method_invocation_event(const methodHandle& m, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->invocation_count(); @@ -519,208 +504,3 @@ NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } } -// StackWalkCompPolicy - walk up stack to find a suitable method to compile - -#ifdef COMPILER2 -const char* StackWalkCompPolicy::_msg = NULL; - - -// Consider m for compilation -void StackWalkCompPolicy::method_invocation_event(const methodHandle& m, JavaThread* thread) { - const int comp_level = CompLevel_highest_tier; - const int hot_count = m->invocation_count(); - reset_counter_for_invocation_event(m); - - if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m, comp_level)) { - ResourceMark rm(thread); - frame fr = thread->last_frame(); - assert(fr.is_interpreted_frame(), "must be interpreted"); - assert(fr.interpreter_frame_method() == m(), "bad method"); - - RegisterMap reg_map(thread, false); - javaVFrame* triggerVF = thread->last_java_vframe(®_map); - // triggerVF is the frame that triggered its counter - RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m()); - - if (first->top_method()->code() != NULL) { - // called obsolete method/nmethod -- no need to recompile - } else { - GrowableArray* stack = new GrowableArray(50); - stack->push(first); - RFrame* top = findTopInlinableFrame(stack); - assert(top != NULL, "findTopInlinableFrame returned null"); - CompileBroker::compile_method(top->top_method(), InvocationEntryBci, comp_level, - m, hot_count, CompileTask::Reason_InvocationCount, thread); - } - } -} - -void StackWalkCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) { - const int comp_level = CompLevel_highest_tier; - const int hot_count = m->backedge_count(); - - if (is_compilation_enabled() && can_be_osr_compiled(m, comp_level)) { - CompileBroker::compile_method(m, bci, comp_level, m, hot_count, CompileTask::Reason_BackedgeCount, thread); - NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) - } -} - -RFrame* StackWalkCompPolicy::findTopInlinableFrame(GrowableArray* stack) { - // go up the stack until finding a frame that (probably) won't be inlined - // into its caller - RFrame* current = stack->at(0); // current choice for stopping - assert( current && !current->is_compiled(), "" ); - const char* msg = NULL; - - while (1) { - - // before going up the stack further, check if doing so would get us into - // compiled code - RFrame* next = senderOf(current, stack); - if( !next ) // No next frame up the stack? - break; // Then compile with current frame - - Method* m = current->top_method(); - Method* next_m = next->top_method(); - - if( !Inline ) { // Inlining turned off - msg = "Inlining turned off"; - break; - } - if (next_m->is_not_compilable()) { // Did fail to compile this before/ - msg = "caller not compilable"; - break; - } - if (next->num() > MaxRecompilationSearchLength) { - // don't go up too high when searching for recompilees - msg = "don't go up any further: > MaxRecompilationSearchLength"; - break; - } - if (next->distance() > MaxInterpretedSearchLength) { - // don't go up too high when searching for recompilees - msg = "don't go up any further: next > MaxInterpretedSearchLength"; - break; - } - // Compiled frame above already decided not to inline; - // do not recompile him. - if (next->is_compiled()) { - msg = "not going up into optimized code"; - break; - } - - // Interpreted frame above us was already compiled. Do not force - // a recompile, although if the frame above us runs long enough an - // OSR might still happen. - if( current->is_interpreted() && next_m->has_compiled_code() ) { - msg = "not going up -- already compiled caller"; - break; - } - - // Compute how frequent this call site is. We have current method 'm'. - // We know next method 'next_m' is interpreted. Find the call site and - // check the various invocation counts. - int invcnt = 0; // Caller counts - if (ProfileInterpreter) { - invcnt = next_m->interpreter_invocation_count(); - } - int cnt = 0; // Call site counts - if (ProfileInterpreter && next_m->method_data() != NULL) { - ResourceMark rm; - int bci = next->top_vframe()->bci(); - ProfileData* data = next_m->method_data()->bci_to_data(bci); - if (data != NULL && data->is_CounterData()) - cnt = data->as_CounterData()->count(); - } - - // Caller counts / call-site counts; i.e. is this call site - // a hot call site for method next_m? - int freq = (invcnt) ? cnt/invcnt : cnt; - - // Check size and frequency limits - if ((msg = shouldInline(m, freq, cnt)) != NULL) { - break; - } - // Check inlining negative tests - if ((msg = shouldNotInline(m)) != NULL) { - break; - } - - - // If the caller method is too big or something then we do not want to - // compile it just to inline a method - if (!can_be_compiled(next_m, CompLevel_any)) { - msg = "caller cannot be compiled"; - break; - } - - if( next_m->name() == vmSymbols::class_initializer_name() ) { - msg = "do not compile class initializer (OSR ok)"; - break; - } - - current = next; - } - - assert( !current || !current->is_compiled(), "" ); - - return current; -} - -RFrame* StackWalkCompPolicy::senderOf(RFrame* rf, GrowableArray* stack) { - RFrame* sender = rf->caller(); - if (sender && sender->num() == stack->length()) stack->push(sender); - return sender; -} - - -const char* StackWalkCompPolicy::shouldInline(const methodHandle& m, float freq, int cnt) { - // Allows targeted inlining - // positive filter: should send be inlined? returns NULL (--> yes) - // or rejection msg - int max_size = MaxInlineSize; - int cost = m->code_size(); - - // Check for too many throws (and not too huge) - if (m->interpreter_throwout_count() > InlineThrowCount && cost < InlineThrowMaxSize ) { - return NULL; - } - - // bump the max size if the call is frequent - if ((freq >= InlineFrequencyRatio) || (cnt >= InlineFrequencyCount)) { - if (TraceFrequencyInlining) { - tty->print("(Inlined frequent method)\n"); - m->print(); - } - max_size = FreqInlineSize; - } - if (cost > max_size) { - return (_msg = "too big"); - } - return NULL; -} - - -const char* StackWalkCompPolicy::shouldNotInline(const methodHandle& m) { - // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg - if (m->is_abstract()) return (_msg = "abstract method"); - // note: we allow ik->is_abstract() - if (!m->method_holder()->is_initialized()) return (_msg = "method holder not initialized"); - if (m->is_native()) return (_msg = "native method"); - CompiledMethod* m_code = m->code(); - if (m_code != NULL && m_code->code_size() > InlineSmallCode) - return (_msg = "already compiled into a big method"); - - // use frequency-based objections only for non-trivial methods - if (m->code_size() <= MaxTrivialSize) return NULL; - if (UseInterpreter) { // don't use counts with -Xcomp - if ((m->code() == NULL) && m->was_never_executed()) return (_msg = "never executed"); - if (!m->was_executed_more_than(MIN2(MinInliningThreshold, CompileThreshold >> 1))) return (_msg = "executed < MinInliningThreshold times"); - } - if (Method::has_unloaded_classes_in_signature(m, JavaThread::current())) return (_msg = "unloaded signature classes"); - - return NULL; -} - - - -#endif // COMPILER2 diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/compilationPolicy.hpp --- a/src/hotspot/share/runtime/compilationPolicy.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/compilationPolicy.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -36,7 +36,6 @@ // interpreted). class CompileTask; class CompileQueue; -class RFrame; class CompilationPolicy : public CHeapObj { static CompilationPolicy* _policy; @@ -85,17 +84,19 @@ virtual bool should_not_inline(ciEnv* env, ciMethod* method) { return false; } }; -// A base class for baseline policies. -class NonTieredCompPolicy : public CompilationPolicy { +// A simple compilation policy. +class SimpleCompPolicy : public CompilationPolicy { int _compiler_count; -protected: + private: static void trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci); static void trace_osr_request(const methodHandle& method, nmethod* osr, int bci); static void trace_osr_completion(nmethod* osr_nm); void reset_counter_for_invocation_event(const methodHandle& method); void reset_counter_for_back_branch_event(const methodHandle& method); -public: - NonTieredCompPolicy() : _compiler_count(0) { } + void method_invocation_event(const methodHandle& m, JavaThread* thread); + void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread); + public: + SimpleCompPolicy() : _compiler_count(0) { } virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; } virtual int compiler_count(CompLevel comp_level); virtual void do_safepoint_work(); @@ -106,38 +107,7 @@ virtual void initialize(); virtual CompileTask* select_task(CompileQueue* compile_queue); virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, CompiledMethod* nm, JavaThread* thread); - virtual void method_invocation_event(const methodHandle& m, JavaThread* thread) = 0; - virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) = 0; -}; - -class SimpleCompPolicy : public NonTieredCompPolicy { - public: - virtual void method_invocation_event(const methodHandle& m, JavaThread* thread); - virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread); }; -// StackWalkCompPolicy - existing C2 policy - -#ifdef COMPILER2 -class StackWalkCompPolicy : public NonTieredCompPolicy { - public: - virtual void method_invocation_event(const methodHandle& m, JavaThread* thread); - virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread); - - private: - RFrame* findTopInlinableFrame(GrowableArray* stack); - RFrame* senderOf(RFrame* rf, GrowableArray* stack); - - // the following variables hold values computed by the last inlining decision - // they are used for performance debugging only (print better messages) - static const char* _msg; // reason for not inlining - - static const char* shouldInline (const methodHandle& callee, float frequency, int cnt); - // positive filter: should send be inlined? returns NULL (--> yes) or rejection msg - static const char* shouldNotInline(const methodHandle& callee); - // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg - -}; -#endif #endif // SHARE_RUNTIME_COMPILATIONPOLICY_HPP diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/globals.hpp --- a/src/hotspot/share/runtime/globals.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/globals.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -1017,10 +1017,6 @@ "Inject thread creation failures for " \ "UseDynamicNumberOfCompilerThreads") \ \ - product(intx, CompilationPolicyChoice, 0, \ - "which compilation policy (0-2)") \ - range(0, 2) \ - \ develop(bool, UseStackBanging, true, \ "use stack banging for stack overflow checks (required for " \ "proper StackOverflow handling; disable only to measure cost " \ @@ -2143,14 +2139,6 @@ "% of CompileThreshold) before profiling in the interpreter") \ range(0, 100) \ \ - develop(intx, MaxRecompilationSearchLength, 10, \ - "The maximum number of frames to inspect when searching for " \ - "recompilee") \ - \ - develop(intx, MaxInterpretedSearchLength, 3, \ - "The maximum number of interpreted frames to skip when searching "\ - "for recompilee") \ - \ develop(intx, DesiredMethodLimit, 8000, \ "The desired maximum method size (in bytecodes) after inlining") \ \ diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/mutex.cpp --- a/src/hotspot/share/runtime/mutex.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/mutex.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -282,6 +282,11 @@ assert(_safepoint_check_required != _safepoint_check_sometimes || is_sometimes_ok(name), "Lock has _safepoint_check_sometimes %s", name); + + assert(_rank > special || _allow_vm_block, + "Special locks or below should allow the vm to block"); + assert(_rank > special || _safepoint_check_required == _safepoint_check_never, + "Special locks or below should never safepoint"); #endif } @@ -388,17 +393,13 @@ // NSV implied with locking allow_vm_block or !safepoint_check locks. void Mutex::no_safepoint_verifier(Thread* thread, bool enable) { - // Threads_lock is special, since the safepoint synchronization will not start before this is - // acquired. Hence, a JavaThread cannot be holding it at a safepoint. So is VMOperationRequest_lock, - // since it is used to transfer control between JavaThreads and the VMThread - // Do not *exclude* any locks unless you are absolutely sure it is correct. Ask someone else first! - if ((_allow_vm_block && - this != Threads_lock && - this != Compile_lock && // Temporary: should not be necessary when we get separate compilation - this != tty_lock && // The tty_lock is released for the safepoint. - this != VMOperationRequest_lock && - this != VMOperationQueue_lock) || - rank() == Mutex::special) { + // The tty_lock is special because it is released for the safepoint by + // the safepoint mechanism. + if (this == tty_lock) { + return; + } + + if (_allow_vm_block) { if (enable) { thread->_no_safepoint_count++; } else { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/mutexLocker.cpp --- a/src/hotspot/share/runtime/mutexLocker.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/mutexLocker.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -135,6 +135,7 @@ Mutex* MetaspaceExpand_lock = NULL; Mutex* ClassLoaderDataGraph_lock = NULL; Monitor* ThreadsSMRDelete_lock = NULL; +Mutex* ThreadIdTableCreate_lock = NULL; Mutex* SharedDecoder_lock = NULL; Mutex* DCmdFactory_lock = NULL; #if INCLUDE_NMT @@ -190,147 +191,148 @@ #endif #define def(var, type, pri, vm_block, safepoint_check_allowed ) { \ - var = new type(Mutex::pri, #var, vm_block, safepoint_check_allowed); \ + var = new type(Mutex::pri, #var, vm_block, Mutex::safepoint_check_allowed); \ assert(_num_mutex < MAX_NUM_MUTEX, "increase MAX_NUM_MUTEX"); \ _mutex_array[_num_mutex++] = var; \ } // Using Padded subclasses to prevent false sharing of these global monitors and mutexes. void mutex_init() { - def(tty_lock , PaddedMutex , tty, true, Monitor::_safepoint_check_never); // allow to lock in VM + def(tty_lock , PaddedMutex , tty, true, _safepoint_check_never); // allow to lock in VM - def(CGC_lock , PaddedMonitor, special, true, Monitor::_safepoint_check_never); // coordinate between fore- and background GC - def(STS_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); + def(CGC_lock , PaddedMonitor, special, true, _safepoint_check_never); // coordinate between fore- and background GC + def(STS_lock , PaddedMonitor, leaf, true, _safepoint_check_never); - def(FullGCCount_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent + def(FullGCCount_lock , PaddedMonitor, leaf, true, _safepoint_check_never); // in support of ExplicitGCInvokesConcurrent if (UseG1GC) { - def(DirtyCardQ_CBL_mon , PaddedMonitor, access, true, Monitor::_safepoint_check_never); - def(Shared_DirtyCardQ_lock , PaddedMutex , access + 1, true, Monitor::_safepoint_check_never); + def(DirtyCardQ_CBL_mon , PaddedMonitor, access, true, _safepoint_check_never); + def(Shared_DirtyCardQ_lock , PaddedMutex , access + 1, true, _safepoint_check_never); - def(FreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); - def(OldSets_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); - def(RootRegionScan_lock , PaddedMonitor, leaf , true, Monitor::_safepoint_check_never); + def(FreeList_lock , PaddedMutex , leaf , true, _safepoint_check_never); + def(OldSets_lock , PaddedMutex , leaf , true, _safepoint_check_never); + def(RootRegionScan_lock , PaddedMonitor, leaf , true, _safepoint_check_never); - def(StringDedupQueue_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); - def(StringDedupTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); + def(StringDedupQueue_lock , PaddedMonitor, leaf, true, _safepoint_check_never); + def(StringDedupTable_lock , PaddedMutex , leaf, true, _safepoint_check_never); - def(MarkStackFreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); - def(MarkStackChunkList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); + def(MarkStackFreeList_lock , PaddedMutex , leaf , true, _safepoint_check_never); + def(MarkStackChunkList_lock , PaddedMutex , leaf , true, _safepoint_check_never); - def(MonitoringSupport_lock , PaddedMutex , native , true, Monitor::_safepoint_check_never); // used for serviceability monitoring support + def(MonitoringSupport_lock , PaddedMutex , native , true, _safepoint_check_never); // used for serviceability monitoring support } if (UseShenandoahGC) { - def(StringDedupQueue_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); - def(StringDedupTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); + def(StringDedupQueue_lock , PaddedMonitor, leaf, true, _safepoint_check_never); + def(StringDedupTable_lock , PaddedMutex , leaf, true, _safepoint_check_never); } - def(ParGCRareEvent_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_always); - def(CGCPhaseManager_lock , PaddedMonitor, leaf, false, Monitor::_safepoint_check_always); - def(CodeCache_lock , PaddedMonitor, special, true, Monitor::_safepoint_check_never); - def(RawMonitor_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never); - def(OopMapCacheAlloc_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation. + def(ParGCRareEvent_lock , PaddedMutex , leaf , true, _safepoint_check_always); + def(CGCPhaseManager_lock , PaddedMonitor, leaf, false, _safepoint_check_always); + def(CodeCache_lock , PaddedMonitor, special, true, _safepoint_check_never); + def(RawMonitor_lock , PaddedMutex , special, true, _safepoint_check_never); + def(OopMapCacheAlloc_lock , PaddedMutex , leaf, true, _safepoint_check_always); // used for oop_map_cache allocation. - def(MetaspaceExpand_lock , PaddedMutex , leaf-1, true, Monitor::_safepoint_check_never); - def(ClassLoaderDataGraph_lock , PaddedMutex , nonleaf, false, Monitor::_safepoint_check_always); + def(MetaspaceExpand_lock , PaddedMutex , leaf-1, true, _safepoint_check_never); + def(ClassLoaderDataGraph_lock , PaddedMutex , nonleaf, false, _safepoint_check_always); - def(Patching_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never); // used for safepointing and code patching. - def(CompiledMethod_lock , PaddedMutex , special-1, true, Monitor::_safepoint_check_never); - def(Service_lock , PaddedMonitor, special, true, Monitor::_safepoint_check_never); // used for service thread operations - def(JmethodIdCreation_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // used for creating jmethodIDs. + def(Patching_lock , PaddedMutex , special, true, _safepoint_check_never); // used for safepointing and code patching. + def(CompiledMethod_lock , PaddedMutex , special-1, true, _safepoint_check_never); + def(Service_lock , PaddedMonitor, special, true, _safepoint_check_never); // used for service thread operations + def(JmethodIdCreation_lock , PaddedMutex , leaf, true, _safepoint_check_always); // used for creating jmethodIDs. - def(SystemDictionary_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_always); - def(ProtectionDomainSet_lock , PaddedMutex , leaf-1, true, Monitor::_safepoint_check_never); - def(SharedDictionary_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); - def(Module_lock , PaddedMutex , leaf+2, false, Monitor::_safepoint_check_always); - def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); - def(VMStatistic_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); - def(ExpandHeap_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // Used during compilation by VM thread - def(JNIHandleBlockFreeList_lock , PaddedMutex , leaf-1, true, Monitor::_safepoint_check_never); // handles are used by VM thread - def(SignatureHandlerLibrary_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); - def(SymbolArena_lock , PaddedMutex , leaf+2, true, Monitor::_safepoint_check_never); - def(ProfilePrint_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing - def(ExceptionCache_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing - def(Debug1_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); + def(SystemDictionary_lock , PaddedMonitor, leaf, true, _safepoint_check_always); + def(ProtectionDomainSet_lock , PaddedMutex , leaf-1, true, _safepoint_check_never); + def(SharedDictionary_lock , PaddedMutex , leaf, true, _safepoint_check_always); + def(Module_lock , PaddedMutex , leaf+2, false, _safepoint_check_always); + def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, _safepoint_check_never); + def(VMStatistic_lock , PaddedMutex , leaf, false, _safepoint_check_always); + def(ExpandHeap_lock , PaddedMutex , leaf, true, _safepoint_check_always); // Used during compilation by VM thread + def(JNIHandleBlockFreeList_lock , PaddedMutex , leaf-1, true, _safepoint_check_never); // handles are used by VM thread + def(SignatureHandlerLibrary_lock , PaddedMutex , leaf, false, _safepoint_check_always); + def(SymbolArena_lock , PaddedMutex , leaf+2, true, _safepoint_check_never); + def(ProfilePrint_lock , PaddedMutex , leaf, false, _safepoint_check_always); // serial profile printing + def(ExceptionCache_lock , PaddedMutex , leaf, false, _safepoint_check_always); // serial profile printing + def(Debug1_lock , PaddedMutex , leaf, true, _safepoint_check_never); #ifndef PRODUCT - def(FullGCALot_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe + def(FullGCALot_lock , PaddedMutex , leaf, false, _safepoint_check_always); // a lock to make FullGCALot MT safe #endif - def(BeforeExit_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_always); - def(PerfDataMemAlloc_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // used for allocating PerfData memory for performance data - def(PerfDataManager_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // used for synchronized access to PerfDataManager resources + def(BeforeExit_lock , PaddedMonitor, leaf, true, _safepoint_check_always); + def(PerfDataMemAlloc_lock , PaddedMutex , leaf, true, _safepoint_check_always); // used for allocating PerfData memory for performance data + def(PerfDataManager_lock , PaddedMutex , leaf, true, _safepoint_check_always); // used for synchronized access to PerfDataManager resources // CMS_modUnionTable_lock leaf // CMS_bitMap_lock leaf 1 // CMS_freeList_lock leaf 2 - def(Threads_lock , PaddedMonitor, barrier, true, Monitor::_safepoint_check_always); // Used for safepoint protocol. - def(NonJavaThreadsList_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never); - def(NonJavaThreadsListSync_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never); + def(Threads_lock , PaddedMonitor, barrier, true, _safepoint_check_always); // Used for safepoint protocol. + def(NonJavaThreadsList_lock , PaddedMutex, leaf, true, _safepoint_check_never); + def(NonJavaThreadsListSync_lock , PaddedMutex, leaf, true, _safepoint_check_never); - def(VMOperationQueue_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_never); // VM_thread allowed to block on these - def(VMOperationRequest_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); - def(RetData_lock , PaddedMutex , nonleaf, false, Monitor::_safepoint_check_always); - def(Terminator_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); - def(InitCompleted_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); - def(VtableStubs_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never); - def(Notify_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); - def(JNICritical_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); // used for JNI critical regions - def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_always); + def(VMOperationQueue_lock , PaddedMonitor, nonleaf, true, _safepoint_check_never); // VM_thread allowed to block on these + def(VMOperationRequest_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); + def(RetData_lock , PaddedMutex , nonleaf, false, _safepoint_check_always); + def(Terminator_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); + def(InitCompleted_lock , PaddedMonitor, leaf, true, _safepoint_check_never); + def(VtableStubs_lock , PaddedMutex , nonleaf, true, _safepoint_check_never); + def(Notify_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); + def(JNICritical_lock , PaddedMonitor, nonleaf, true, _safepoint_check_always); // used for JNI critical regions + def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, _safepoint_check_always); - def(Heap_lock , PaddedMonitor, nonleaf+1, false, Monitor::_safepoint_check_sometimes); // Doesn't safepoint check during termination. - def(JfieldIdCreation_lock , PaddedMutex , nonleaf+1, true, Monitor::_safepoint_check_always); // jfieldID, Used in VM_Operation + def(Heap_lock , PaddedMonitor, nonleaf+1, false, _safepoint_check_sometimes); // Doesn't safepoint check during termination. + def(JfieldIdCreation_lock , PaddedMutex , nonleaf+1, true, _safepoint_check_always); // jfieldID, Used in VM_Operation - def(CompiledIC_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_never); // locks VtableStubs_lock, InlineCacheBuffer_lock - def(CompileTaskAlloc_lock , PaddedMutex , nonleaf+2, true, Monitor::_safepoint_check_always); - def(CompileStatistics_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); - def(DirectivesStack_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never); - def(MultiArray_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); + def(CompiledIC_lock , PaddedMutex , nonleaf+2, false, _safepoint_check_never); // locks VtableStubs_lock, InlineCacheBuffer_lock + def(CompileTaskAlloc_lock , PaddedMutex , nonleaf+2, true, _safepoint_check_always); + def(CompileStatistics_lock , PaddedMutex , nonleaf+2, false, _safepoint_check_always); + def(DirectivesStack_lock , PaddedMutex , special, true, _safepoint_check_never); + def(MultiArray_lock , PaddedMutex , nonleaf+2, false, _safepoint_check_always); - def(JvmtiThreadState_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController - def(Management_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); // used for JVM management + def(JvmtiThreadState_lock , PaddedMutex , nonleaf+2, false, _safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController + def(Management_lock , PaddedMutex , nonleaf+2, false, _safepoint_check_always); // used for JVM management - def(Compile_lock , PaddedMutex , nonleaf+3, true, Monitor::_safepoint_check_always); - def(MethodData_lock , PaddedMutex , nonleaf+3, false, Monitor::_safepoint_check_always); - def(TouchedMethodLog_lock , PaddedMutex , nonleaf+3, false, Monitor::_safepoint_check_always); + def(Compile_lock , PaddedMutex , nonleaf+3, false, _safepoint_check_always); + def(MethodData_lock , PaddedMutex , nonleaf+3, false, _safepoint_check_always); + def(TouchedMethodLog_lock , PaddedMutex , nonleaf+3, false, _safepoint_check_always); - def(MethodCompileQueue_lock , PaddedMonitor, nonleaf+4, false, Monitor::_safepoint_check_always); - def(Debug2_lock , PaddedMutex , nonleaf+4, true, Monitor::_safepoint_check_never); - def(Debug3_lock , PaddedMutex , nonleaf+4, true, Monitor::_safepoint_check_never); - def(CompileThread_lock , PaddedMonitor, nonleaf+5, false, Monitor::_safepoint_check_always); - def(PeriodicTask_lock , PaddedMonitor, nonleaf+5, true, Monitor::_safepoint_check_always); - def(RedefineClasses_lock , PaddedMonitor, nonleaf+5, true, Monitor::_safepoint_check_always); + def(MethodCompileQueue_lock , PaddedMonitor, nonleaf+4, false, _safepoint_check_always); + def(Debug2_lock , PaddedMutex , nonleaf+4, true, _safepoint_check_never); + def(Debug3_lock , PaddedMutex , nonleaf+4, true, _safepoint_check_never); + def(CompileThread_lock , PaddedMonitor, nonleaf+5, false, _safepoint_check_always); + def(PeriodicTask_lock , PaddedMonitor, nonleaf+5, true, _safepoint_check_always); + def(RedefineClasses_lock , PaddedMonitor, nonleaf+5, true, _safepoint_check_always); if (WhiteBoxAPI) { - def(Compilation_lock , PaddedMonitor, leaf, false, Monitor::_safepoint_check_never); + def(Compilation_lock , PaddedMonitor, leaf, false, _safepoint_check_never); } #if INCLUDE_JFR - def(JfrMsg_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_always); - def(JfrBuffer_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); - def(JfrStream_lock , PaddedMutex , leaf+1, true, Monitor::_safepoint_check_never); // ensure to rank lower than 'safepoint' - def(JfrStacktrace_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never); - def(JfrThreadSampler_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); + def(JfrMsg_lock , PaddedMonitor, leaf, true, _safepoint_check_always); + def(JfrBuffer_lock , PaddedMutex , leaf, true, _safepoint_check_never); + def(JfrStream_lock , PaddedMutex , leaf+1, true, _safepoint_check_never); // ensure to rank lower than 'safepoint' + def(JfrStacktrace_lock , PaddedMutex , special, true, _safepoint_check_never); + def(JfrThreadSampler_lock , PaddedMonitor, leaf, true, _safepoint_check_never); #endif #ifndef SUPPORTS_NATIVE_CX8 - def(UnsafeJlong_lock , PaddedMutex , special, false, Monitor::_safepoint_check_never); + def(UnsafeJlong_lock , PaddedMutex , special, false, _safepoint_check_never); #endif - def(CodeHeapStateAnalytics_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); - def(NMethodSweeperStats_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never); - def(ThreadsSMRDelete_lock , PaddedMonitor, special, true, Monitor::_safepoint_check_never); - def(SharedDecoder_lock , PaddedMutex , native, false, Monitor::_safepoint_check_never); - def(DCmdFactory_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); + def(CodeHeapStateAnalytics_lock , PaddedMutex , leaf, true, _safepoint_check_never); + def(NMethodSweeperStats_lock , PaddedMutex , special, true, _safepoint_check_never); + def(ThreadsSMRDelete_lock , PaddedMonitor, special, true, _safepoint_check_never); + def(ThreadIdTableCreate_lock , PaddedMutex , leaf, false, _safepoint_check_always); + def(SharedDecoder_lock , PaddedMutex , native, false, _safepoint_check_never); + def(DCmdFactory_lock , PaddedMutex , leaf, true, _safepoint_check_never); #if INCLUDE_NMT - def(NMTQuery_lock , PaddedMutex , max_nonleaf, false, Monitor::_safepoint_check_always); + def(NMTQuery_lock , PaddedMutex , max_nonleaf, false, _safepoint_check_always); #endif #if INCLUDE_CDS #if INCLUDE_JVMTI - def(CDSClassFileStream_lock , PaddedMutex , max_nonleaf, false, Monitor::_safepoint_check_always); + def(CDSClassFileStream_lock , PaddedMutex , max_nonleaf, false, _safepoint_check_always); #endif #if INCLUDE_JVMCI - def(JVMCI_lock , PaddedMonitor, nonleaf+2, true, Monitor::_safepoint_check_always); + def(JVMCI_lock , PaddedMonitor, nonleaf+2, true, _safepoint_check_always); #endif - def(DumpTimeTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); + def(DumpTimeTable_lock , PaddedMutex , leaf, true, _safepoint_check_never); #endif // INCLUDE_CDS } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/mutexLocker.hpp --- a/src/hotspot/share/runtime/mutexLocker.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/mutexLocker.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -115,6 +115,7 @@ extern Monitor* PeriodicTask_lock; // protects the periodic task structure extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition extern Monitor* ThreadsSMRDelete_lock; // Used by ThreadsSMRSupport to take pressure off the Threads_lock +extern Mutex* ThreadIdTableCreate_lock; // Used by ThreadIdTable to lazily create the thread id table extern Mutex* SharedDecoder_lock; // serializes access to the decoder during normal (not error reporting) use extern Mutex* DCmdFactory_lock; // serialize access to DCmdFactory information #if INCLUDE_NMT diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/rframe.cpp --- a/src/hotspot/share/runtime/rframe.cpp Mon Sep 30 20:16:48 2019 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "code/codeCache.hpp" -#include "interpreter/interpreter.hpp" -#include "oops/method.inline.hpp" -#include "oops/oop.inline.hpp" -#include "oops/symbol.hpp" -#include "runtime/frame.inline.hpp" -#include "runtime/rframe.hpp" -#include "runtime/vframe.hpp" -#include "runtime/vframe_hp.hpp" - - -static RFrame*const noCaller = (RFrame*) 0x1; // no caller (i.e., initial frame) -static RFrame*const noCallerYet = (RFrame*) 0x0; // caller not yet computed - -RFrame::RFrame(frame fr, JavaThread* thread, RFrame*const callee) : - _fr(fr), _thread(thread), _callee(callee), _num(callee ? callee->num() + 1 : 0) { - _caller = (RFrame*)noCallerYet; - _invocations = 0; - _distance = 0; -} - -void RFrame::set_distance(int d) { - assert(is_compiled() || d >= 0, "should be positive"); - _distance = d; -} - -InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee) -: RFrame(fr, thread, callee) { - RegisterMap map(thread, false); - _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); - _method = _vf->method(); - assert( _vf->is_interpreted_frame(), "must be interpreted"); - init(); -} - -InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, Method* m) -: RFrame(fr, thread, NULL) { - RegisterMap map(thread, false); - _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); - _method = m; - - assert( _vf->is_interpreted_frame(), "must be interpreted"); - init(); -} - -CompiledRFrame::CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee) -: RFrame(fr, thread, callee) { - init(); -} - -CompiledRFrame::CompiledRFrame(frame fr, JavaThread* thread) -: RFrame(fr, thread, NULL) { - init(); -} - -DeoptimizedRFrame::DeoptimizedRFrame(frame fr, JavaThread* thread, RFrame*const callee) -: InterpretedRFrame(fr, thread, callee) {} - -RFrame* RFrame::new_RFrame(frame fr, JavaThread* thread, RFrame*const callee) { - RFrame* rf = NULL; - int dist = callee ? callee->distance() : -1; - if (fr.is_interpreted_frame()) { - rf = new InterpretedRFrame(fr, thread, callee); - dist++; - } else if (fr.is_compiled_frame()) { - // Even deopted frames look compiled because the deopt - // is invisible until it happens. - rf = new CompiledRFrame(fr, thread, callee); - } else { - assert(false, "Unhandled frame type"); - } - if (rf != NULL) { - rf->set_distance(dist); - rf->init(); - } - return rf; -} - -RFrame* RFrame::caller() { - if (_caller != noCallerYet) return (_caller == noCaller) ? NULL : _caller; // already computed caller - - // caller not yet computed; do it now - if (_fr.is_first_java_frame()) { - _caller = (RFrame*)noCaller; - return NULL; - } - - RegisterMap map(_thread, false); - frame sender = _fr.real_sender(&map); - if (sender.is_java_frame()) { - _caller = new_RFrame(sender, thread(), this); - return _caller; - } - - // Real caller is not java related - _caller = (RFrame*)noCaller; - return NULL; -} - -int InterpretedRFrame::cost() const { - return _method->code_size(); // fix this - //return _method->estimated_inline_cost(_receiverKlass); -} - -int CompiledRFrame::cost() const { - CompiledMethod* nm = top_method()->code(); - if (nm != NULL) { - return nm->insts_size(); - } else { - return top_method()->code_size(); - } -} - -void CompiledRFrame::init() { - RegisterMap map(thread(), false); - vframe* vf = vframe::new_vframe(&_fr, &map, thread()); - assert(vf->is_compiled_frame(), "must be compiled"); - _nm = compiledVFrame::cast(vf)->code()->as_nmethod(); - vf = vf->top(); - _vf = javaVFrame::cast(vf); - _method = CodeCache::find_nmethod(_fr.pc())->method(); - assert(_method, "should have found a method"); -#ifndef PRODUCT - _invocations = _method->compiled_invocation_count(); -#endif -} - -void InterpretedRFrame::init() { - _invocations = _method->invocation_count() + _method->backedge_count(); -} - -void RFrame::print(const char* kind) { -#ifndef PRODUCT -#if COMPILER2_OR_JVMCI - int cnt = top_method()->interpreter_invocation_count(); -#else - int cnt = top_method()->invocation_count(); -#endif - tty->print("%3d %s ", _num, is_interpreted() ? "I" : "C"); - top_method()->print_short_name(tty); - tty->print_cr(": inv=%5d(%d) cst=%4d", _invocations, cnt, cost()); -#endif -} - -void CompiledRFrame::print() { - RFrame::print("comp"); -} - -void InterpretedRFrame::print() { - RFrame::print("int."); -} - -void DeoptimizedRFrame::print() { - RFrame::print("deopt."); -} diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/rframe.hpp --- a/src/hotspot/share/runtime/rframe.hpp Mon Sep 30 20:16:48 2019 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_RUNTIME_RFRAME_HPP -#define SHARE_RUNTIME_RFRAME_HPP - -#include "memory/allocation.hpp" -#include "runtime/frame.hpp" - -// rframes ("recompiler frames") decorate stack frames with some extra information -// needed by the recompiler. The recompiler views the stack (at the time of recompilation) -// as a list of rframes. - -class RFrame : public ResourceObj { - protected: - const frame _fr; // my frame - JavaThread* const _thread; // thread where frame resides. - RFrame* _caller; // caller / callee rframes (or NULL) - RFrame*const _callee; - const int _num; // stack frame number (0 = most recent) - int _invocations; // current invocation estimate (for this frame) - // (i.e., how often was this frame called) - int _distance; // recompilation search "distance" (measured in # of interpreted frames) - - RFrame(frame fr, JavaThread* thread, RFrame*const callee); - virtual void init() = 0; // compute invocations, loopDepth, etc. - void print(const char* name); - - public: - - static RFrame* new_RFrame(frame fr, JavaThread* thread, RFrame*const callee); - - virtual bool is_interpreted() const { return false; } - virtual bool is_compiled() const { return false; } - int distance() const { return _distance; } - void set_distance(int d); - int invocations() const { return _invocations; } - int num() const { return _num; } - frame fr() const { return _fr; } - JavaThread* thread() const { return _thread; } - virtual int cost() const = 0; // estimated inlining cost (size) - virtual Method* top_method() const = 0; - virtual javaVFrame* top_vframe() const = 0; - virtual nmethod* nm() const { ShouldNotCallThis(); return NULL; } - - RFrame* caller(); - RFrame* callee() const { return _callee; } - RFrame* parent() const; // rframe containing lexical scope (if any) - virtual void print() = 0; - - static int computeSends(Method* m); - static int computeSends(nmethod* nm); - static int computeCumulSends(Method* m); - static int computeCumulSends(nmethod* nm); -}; - -class CompiledRFrame : public RFrame { // frame containing a compiled method - protected: - nmethod* _nm; - javaVFrame* _vf; // top vframe; may be NULL (for most recent frame) - Method* _method; // top method - - CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee); - void init(); - friend class RFrame; - - public: - CompiledRFrame(frame fr, JavaThread* thread); // for nmethod triggering its counter (callee == NULL) - bool is_compiled() const { return true; } - Method* top_method() const { return _method; } - javaVFrame* top_vframe() const { return _vf; } - nmethod* nm() const { return _nm; } - int cost() const; - void print(); -}; - -class InterpretedRFrame : public RFrame { // interpreter frame - protected: - javaVFrame* _vf; // may be NULL (for most recent frame) - Method* _method; - - InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee); - void init(); - friend class RFrame; - - public: - InterpretedRFrame(frame fr, JavaThread* thread, Method* m); // constructor for method triggering its invocation counter - bool is_interpreted() const { return true; } - Method* top_method() const { return _method; } - javaVFrame* top_vframe() const { return _vf; } - int cost() const; - void print(); -}; - -// treat deoptimized frames as interpreted -class DeoptimizedRFrame : public InterpretedRFrame { - protected: - DeoptimizedRFrame(frame fr, JavaThread* thread, RFrame*const callee); - friend class RFrame; - public: - void print(); -}; - -#endif // SHARE_RUNTIME_RFRAME_HPP diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/sharedRuntime.cpp --- a/src/hotspot/share/runtime/sharedRuntime.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/sharedRuntime.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -1269,6 +1269,7 @@ // will be supported. if (!callee_method->is_old() && (callee == NULL || (callee->is_in_use() && callee_method->code() == callee))) { + NoSafepointVerifier nsv; #ifdef ASSERT // We must not try to patch to jump to an already unloaded method. if (dest_entry_point != 0) { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/threadSMR.cpp --- a/src/hotspot/share/runtime/threadSMR.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/threadSMR.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -26,9 +26,11 @@ #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "runtime/jniHandles.inline.hpp" +#include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadSMR.inline.hpp" #include "runtime/vmOperations.hpp" +#include "services/threadIdTable.hpp" #include "services/threadService.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" @@ -129,7 +131,6 @@ // Impl note: See _to_delete_list_cnt note. uint ThreadsSMRSupport::_to_delete_list_max = 0; - // 'inline' functions first so the definitions are before first use: inline void ThreadsSMRSupport::add_deleted_thread_times(uint add_value) { @@ -608,16 +609,28 @@ } JavaThread* ThreadsList::find_JavaThread_from_java_tid(jlong java_tid) const { - for (uint i = 0; i < length(); i++) { - JavaThread* thread = thread_at(i); - oop tobj = thread->threadObj(); - // Ignore the thread if it hasn't run yet, has exited - // or is starting to exit. - if (tobj != NULL && !thread->is_exiting() && - java_tid == java_lang_Thread::thread_id(tobj)) { - // found a match - return thread; + ThreadIdTable::lazy_initialize(this); + JavaThread* thread = ThreadIdTable::find_thread_by_tid(java_tid); + if (thread == NULL) { + // If the thread is not found in the table find it + // with a linear search and add to the table. + for (uint i = 0; i < length(); i++) { + thread = thread_at(i); + oop tobj = thread->threadObj(); + // Ignore the thread if it hasn't run yet, has exited + // or is starting to exit. + if (tobj != NULL && java_tid == java_lang_Thread::thread_id(tobj)) { + MutexLocker ml(Threads_lock); + // Must be inside the lock to ensure that we don't add a thread to the table + // that has just passed the removal point in ThreadsSMRSupport::remove_thread() + if (!thread->is_exiting()) { + ThreadIdTable::add_thread(java_tid, thread); + return thread; + } + } } + } else if (!thread->is_exiting()) { + return thread; } return NULL; } @@ -742,6 +755,10 @@ ThreadsList *old_list = xchg_java_thread_list(new_list); free_list(old_list); + if (ThreadIdTable::is_initialized()) { + jlong tid = SharedRuntime::get_java_tid(thread); + ThreadIdTable::add_thread(tid, thread); + } } // set_delete_notify() and clear_delete_notify() are called @@ -909,6 +926,10 @@ } void ThreadsSMRSupport::remove_thread(JavaThread *thread) { + if (ThreadIdTable::is_initialized()) { + jlong tid = SharedRuntime::get_java_tid(thread); + ThreadIdTable::remove_thread(tid); + } ThreadsList *new_list = ThreadsList::remove_thread(ThreadsSMRSupport::get_java_thread_list(), thread); if (EnableThreadSMRStatistics) { ThreadsSMRSupport::inc_java_thread_list_alloc_cnt(); diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/tieredThresholdPolicy.hpp --- a/src/hotspot/share/runtime/tieredThresholdPolicy.hpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/tieredThresholdPolicy.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -215,7 +215,6 @@ bool maybe_switch_to_aot(const methodHandle& mh, CompLevel cur_level, CompLevel next_level, JavaThread* thread); -protected: int c1_count() const { return _c1_count; } int c2_count() const { return _c2_count; } void set_c1_count(int x) { _c1_count = x; } @@ -224,11 +223,11 @@ enum EventType { CALL, LOOP, COMPILE, REMOVE_FROM_QUEUE, UPDATE_IN_QUEUE, REPROFILE, MAKE_NOT_ENTRANT }; void print_event(EventType type, const methodHandle& mh, const methodHandle& imh, int bci, CompLevel level); // Print policy-specific information if necessary - virtual void print_specific(EventType type, const methodHandle& mh, const methodHandle& imh, int bci, CompLevel level); + void print_specific(EventType type, const methodHandle& mh, const methodHandle& imh, int bci, CompLevel level); // Check if the method can be compiled, change level if necessary void compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread); // Submit a given method for compilation - virtual void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread); + void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread); // Simple methods are as good being compiled with C1 as C2. // This function tells if it's such a function. inline static bool is_trivial(Method* method); @@ -242,10 +241,10 @@ // Get a compilation level for a given method. static CompLevel comp_level(Method* method); - virtual void method_invocation_event(const methodHandle& method, const methodHandle& inlinee, - CompLevel level, CompiledMethod* nm, JavaThread* thread); - virtual void method_back_branch_event(const methodHandle& method, const methodHandle& inlinee, - int bci, CompLevel level, CompiledMethod* nm, JavaThread* thread); + void method_invocation_event(const methodHandle& method, const methodHandle& inlinee, + CompLevel level, CompiledMethod* nm, JavaThread* thread); + void method_back_branch_event(const methodHandle& method, const methodHandle& inlinee, + int bci, CompLevel level, CompiledMethod* nm, JavaThread* thread); void set_increase_threshold_at_ratio() { _increase_threshold_at_ratio = 100 / (100 - (double)IncreaseFirstTierCompileThresholdAt); } void set_start_time(jlong t) { _start_time = t; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/runtime/vmThread.cpp --- a/src/hotspot/share/runtime/vmThread.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/runtime/vmThread.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -354,9 +354,9 @@ void VMThread::wait_for_vm_thread_exit() { assert(Thread::current()->is_Java_thread(), "Should be a JavaThread"); assert(((JavaThread*)Thread::current())->is_terminated(), "Should be terminated"); - { MutexLocker mu(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); + { MonitorLocker mu(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); _should_terminate = true; - VMOperationQueue_lock->notify(); + mu.notify(); } // Note: VM thread leaves at Safepoint. We are not stopped by Safepoint @@ -620,8 +620,8 @@ // // Notify (potential) waiting Java thread(s) - { MutexLocker mu(VMOperationRequest_lock, Mutex::_no_safepoint_check_flag); - VMOperationRequest_lock->notify_all(); + { MonitorLocker mu(VMOperationRequest_lock, Mutex::_no_safepoint_check_flag); + mu.notify_all(); } // We want to make sure that we get to a safepoint regularly @@ -695,12 +695,11 @@ // VMOperationQueue_lock, so we can block without a safepoint check. This allows vm operation requests // to be queued up during a safepoint synchronization. { - VMOperationQueue_lock->lock_without_safepoint_check(); + MonitorLocker ml(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); log_debug(vmthread)("Adding VM operation: %s", op->name()); _vm_queue->add(op); op->set_timestamp(os::javaTimeMillis()); - VMOperationQueue_lock->notify(); - VMOperationQueue_lock->unlock(); + ml.notify(); } if (!concurrent) { diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/services/management.cpp --- a/src/hotspot/share/services/management.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/services/management.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -2068,6 +2068,31 @@ } #endif // INCLUDE_MANAGEMENT +// Gets the amount of memory allocated on the Java heap for a single thread. +// Returns -1 if the thread does not exist or has terminated. +JVM_ENTRY(jlong, jmm_GetOneThreadAllocatedMemory(JNIEnv *env, jlong thread_id)) + if (thread_id < 0) { + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Invalid thread ID", -1); + } + + if (thread_id == 0) { + // current thread + if (THREAD->is_Java_thread()) { + return ((JavaThread*)THREAD)->cooked_allocated_bytes(); + } + return -1; + } + + ThreadsListHandle tlh; + JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id); + + if (java_thread != NULL) { + return java_thread->cooked_allocated_bytes(); + } + return -1; +JVM_END + // Gets an array containing the amount of memory allocated on the Java // heap for a set of threads (in bytes). Each element of the array is // the amount of memory allocated for the thread ID specified in the @@ -2192,6 +2217,7 @@ jmm_GetMemoryManagers, jmm_GetMemoryPoolUsage, jmm_GetPeakMemoryPoolUsage, + jmm_GetOneThreadAllocatedMemory, jmm_GetThreadAllocatedMemory, jmm_GetMemoryUsage, jmm_GetLongAttribute, diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/services/memoryManager.cpp --- a/src/hotspot/share/services/memoryManager.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/hotspot/share/services/memoryManager.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -178,7 +178,7 @@ _num_collections = 0; _last_gc_stat = NULL; _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true, - Monitor::_safepoint_check_never); + Mutex::_safepoint_check_never); _current_gc_stat = NULL; _num_gc_threads = 1; _notification_enabled = false; diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/services/threadIdTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/services/threadIdTable.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,238 @@ + +/* +* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +* +*/ + +#include "precompiled.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/thread.hpp" +#include "runtime/threadSMR.hpp" +#include "runtime/timerTrace.hpp" +#include "services/threadIdTable.hpp" +#include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" + + +typedef ConcurrentHashTable ThreadIdTableHash; + +// 2^24 is max size +static const size_t END_SIZE = 24; +// Default initial size 256 +static const size_t DEFAULT_TABLE_SIZE_LOG = 8; +// Prefer short chains of avg 2 +static const double PREF_AVG_LIST_LEN = 2.0; +static ThreadIdTableHash* volatile _local_table = NULL; +static volatile size_t _current_size = 0; +static volatile size_t _items_count = 0; + +volatile bool ThreadIdTable::_is_initialized = false; + +class ThreadIdTableEntry : public CHeapObj { +private: + jlong _tid; + JavaThread* _java_thread; +public: + ThreadIdTableEntry(jlong tid, JavaThread* java_thread) : + _tid(tid), _java_thread(java_thread) {} + + jlong tid() const { return _tid; } + JavaThread* thread() const { return _java_thread; } +}; + +class ThreadIdTableConfig : public AllStatic { + public: + typedef ThreadIdTableEntry* Value; + + static uintx get_hash(Value const& value, bool* is_dead) { + jlong tid = value->tid(); + return primitive_hash(tid); + } + static void* allocate_node(size_t size, Value const& value) { + ThreadIdTable::item_added(); + return AllocateHeap(size, mtInternal); + } + static void free_node(void* memory, Value const& value) { + delete value; + FreeHeap(memory); + ThreadIdTable::item_removed(); + } +}; + +static size_t ceil_log2(size_t val) { + size_t ret; + for (ret = 1; ((size_t)1 << ret) < val; ++ret); + return ret; +} + +// Lazily creates the table and populates it with the given +// thread list +void ThreadIdTable::lazy_initialize(const ThreadsList *threads) { + if (!_is_initialized) { + { + // There is no obvious benefits in allowing the thread table + // to be concurently populated during the initalization. + MutexLocker ml(ThreadIdTableCreate_lock); + if (_is_initialized) { + return; + } + create_table(threads->length()); + _is_initialized = true; + } + for (uint i = 0; i < threads->length(); i++) { + JavaThread* thread = threads->thread_at(i); + oop tobj = thread->threadObj(); + if (tobj != NULL) { + jlong java_tid = java_lang_Thread::thread_id(tobj); + MutexLocker ml(Threads_lock); + if (!thread->is_exiting()) { + // Must be inside the lock to ensure that we don't add a thread to the table + // that has just passed the removal point in ThreadsSMRSupport::remove_thread() + add_thread(java_tid, thread); + } + } + } + } +} + +void ThreadIdTable::create_table(size_t size) { + assert(_local_table == NULL, "Thread table is already created"); + size_t size_log = ceil_log2(size); + size_t start_size_log = + size_log > DEFAULT_TABLE_SIZE_LOG ? size_log : DEFAULT_TABLE_SIZE_LOG; + _current_size = (size_t)1 << start_size_log; + _local_table = new ThreadIdTableHash(start_size_log, END_SIZE); +} + +void ThreadIdTable::item_added() { + Atomic::inc(&_items_count); + log_trace(thread, table) ("Thread entry added"); +} + +void ThreadIdTable::item_removed() { + Atomic::dec(&_items_count); + log_trace(thread, table) ("Thread entry removed"); +} + +double ThreadIdTable::get_load_factor() { + return ((double)_items_count) / _current_size; +} + +size_t ThreadIdTable::table_size() { + return (size_t)1 << _local_table->get_size_log2(Thread::current()); +} + +void ThreadIdTable::grow(JavaThread* jt) { + ThreadIdTableHash::GrowTask gt(_local_table); + if (!gt.prepare(jt)) { + return; + } + log_trace(thread, table)("Started to grow"); + TraceTime timer("Grow", TRACETIME_LOG(Debug, membername, table, perf)); + while (gt.do_task(jt)) { + gt.pause(jt); + { + ThreadBlockInVM tbivm(jt); + } + gt.cont(jt); + } + gt.done(jt); + _current_size = table_size(); + log_info(thread, table)("Grown to size:" SIZE_FORMAT, _current_size); +} + +class ThreadIdTableLookup : public StackObj { +private: + jlong _tid; + uintx _hash; +public: + ThreadIdTableLookup(jlong tid) + : _tid(tid), _hash(primitive_hash(tid)) {} + uintx get_hash() const { + return _hash; + } + bool equals(ThreadIdTableEntry** value, bool* is_dead) { + bool equals = primitive_equals(_tid, (*value)->tid()); + if (!equals) { + return false; + } + return true; + } +}; + +class ThreadGet : public StackObj { +private: + JavaThread* _return; +public: + ThreadGet(): _return(NULL) {} + void operator()(ThreadIdTableEntry** val) { + _return = (*val)->thread(); + } + JavaThread* get_res_thread() { + return _return; + } +}; + +void ThreadIdTable::grow_if_required() { + assert(Thread::current()->is_Java_thread(),"Must be Java thread"); + assert(_is_initialized, "Thread table is not initialized"); + double load_factor = get_load_factor(); + log_debug(thread, table)("Concurrent work, load factor: %g", load_factor); + if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { + grow(JavaThread::current()); + } +} + +JavaThread* ThreadIdTable::add_thread(jlong tid, JavaThread* java_thread) { + assert(_is_initialized, "Thread table is not initialized"); + Thread* thread = Thread::current(); + ThreadIdTableLookup lookup(tid); + ThreadGet tg; + while (true) { + if (_local_table->get(thread, lookup, tg)) { + return tg.get_res_thread(); + } + ThreadIdTableEntry* entry = new ThreadIdTableEntry(tid, java_thread); + // The hash table takes ownership of the ThreadTableEntry, + // even if it's not inserted. + if (_local_table->insert(thread, lookup, entry)) { + grow_if_required(); + return java_thread; + } + } +} + +JavaThread* ThreadIdTable::find_thread_by_tid(jlong tid) { + assert(_is_initialized, "Thread table is not initialized"); + Thread* thread = Thread::current(); + ThreadIdTableLookup lookup(tid); + ThreadGet tg; + _local_table->get(thread, lookup, tg); + return tg.get_res_thread(); +} + +bool ThreadIdTable::remove_thread(jlong tid) { + assert(_is_initialized, "Thread table is not initialized"); + Thread* thread = Thread::current(); + ThreadIdTableLookup lookup(tid); + return _local_table->remove(thread, lookup); +} diff -r 7cd20dbeee36 -r 18e27ee2276b src/hotspot/share/services/threadIdTable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/services/threadIdTable.hpp Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,62 @@ + +/* +* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +* +*/ + +#ifndef SHARE_SERVICES_THREADIDTABLE_HPP +#define SHARE_SERVICES_THREADIDTABLE_HPP + +#include "memory/allocation.hpp" + +class JavaThread; +class ThreadsList; +class ThreadIdTableConfig; + +class ThreadIdTable : public AllStatic { + friend class ThreadIdTableConfig; + + static volatile bool _is_initialized; + +public: + // Initialization + static void lazy_initialize(const ThreadsList* threads); + static bool is_initialized() { return _is_initialized; } + + // Lookup and list management + static JavaThread* find_thread_by_tid(jlong tid); + static JavaThread* add_thread(jlong tid, JavaThread* thread); + static bool remove_thread(jlong tid); + +private: + static void create_table(size_t size); + + static size_t table_size(); + static double get_load_factor(); + static void grow_if_required(); + static void grow(JavaThread* jt); + + static void item_added(); + static void item_removed(); +}; + +#endif // SHARE_SERVICES_THREADIDTABLE_HPP diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java --- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,10 +79,26 @@ ArrayList entries = new ArrayList<>(); try { long fp = setmntent(Util.toBytes(fstab), Util.toBytes("r")); + int maxLineSize = 1024; + try { + for (;;) { + int lineSize = getlinelen(fp); + if (lineSize == -1) + break; + if (lineSize > maxLineSize) + maxLineSize = lineSize; + } + } catch (UnixException x) { + // nothing we need to do + } finally { + rewind(fp); + } + try { for (;;) { UnixMountEntry entry = new UnixMountEntry(); - int res = getmntent(fp, entry); + // count in NUL character at the end + int res = getmntent(fp, entry, maxLineSize + 1); if (res < 0) break; entries.add(entry); diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java --- a/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java Mon Sep 30 20:26:28 2019 -0400 @@ -51,7 +51,17 @@ /** * int getmntent(FILE *fp, struct mnttab *mp, int len); */ - static native int getmntent(long fp, UnixMountEntry entry) + + static int getmntent(long fp, UnixMountEntry entry, int buflen) throws UnixException { + NativeBuffer buffer = NativeBuffers.getNativeBuffer(buflen); + try { + return getmntent0(fp, entry, buffer.address(), buflen); + } finally { + buffer.release(); + } + } + + static native int getmntent0(long fp, UnixMountEntry entry, long buffer, int bufLen) throws UnixException; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c --- a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,12 +169,11 @@ } JNIEXPORT jint JNICALL -Java_sun_nio_fs_LinuxNativeDispatcher_getmntent(JNIEnv* env, jclass this, - jlong value, jobject entry) +Java_sun_nio_fs_LinuxNativeDispatcher_getmntent0(JNIEnv* env, jclass this, + jlong value, jobject entry, jlong buffer, jint bufLen) { struct mntent ent; - char buf[1024]; - int buflen = sizeof(buf); + char * buf = (char*)jlong_to_ptr(buffer); struct mntent* m; FILE* fp = jlong_to_ptr(value); jsize len; @@ -184,7 +183,7 @@ char* fstype; char* options; - m = getmntent_r(fp, &ent, (char*)&buf, buflen); + m = getmntent_r(fp, &ent, buf, (int)bufLen); if (m == NULL) return -1; name = m->mnt_fsname; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/io/FilePermission.java --- a/src/java.base/share/classes/java/io/FilePermission.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/io/FilePermission.java Mon Sep 30 20:26:28 2019 -0400 @@ -1196,7 +1196,7 @@ if ((effective & desired) == desired) { return true; } - needed = (desired ^ effective); + needed = (desired & ~effective); } } return false; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/net/SocketPermission.java --- a/src/java.base/share/classes/java/net/SocketPermission.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/net/SocketPermission.java Mon Sep 30 20:26:28 2019 -0400 @@ -1433,7 +1433,7 @@ if ((effective & desired) == desired) { return true; } - needed = (desired ^ effective); + needed = (desired & ~effective); } } return false; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/security/Provider.java --- a/src/java.base/share/classes/java/security/Provider.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/security/Provider.java Mon Sep 30 20:26:28 2019 -0400 @@ -1255,9 +1255,9 @@ } synchronized (this) { ensureLegacyParsed(); - } - if (legacyMap != null && !legacyMap.isEmpty()) { - return legacyMap.get(key); + if (legacyMap != null && !legacyMap.isEmpty()) { + return legacyMap.get(key); + } } return null; } diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/time/Ser.java --- a/src/java.base/share/classes/java/time/Ser.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/time/Ser.java Mon Sep 30 20:26:28 2019 -0400 @@ -61,6 +61,7 @@ import java.io.InvalidClassException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.Serializable; import java.io.StreamCorruptedException; /** @@ -112,7 +113,7 @@ /** The type being serialized. */ private byte type; /** The object being serialized. */ - private Object object; + private Serializable object; /** * Constructor for deserialization. @@ -126,7 +127,7 @@ * @param type the type * @param object the object */ - Ser(byte type, Object object) { + Ser(byte type, Serializable object) { this.type = type; this.object = object; } @@ -224,20 +225,35 @@ * {@code Ser} object. * *
    - *
  • Duration - {@code Duration.ofSeconds(seconds, nanos);} - *
  • Instant - {@code Instant.ofEpochSecond(seconds, nanos);} - *
  • LocalDate - {@code LocalDate.of(year, month, day);} - *
  • LocalDateTime - {@code LocalDateTime.of(date, time);} - *
  • LocalTime - {@code LocalTime.of(hour, minute, second, nano);} - *
  • MonthDay - {@code MonthDay.of(month, day);} - *
  • OffsetTime - {@code OffsetTime.of(time, offset);} - *
  • OffsetDateTime - {@code OffsetDateTime.of(dateTime, offset);} - *
  • Period - {@code Period.of(years, months, days);} - *
  • Year - {@code Year.of(year);} - *
  • YearMonth - {@code YearMonth.of(year, month);} - *
  • ZonedDateTime - {@code ZonedDateTime.ofLenient(dateTime, offset, zone);} - *
  • ZoneId - {@code ZoneId.of(id);} - *
  • ZoneOffset - {@code (offsetByte == 127 ? ZoneOffset.ofTotalSeconds(in.readInt()) : ZoneOffset.ofTotalSeconds(offsetByte * 900));} + *
  • Duration - + * {@code Duration.ofSeconds(seconds, nanos);} + *
  • Instant - + * {@code Instant.ofEpochSecond(seconds, nanos);} + *
  • LocalDate - + * {@code LocalDate.of(year, month, day);} + *
  • LocalDateTime - + * {@code LocalDateTime.of(date, time);} + *
  • LocalTime - + * {@code LocalTime.of(hour, minute, second, nano);} + *
  • MonthDay - + * {@code MonthDay.of(month, day);} + *
  • OffsetTime - + * {@code OffsetTime.of(time, offset);} + *
  • OffsetDateTime - + * {@code OffsetDateTime.of(dateTime, offset);} + *
  • Period - + * {@code Period.of(years, months, days);} + *
  • Year - + * {@code Year.of(year);} + *
  • YearMonth - + * {@code YearMonth.of(year, month);} + *
  • ZonedDateTime - + * {@code ZonedDateTime.ofLenient(dateTime, offset, zone);} + *
  • ZoneId - + * {@code ZoneId.of(id);} + *
  • ZoneOffset - + * {@code (offsetByte == 127 ? ZoneOffset.ofTotalSeconds(in.readInt()) : + * ZoneOffset.ofTotalSeconds(offsetByte * 900));} *
* * @param in the data to read, not null @@ -247,12 +263,13 @@ object = readInternal(type, in); } - static Object read(ObjectInput in) throws IOException, ClassNotFoundException { + static Serializable read(ObjectInput in) throws IOException, ClassNotFoundException { byte type = in.readByte(); return readInternal(type, in); } - private static Object readInternal(byte type, ObjectInput in) throws IOException, ClassNotFoundException { + private static Serializable readInternal(byte type, ObjectInput in) + throws IOException, ClassNotFoundException { switch (type) { case DURATION_TYPE: return Duration.readExternal(in); case INSTANT_TYPE: return Instant.readExternal(in); diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/time/chrono/AbstractChronology.java --- a/src/java.base/share/classes/java/time/chrono/AbstractChronology.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/time/chrono/AbstractChronology.java Mon Sep 30 20:26:28 2019 -0400 @@ -731,7 +731,7 @@ */ @java.io.Serial Object writeReplace() { - return new Ser(Ser.CHRONO_TYPE, this); + return new Ser(Ser.CHRONO_TYPE, (Serializable)this); } /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/time/chrono/Ser.java --- a/src/java.base/share/classes/java/time/chrono/Ser.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/time/chrono/Ser.java Mon Sep 30 20:26:28 2019 -0400 @@ -61,6 +61,7 @@ import java.io.InvalidClassException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.Serializable; import java.io.StreamCorruptedException; import java.time.LocalDate; import java.time.LocalDateTime; @@ -110,7 +111,7 @@ /** The type being serialized. */ private byte type; /** The object being serialized. */ - private Object object; + private Serializable object; /** * Constructor for deserialization. @@ -124,7 +125,7 @@ * @param type the type * @param object the object */ - Ser(byte type, Object object) { + Ser(byte type, Serializable object) { this.type = type; this.object = object; } @@ -203,18 +204,30 @@ * {@code Ser} object. * * * * @param in the data stream to read from, not null @@ -225,16 +238,17 @@ object = readInternal(type, in); } - static Object read(ObjectInput in) throws IOException, ClassNotFoundException { + static Serializable read(ObjectInput in) throws IOException, ClassNotFoundException { byte type = in.readByte(); return readInternal(type, in); } - private static Object readInternal(byte type, ObjectInput in) throws IOException, ClassNotFoundException { + private static Serializable readInternal(byte type, ObjectInput in) + throws IOException, ClassNotFoundException { switch (type) { - case CHRONO_TYPE: return AbstractChronology.readExternal(in); - case CHRONO_LOCAL_DATE_TIME_TYPE: return ChronoLocalDateTimeImpl.readExternal(in); - case CHRONO_ZONE_DATE_TIME_TYPE: return ChronoZonedDateTimeImpl.readExternal(in); + case CHRONO_TYPE: return (Serializable)AbstractChronology.readExternal(in); + case CHRONO_LOCAL_DATE_TIME_TYPE: return (Serializable)ChronoLocalDateTimeImpl.readExternal(in); + case CHRONO_ZONE_DATE_TIME_TYPE: return (Serializable)ChronoZonedDateTimeImpl.readExternal(in); case JAPANESE_DATE_TYPE: return JapaneseDate.readExternal(in); case JAPANESE_ERA_TYPE: return JapaneseEra.readExternal(in); case HIJRAH_DATE_TYPE: return HijrahDate.readExternal(in); diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/time/zone/Ser.java --- a/src/java.base/share/classes/java/time/zone/Ser.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/time/zone/Ser.java Mon Sep 30 20:26:28 2019 -0400 @@ -68,6 +68,7 @@ import java.io.InvalidClassException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.Serializable; import java.io.StreamCorruptedException; import java.time.ZoneOffset; @@ -97,7 +98,7 @@ /** The type being serialized. */ private byte type; /** The object being serialized. */ - private Object object; + private Serializable object; /** * Constructor for deserialization. @@ -111,7 +112,7 @@ * @param type the type * @param object the object */ - Ser(byte type, Object object) { + Ser(byte type, Serializable object) { this.type = type; this.object = object; } @@ -183,12 +184,13 @@ object = readInternal(type, in); } - static Object read(DataInput in) throws IOException, ClassNotFoundException { + static Serializable read(DataInput in) throws IOException, ClassNotFoundException { byte type = in.readByte(); return readInternal(type, in); } - private static Object readInternal(byte type, DataInput in) throws IOException, ClassNotFoundException { + private static Serializable readInternal(byte type, DataInput in) + throws IOException, ClassNotFoundException { switch (type) { case ZRULES: return ZoneRules.readExternal(in); diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Mon Sep 30 20:26:28 2019 -0400 @@ -130,7 +130,7 @@ } public final boolean block() { - while (!isReleasable()) LockSupport.park(this); + while (!isReleasable()) LockSupport.park(); return true; } } diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Mon Sep 30 20:26:28 2019 -0400 @@ -502,7 +502,7 @@ } public final boolean block() { - while (!isReleasable()) LockSupport.park(this); + while (!isReleasable()) LockSupport.park(); return true; } } diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java Mon Sep 30 20:26:28 2019 -0400 @@ -119,6 +119,16 @@ static native void fclose(long stream) throws UnixException; /** + * void rewind(FILE* stream); + */ + static native void rewind(long stream) throws UnixException; + + /** + * ssize_t getline(char **lineptr, size_t *n, FILE *stream); + */ + static native int getlinelen(long stream) throws UnixException; + + /** * link(const char* existing, const char* new) */ static void link(UnixPath existing, UnixPath newfile) throws UnixException { diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c Mon Sep 30 20:26:28 2019 -0400 @@ -403,6 +403,51 @@ } } +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_rewind(JNIEnv* env, jclass this, jlong stream) +{ + FILE* fp = jlong_to_ptr(stream); + int saved_errno; + + errno = 0; + rewind(fp); + saved_errno = errno; + if (ferror(fp)) { + throwUnixException(env, saved_errno); + } +} + +/** + * This function returns line length without NUL terminator or -1 on EOF. + */ +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getlinelen(JNIEnv* env, jclass this, jlong stream) +{ + FILE* fp = jlong_to_ptr(stream); + size_t lineSize = 0; + char * lineBuffer = NULL; + int saved_errno; + + ssize_t res = getline(&lineBuffer, &lineSize, fp); + saved_errno = errno; + + /* Should free lineBuffer no matter result, according to man page */ + if (lineBuffer != NULL) + free(lineBuffer); + + if (feof(fp)) + return -1; + + /* On successfull return res >= 0, otherwise res is -1 */ + if (res == -1) + throwUnixException(env, saved_errno); + + if (res > INT_MAX) + throwUnixException(env, EOVERFLOW); + + return (jint)res; +} + JNIEXPORT jint JNICALL Java_sun_nio_fs_UnixNativeDispatcher_open0(JNIEnv* env, jclass this, jlong pathAddress, jint oflags, jint mode) diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,8 +108,9 @@ private static final short OFFSETOF_FIND_DATA_SIZELOW = 32; private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36; - // used to adjust values between Windows and java epoch - private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; + // used to adjust values between Windows and java epochs + private static final long WINDOWS_EPOCH_IN_MICROS = -11644473600000000L; + private static final long WINDOWS_EPOCH_IN_100NS = -116444736000000000L; // indicates if accurate metadata is required (interesting on NTFS only) private static final boolean ensureAccurateMetadata; @@ -137,24 +138,23 @@ * since January 1, 1601 to a FileTime. */ static FileTime toFileTime(long time) { - // 100ns -> us - time /= 10L; - // adjust to java epoch - time += WINDOWS_EPOCH_IN_MICROSECONDS; - return FileTime.from(time, TimeUnit.MICROSECONDS); + try { + long adjusted = Math.addExact(time, WINDOWS_EPOCH_IN_100NS); + long nanos = Math.multiplyExact(adjusted, 100L); + return FileTime.from(nanos, TimeUnit.NANOSECONDS); + } catch (ArithmeticException e) { + long micros = Math.addExact(time/10L, WINDOWS_EPOCH_IN_MICROS); + return FileTime.from(micros, TimeUnit.MICROSECONDS); + } } /** - * Convert FileTime to 64-bit value representing the number of 100-nanosecond - * intervals since January 1, 1601. + * Convert FileTime to 64-bit value representing the number of + * 100-nanosecond intervals since January 1, 1601. */ static long toWindowsTime(FileTime time) { - long value = time.to(TimeUnit.MICROSECONDS); - // adjust to Windows epoch+= 11644473600000000L; - value -= WINDOWS_EPOCH_IN_MICROSECONDS; - // us -> 100ns - value *= 10L; - return value; + long adjusted = time.to(TimeUnit.NANOSECONDS)/100L; + return adjusted - WINDOWS_EPOCH_IN_100NS; } /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java Mon Sep 30 20:26:28 2019 -0400 @@ -75,7 +75,7 @@ private BufferCapabilities bufferCaps; private long pConfigInfo; private ContextCapabilities oglCaps; - private OGLContext context; + private final OGLContext context; private final Object disposerReferent = new Object(); private final int maxTextureSize; @@ -105,7 +105,7 @@ this.pConfigInfo = configInfo; this.oglCaps = oglCaps; this.maxTextureSize = maxTextureSize; - context = new OGLContext(OGLRenderQueue.getInstance(), this); + context = new OGLContext(OGLRenderQueue.getInstance()); // add a record to the Disposer so that we destroy the native // CGLGraphicsConfigInfo data when this object goes away diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,9 @@ native void validate(int xoff, int yoff, int width, int height, boolean isOpaque); - private native void initOps(long pConfigInfo, long pPeerData, long layerPtr, - int xoff, int yoff, boolean isOpaque); + private native void initOps(OGLGraphicsConfig gc, long pConfigInfo, + long pPeerData, long layerPtr, int xoff, + int yoff, boolean isOpaque); protected CGLSurfaceData(CGLGraphicsConfig gc, ColorModel cm, int type, int width, int height) { @@ -74,7 +75,7 @@ pPeerData = pView.getAWTView(); isOpaque = pView.isOpaque(); } - initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque); + initOps(gc, pConfigInfo, pPeerData, 0, 0, 0, isOpaque); } protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc, @@ -90,7 +91,7 @@ layerPtr = layer.getPointer(); isOpaque = layer.isOpaque(); } - initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque); + initOps(gc, pConfigInfo, 0, layerPtr, 0, 0, isOpaque); } @Override //SurfaceData diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Mon Sep 30 20:26:28 2019 -0400 @@ -1408,10 +1408,8 @@ JNF_COCOA_ENTER(env); NSView *view = (NSView *)jlong_to_ptr(viewPtr); - NSWindow *window = [view window]; - [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - + NSWindow *window = [view window]; ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; }]; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m Mon Sep 30 20:26:28 2019 -0400 @@ -131,31 +131,6 @@ } /** - * Returns a pointer (as a jlong) to the native CGLGraphicsConfigInfo - * associated with the given OGLSDOps. This method can be called from - * shared code to retrieve the native GraphicsConfig data in a platform- - * independent manner. - */ -jlong -OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo) -{ - J2dTraceLn(J2D_TRACE_INFO, "OGLSD_GetNativeConfigInfo"); - - if (oglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: ops are null"); - return 0L; - } - - CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; - if (cglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: cgl ops are null"); - return 0L; - } - - return ptr_to_jlong(cglsdo->configInfo); -} - -/** * Makes the given GraphicsConfig's context current to its associated * "scratch" surface. If there is a problem making the context current, * this method will return NULL; otherwise, returns a pointer to the @@ -359,7 +334,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_opengl_CGLSurfaceData_initOps - (JNIEnv *env, jobject cglsd, + (JNIEnv *env, jobject cglsd, jobject gc, jlong pConfigInfo, jlong pPeerData, jlong layerPtr, jint xoff, jint yoff, jboolean isOpaque) { @@ -367,8 +342,22 @@ J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); + gc = (*env)->NewGlobalRef(env, gc); + if (gc == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + OGLSDOps *oglsdo = (OGLSDOps *) SurfaceData_InitOps(env, cglsd, sizeof(OGLSDOps)); + if (oglsdo == NULL) { + (*env)->DeleteGlobalRef(env, gc); + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + // later the graphicsConfig will be used for deallocation of oglsdo + oglsdo->graphicsConfig = gc; + CGLSDOps *cglsdo = (CGLSDOps *)malloc(sizeof(CGLSDOps)); if (cglsdo == NULL) { JNU_ThrowOutOfMemoryError(env, "creating native cgl ops"); diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp --- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp Mon Sep 30 20:26:28 2019 -0400 @@ -414,11 +414,18 @@ AudioControl **audioControls, int offset, int len) { void *jControl = NULL; PortControl *control = (PortControl *)calloc(1, sizeof(PortControl)); + if (control == NULL) { + return NULL; + } float precision = 0.01; control->type = type; control->controlCount = len; control->audioControls = (AudioControl **)malloc(len * sizeof(AudioControl *)); + if (control->audioControls == NULL) { + free(control); + return NULL; + } memcpy(control->audioControls, audioControls + offset, len * sizeof(AudioControl *)); switch (control->type) { @@ -482,6 +489,9 @@ OS_ERROR1(err, "PORT_GetControls (portIndex = %d) get OwnedObject values", portIndex); } else { mixer->deviceControls = (AudioControl *)calloc(mixer->deviceControlCount, sizeof(AudioControl)); + if (mixer->deviceControls == NULL) { + return; + } for (int i = 0; i < mixer->deviceControlCount; i++) { AudioControl *control = &mixer->deviceControls[i]; @@ -615,10 +625,16 @@ if (err == noErr) { CFIndex length = CFStringGetLength(cfname) + 1; channelName = (char *)malloc(length); + if (channelName == NULL) { + return; + } CFStringGetCString(cfname, channelName, length, kCFStringEncodingUTF8); CFRelease(cfname); } else { channelName = (char *)malloc(16); + if (channelName == NULL) { + return; + } sprintf(channelName, "Ch %d", ch); } diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/applet/Applet.java --- a/src/java.desktop/share/classes/java/applet/Applet.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/applet/Applet.java Mon Sep 30 20:26:28 2019 -0400 @@ -544,6 +544,7 @@ /** * The accessible context associated with this {@code Applet}. */ + @SuppressWarnings("serial") // Not statically typed as Serializable AccessibleContext accessibleContext = null; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/BorderLayout.java --- a/src/java.desktop/share/classes/java/awt/BorderLayout.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/BorderLayout.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,11 +92,10 @@ * Here is an example of five buttons in an applet laid out using * the {@code BorderLayout} layout manager: *

- * Diagram of an applet demonstrating BorderLayout.
- *      Each section of the BorderLayout contains a Button corresponding to its position in the layout, one of:
- *      North, West, Center, East, or South. + * Diagram of an applet
+ * demonstrating BorderLayout. Each section of the BorderLayout contains a
+ * Button corresponding to its position in the layout, one of: North, West,
+ * Center, East, or South. *

* The code for this applet is as follows: * diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Button.java --- a/src/java.desktop/share/classes/java/awt/Button.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Button.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,8 +40,8 @@ * depicts three views of a "{@code Quit}" button as it appears * under the Solaris operating system: *

- * The following context describes the graphic + * The following context describes the
+ * graphic *

* The first view shows the button as it appears normally. * The second view shows the button diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Checkbox.java --- a/src/java.desktop/share/classes/java/awt/Checkbox.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Checkbox.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,8 +52,8 @@ * This image depicts the check boxes and grid layout * created by this code example: *

- * The following context describes the graphic. + * The following context describes the
+ * graphic. *

* The button labeled {@code one} is in the "on" state, and the * other two are in the "off" state. In this example, which uses the diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/CheckboxGroup.java --- a/src/java.desktop/share/classes/java/awt/CheckboxGroup.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/CheckboxGroup.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,9 +46,9 @@ *

* This image depicts the check box group created by this example: *

- * Shows three checkboxes, arranged vertically, labeled one, two, and three. Checkbox one is in the on state. + * Shows three checkboxes,
+ * arranged vertically, labeled one, two, and three. Checkbox one is in the on
+ * state. * * @author Sami Shaio * @see java.awt.Checkbox diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java --- a/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * Menu labeled Examples, containing items Basic, Simple, Check, and More
  * Examples. The Check item is a CheckBoxMenuItem instance, in the off state. + * style="margin: 7px 10px;"> *

* The item labeled {@code Check} shows a check box menu item * in its "off" state. diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Choice.java --- a/src/java.desktop/share/classes/java/awt/Choice.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Choice.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,8 +51,8 @@ * After this choice menu has been added to a panel, * it appears as follows in its normal state: *

- * The following text describes the graphic + * The following text describes the
+ * graphic *

* In the picture, {@code "Green"} is the current choice. * Pushing the mouse button down on the object causes a menu to diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Component.java --- a/src/java.desktop/share/classes/java/awt/Component.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Component.java Mon Sep 30 20:26:28 2019 -0400 @@ -469,6 +469,7 @@ * @see #getFocusTraversalKeys * @since 1.4 */ + @SuppressWarnings("serial") // Not statically typed as Serializable Set[] focusTraversalKeys; private static final String[] focusTraversalKeyPropertyNames = { @@ -9293,6 +9294,7 @@ /** * The {@code AccessibleContext} associated with this {@code Component}. */ + @SuppressWarnings("serial") // Not statically typed as Serializable protected AccessibleContext accessibleContext = null; /** @@ -9344,12 +9346,14 @@ * A component listener to track show/hide/resize events * and convert them to PropertyChange events. */ + @SuppressWarnings("serial") // Not statically typed as Serializable protected ComponentListener accessibleAWTComponentHandler = null; /** * A listener to track focus events * and convert them to PropertyChange events. */ + @SuppressWarnings("serial") // Not statically typed as Serializable protected FocusListener accessibleAWTFocusHandler = null; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Container.java --- a/src/java.desktop/share/classes/java/awt/Container.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Container.java Mon Sep 30 20:26:28 2019 -0400 @@ -3851,6 +3851,7 @@ * The handler to fire {@code PropertyChange} * when children are added or removed */ + @SuppressWarnings("serial") // Not statically typed as Serializable protected ContainerListener accessibleContainerHandler = null; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Event.java --- a/src/java.desktop/share/classes/java/awt/Event.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Event.java Mon Sep 30 20:26:28 2019 -0400 @@ -455,6 +455,7 @@ * @serial * @see java.awt.AWTEvent#getSource() */ + @SuppressWarnings("serial") // Not statically typed as Serializable public Object target; /** @@ -537,6 +538,7 @@ * * @serial */ + @SuppressWarnings("serial") // Not statically typed as Serializable public Object arg; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/FileDialog.java --- a/src/java.desktop/share/classes/java/awt/FileDialog.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/FileDialog.java Mon Sep 30 20:26:28 2019 -0400 @@ -125,6 +125,7 @@ * @see #setFilenameFilter() * @see FileNameFilter */ + @SuppressWarnings("serial") // Not statically typed as Serializable FilenameFilter filter; private static final String base = "filedlg"; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/FlowLayout.java --- a/src/java.desktop/share/classes/java/awt/FlowLayout.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/FlowLayout.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ *

* Graphic of Layout for Three Buttons + * style="margin: 7px 10px;"> *

* Here is the code for this applet: * diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Frame.java --- a/src/java.desktop/share/classes/java/awt/Frame.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Frame.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,10 +83,10 @@ * of the primary screen in the virtual device, negative coordinates * are possible, as shown in the following figure. *

- * Diagram of virtual device encompassing three physical screens and one primary physical screen. The primary physical screen
- * shows (0,0) coords while a different physical screen shows (-80,-100) coords. + * Diagram of virtual device
+ * encompassing three physical screens and one primary physical screen. The
+ * primary physical screen shows (0,0) coords while a different physical screen
+ * shows (-80,-100) coords. *

* In such an environment, when calling {@code setLocation}, * you must pass a virtual coordinate to this method. Similarly, diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/GridBagLayout.java --- a/src/java.desktop/share/classes/java/awt/GridBagLayout.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/GridBagLayout.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,64 +116,49 @@ *

{@link GridBagConstraints#anchor} *
Specifies where the component should be positioned in its display area. * There are three kinds of possible values: absolute, orientation-relative, - * and baseline-relative + * and baseline-relative. * Orientation relative values are interpreted relative to the container's * {@code ComponentOrientation} property while absolute values * are not. Baseline relative values are calculated relative to the * baseline. Valid values are: * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Absolute, relative and baseline values as described above

Absolute Values

Orientation Relative Values

Baseline Relative Values

- *
    - *
  • {@code GridBagConstraints.NORTH}
  • - *
  • {@code GridBagConstraints.SOUTH}
  • - *
  • {@code GridBagConstraints.WEST}
  • - *
  • {@code GridBagConstraints.EAST}
  • - *
  • {@code GridBagConstraints.NORTHWEST}
  • - *
  • {@code GridBagConstraints.NORTHEAST}
  • - *
  • {@code GridBagConstraints.SOUTHWEST}
  • - *
  • {@code GridBagConstraints.SOUTHEAST}
  • - *
  • {@code GridBagConstraints.CENTER} (the default)
  • + *
      + *
    • Absolute Values: + *
        + *
      • {@code GridBagConstraints.NORTH} + *
      • {@code GridBagConstraints.SOUTH} + *
      • {@code GridBagConstraints.WEST} + *
      • {@code GridBagConstraints.EAST} + *
      • {@code GridBagConstraints.NORTHWEST} + *
      • {@code GridBagConstraints.NORTHEAST} + *
      • {@code GridBagConstraints.SOUTHWEST} + *
      • {@code GridBagConstraints.SOUTHEAST} + *
      • {@code GridBagConstraints.CENTER} (the default) + *
      + *
    • Orientation Relative Values: + *
        + *
      • {@code GridBagConstraints.PAGE_START} + *
      • {@code GridBagConstraints.PAGE_END} + *
      • {@code GridBagConstraints.LINE_START} + *
      • {@code GridBagConstraints.LINE_END} + *
      • {@code GridBagConstraints.FIRST_LINE_START} + *
      • {@code GridBagConstraints.FIRST_LINE_END} + *
      • {@code GridBagConstraints.LAST_LINE_START} + *
      • {@code GridBagConstraints.LAST_LINE_END} + *
      + *
    • Baseline Relative Values: + *
        + *
      • {@code GridBagConstraints.BASELINE} + *
      • {@code GridBagConstraints.BASELINE_LEADING} + *
      • {@code GridBagConstraints.BASELINE_TRAILING} + *
      • {@code GridBagConstraints.ABOVE_BASELINE} + *
      • {@code GridBagConstraints.ABOVE_BASELINE_LEADING} + *
      • {@code GridBagConstraints.ABOVE_BASELINE_TRAILING} + *
      • {@code GridBagConstraints.BELOW_BASELINE} + *
      • {@code GridBagConstraints.BELOW_BASELINE_LEADING} + *
      • {@code GridBagConstraints.BELOW_BASELINE_TRAILING} + *
      *
    - *
- *
    - *
  • {@code GridBagConstraints.PAGE_START}
  • - *
  • {@code GridBagConstraints.PAGE_END}
  • - *
  • {@code GridBagConstraints.LINE_START}
  • - *
  • {@code GridBagConstraints.LINE_END}
  • - *
  • {@code GridBagConstraints.FIRST_LINE_START}
  • - *
  • {@code GridBagConstraints.FIRST_LINE_END}
  • - *
  • {@code GridBagConstraints.LAST_LINE_START}
  • - *
  • {@code GridBagConstraints.LAST_LINE_END}
  • - *
- *
- *
    - *
  • {@code GridBagConstraints.BASELINE}
  • - *
  • {@code GridBagConstraints.BASELINE_LEADING}
  • - *
  • {@code GridBagConstraints.BASELINE_TRAILING}
  • - *
  • {@code GridBagConstraints.ABOVE_BASELINE}
  • - *
  • {@code GridBagConstraints.ABOVE_BASELINE_LEADING}
  • - *
  • {@code GridBagConstraints.ABOVE_BASELINE_TRAILING}
  • - *
  • {@code GridBagConstraints.BELOW_BASELINE}
  • - *
  • {@code GridBagConstraints.BELOW_BASELINE_LEADING}
  • - *
  • {@code GridBagConstraints.BELOW_BASELINE_TRAILING}
  • - *
- *
*
{@link GridBagConstraints#weightx}, * {@link GridBagConstraints#weighty} *
Used to determine how to distribute space, which is @@ -201,14 +186,10 @@ *

* The following figure shows a baseline layout and includes a * component that spans rows: - * - * - * - * - *
Baseline Layout
- * The following text describes this graphic (Figure 1). - *
+ *

+ * The following text describes this graphic (Figure 1). + *

* This layout consists of three components: *
  • A panel that starts in row 0 and ends in row 1. The panel * has a baseline-resize behavior of {@code CONSTANT_DESCENT} and has @@ -257,20 +238,21 @@ * left-to-right container and Figure 3 shows the layout for a horizontal, * right-to-left container. * - * - * - * - * - * - * - * - * - * - *
    Figures
    - * The preceding text describes this graphic (Figure 1). - * - * The preceding text describes this graphic (Figure 2). - *
    Figure 2: Horizontal, Left-to-RightFigure 3: Horizontal, Right-to-Left
    + *
    + *
    + *

    The preceding text describes this graphic (Figure 2). + *

    Figure 2: Horizontal, Left-to-Right + *

    + *
    + *

    The preceding text describes this graphic (Figure 3). + *

    Figure 3: Horizontal, Right-to-Left + *

    + *
    + *
    *

    * Each of the ten components has the {@code fill} field * of its associated {@code GridBagConstraints} object diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/GridLayout.java --- a/src/java.desktop/share/classes/java/awt/GridLayout.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/GridLayout.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,26 +55,21 @@ * If the container's {@code ComponentOrientation} property is horizontal * and right-to-left, the example produces the output shown in Figure 2. * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Figures
    Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2.
- * Row 2 shows buttons 3 then 4. Row 3 shows buttons 5 then 6. - * Shows 6 buttons in rows of 2. Row 1 shows buttons 2 then 1.
- * Row 2 shows buttons 4 then 3. Row 3 shows buttons 6 then 5. - *
    Figure 1: Horizontal, Left-to-RightFigure 2: Horizontal, Right-to-Left
    + *

    + *
    + *

    Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2.
+ *        Row 2 shows buttons 3 then 4. Row 3 shows buttons 5 then 6. + *

    Figure 1: Horizontal, Left-to-Right + *

    + *
    + *

    Shows 6 buttons in rows of 2. Row 1 shows buttons 2 then 1.
+ *        Row 2 shows buttons 4 then 3. Row 3 shows buttons 6 then 5. + *

    Figure 2: Horizontal, Right-to-Left + *

    + *
    + *
    *

    * When both the number of rows and the number of columns have * been set to non-zero values, either by a constructor or diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Label.java --- a/src/java.desktop/share/classes/java/awt/Label.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Label.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,8 +45,8 @@ *

    * produces the following labels: *

    - * Two labels: 'Hi There!' and 'Another label' + * Two labels: 'Hi There!' and
+ * 'Another label' * * @author Sami Shaio * @since 1.0 diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/List.java --- a/src/java.desktop/share/classes/java/awt/List.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/List.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,8 @@ * scrolling list: *

    * Shows a list containing: Venus, Earth, JavaSoft, and Mars. Javasoft is selected. + * alt="Shows a list containing: Venus, Earth, JavaSoft, and Mars. Javasoft is + * selected." style="margin: 7px 10px;"> *

    * If the List allows multiple selections, then clicking on * an item that is already selected deselects it. In the preceding diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/MediaTracker.java --- a/src/java.desktop/share/classes/java/awt/MediaTracker.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/MediaTracker.java Mon Sep 30 20:26:28 2019 -0400 @@ -185,6 +185,7 @@ * @see #addImage(Image, int) * @see #removeImage(Image) */ + @SuppressWarnings("serial") // Not statically typed as Serializable MediaEntry head; /* @@ -922,8 +923,10 @@ } } +@SuppressWarnings("serial") // MediaEntry does not have a no-arg ctor class ImageMediaEntry extends MediaEntry implements ImageObserver, java.io.Serializable { + @SuppressWarnings("serial") // Not statically typed as Serializable Image image; int width; int height; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/MenuBar.java --- a/src/java.desktop/share/classes/java/awt/MenuBar.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/MenuBar.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,9 @@ * This is what a menu bar might look like: *

    * Diagram of MenuBar containing 2 menus: Examples and Options.
- * Examples menu is expanded showing items: Basic, Simple, Check, and More Examples. + * alt="Diagram of MenuBar containing 2 menus: Examples and Options. Examples + * menu is expanded showing items: Basic, Simple, Check, and More Examples." + * style="margin: 7px 10px;"> *

    * A menu bar handles keyboard shortcuts for menu items, passing them * along to its child menus. diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/MenuComponent.java --- a/src/java.desktop/share/classes/java/awt/MenuComponent.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/MenuComponent.java Mon Sep 30 20:26:28 2019 -0400 @@ -470,7 +470,7 @@ * though it won't actually implement the interface - that will be up * to the individual objects which extend MenuComponent. */ - + @SuppressWarnings("serial") // Not statically typed as Serializable AccessibleContext accessibleContext = null; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/MenuItem.java --- a/src/java.desktop/share/classes/java/awt/MenuItem.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/MenuItem.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,8 +51,8 @@ * a simple labeled menu item. *

    * This picture of a menu bar shows five menu items: - * The following text describes this graphic. + * The following text describes this
+ * graphic. *
    * The first two items are simple menu items, labeled * {@code "Basic"} and {@code "Simple"}. diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java --- a/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java Mon Sep 30 20:26:28 2019 -0400 @@ -138,6 +138,7 @@ */ private int blockIncrement = 1; + @SuppressWarnings("serial") // Not statically typed as Serializable private AdjustmentListener adjustmentListener; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Scrollbar.java --- a/src/java.desktop/share/classes/java/awt/Scrollbar.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Scrollbar.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,8 @@ * scroll bars could be used as slider controls to pick * the red, green, and blue components of a color: *

    - * Image shows 3 vertical sliders, side-by-side. + * Image shows 3 vertical sliders,
+ * side-by-side. *

    * Each scroll bar in this example could be created with * code similar to the following: @@ -59,8 +59,8 @@ * Here is an example of a scroll bar that represents a range: *

    * Image shows horizontal slider with starting range of 0 and ending range of 300. The slider thumb is labeled 60. + * alt="Image shows horizontal slider with starting range of 0 and ending range + * of 300. The slider thumb is labeled 60." style="margin: 7px 10px;"> *

    * The value range represented by the bubble in this example * is the visible amount. The horizontal scroll bar diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/SentEvent.java --- a/src/java.desktop/share/classes/java/awt/SentEvent.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/SentEvent.java Mon Sep 30 20:26:28 2019 -0400 @@ -47,6 +47,7 @@ boolean dispatched; private AWTEvent nested; + @SuppressWarnings("serial") // Not statically typed as Serializable private AppContext toNotify; SentEvent() { diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/SequencedEvent.java --- a/src/java.desktop/share/classes/java/awt/SequencedEvent.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/SequencedEvent.java Mon Sep 30 20:26:28 2019 -0400 @@ -55,11 +55,13 @@ private static final LinkedList list = new LinkedList<>(); private final AWTEvent nested; + @SuppressWarnings("serial") // Not statically typed as Serializable private AppContext appContext; private boolean disposed; private final LinkedList pendingEvents = new LinkedList<>(); private static boolean fxAppThreadIsDispatchThread; + @SuppressWarnings("serial") // Not statically typed as Serializable private Thread fxCheckSequenceThread; static { AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() { diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/TextArea.java --- a/src/java.desktop/share/classes/java/awt/TextArea.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/TextArea.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,8 @@ *

    * The following image shows the appearance of a text area: *

    - * A TextArea showing the word 'Hello!' + * A TextArea showing the word
+ * 'Hello!' *

    * This text area could be created by the following line of code: * diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/TextField.java --- a/src/java.desktop/share/classes/java/awt/TextField.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/TextField.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,8 @@ * text fields of varying widths. Two of these text fields * display the predefined text {@code "Hello"}. *

    - * The preceding text describes this image. + * The preceding text describes this
+ * image. *

    * Here is the code that produces these four text fields: * diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/Window.java --- a/src/java.desktop/share/classes/java/awt/Window.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/Window.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,8 +96,9 @@ * possible, as shown in the following figure. *

    * Diagram shows virtual device containing 4 physical screens. Primary physical screen shows coords (0,0), other screen shows (-80,-100). + * alt="Diagram shows virtual device containing 4 physical screens. Primary + * physical screen shows coords (0,0), other screen shows (-80,-100)." + * style="margin: 7px 10px;"> *

    * In such an environment, when calling {@code setLocation}, * you must pass a virtual coordinate to this method. Similarly, @@ -371,6 +372,7 @@ * @see #setShape(Shape) * @since 1.7 */ + @SuppressWarnings("serial") // Not statically typed as Serializable private Shape shape = null; private static final String base = "win"; diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java --- a/src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/desktop/FilesEvent.java Mon Sep 30 20:26:28 2019 -0400 @@ -47,6 +47,7 @@ /** * The list of files. */ + @SuppressWarnings("serial") // Not statically typed as Serializable final List files; /** diff -r 7cd20dbeee36 -r 18e27ee2276b src/java.desktop/share/classes/java/awt/doc-files/DesktopProperties.html --- a/src/java.desktop/share/classes/java/awt/doc-files/DesktopProperties.html Mon Sep 30 20:16:48 2019 -0400 +++ b/src/java.desktop/share/classes/java/awt/doc-files/DesktopProperties.html Mon Sep 30 20:26:28 2019 -0400 @@ -5,7 +5,7 @@ AWT Desktop Properties " + name); - if (!ipv4Name.equals(name)) { - throw new RuntimeException("Mismatch between default" - + " and java.net.preferIPv4Stack=true results"); + + System.out.println("(default) " + addr + "--> " + name + + " (reversed IPv4: " + ipv4Reversed + ")"); + if (!ipv4Name.equals(name)) { + // adding some diagnosting + System.err.println("name=" + name + " doesn't match expected=" + ipv4Name); + System.err.println("Listing all adresses:"); + for (InetAddress any : InetAddress.getAllByName(HOST)) { + System.err.println("\t[" + any + "] address=" + any.getHostAddress() + + ", host=" + any.getHostName()); } + // make the test fail... + throw new RuntimeException("Mismatch between default" + + " and java.net.preferIPv4Stack=true results"); } } @@ -100,5 +142,13 @@ System.out.println("Executing: " + cmd); return new OutputAnalyzer(new ProcessBuilder(cmd).start()).getOutput(); } + + static String reverseWithIPv4Prefer(String addr) throws IOException { + String java = JDKToolFinder.getTestJDKTool("java"); + String testClz = Lookup.class.getName(); + List cmd = List.of(java, "-Djava.net.preferIPv4Stack=true", + "-cp", CLASS_PATH, testClz, "reverse", addr); + System.out.println("Executing: " + cmd); + return new OutputAnalyzer(new ProcessBuilder(cmd).start()).getOutput(); + } } - diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/ProxySelector/NullSelector.java --- a/test/jdk/java/net/ProxySelector/NullSelector.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/ProxySelector/NullSelector.java Mon Sep 30 20:26:28 2019 -0400 @@ -25,6 +25,7 @@ * @bug 6215885 * @library /test/lib * @summary URLConnection.openConnection NPE if ProxySelector.setDefault is set to null + * @run main/othervm NullSelector */ import java.net.*; diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/ResponseCache/B6181108.java --- a/test/jdk/java/net/ResponseCache/B6181108.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/ResponseCache/B6181108.java Mon Sep 30 20:26:28 2019 -0400 @@ -33,6 +33,7 @@ import java.util.*; import java.io.*; import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; public class B6181108 implements Runnable { ServerSocket ss; @@ -105,7 +106,7 @@ .toString(); urlWithSpace = base + "/space%20test/page1.html"; URL url = new URL(urlWithSpace); - URLConnection urlc = url.openConnection(); + URLConnection urlc = url.openConnection(NO_PROXY); int i = ((HttpURLConnection)(urlc)).getResponseCode(); System.out.println("response code = " + i); ResponseCache.setDefault(null); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/ResponseCache/ResponseCacheTest.java --- a/test/jdk/java/net/ResponseCache/ResponseCacheTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/ResponseCache/ResponseCacheTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -33,6 +33,7 @@ import java.io.*; import javax.net.ssl.*; import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; /** * Request should get serviced by the cache handler. Response get @@ -137,7 +138,7 @@ .port(ss.getLocalPort()) .path("/file2.1") .toURL(); - http = (HttpURLConnection)url2.openConnection(); + http = (HttpURLConnection)url2.openConnection(NO_PROXY); System.out.println("responsecode2 is :"+http.getResponseCode()); Map> headers2 = http.getHeaderFields(); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/ResponseCache/getResponseCode.java --- a/test/jdk/java/net/ResponseCache/getResponseCode.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/ResponseCache/getResponseCode.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.net.*; import java.util.*; import java.io.*; +import static java.net.Proxy.NO_PROXY; /** @@ -43,7 +44,7 @@ getResponseCode() throws Exception { url = new URL("http://localhost/file1.cache"); - HttpURLConnection http = (HttpURLConnection)url.openConnection(); + HttpURLConnection http = (HttpURLConnection)url.openConnection(NO_PROXY); int respCode = http.getResponseCode(); http.disconnect(); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/B5052093.java --- a/test/jdk/java/net/URLConnection/B5052093.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/B5052093.java Mon Sep 30 20:26:28 2019 -0400 @@ -33,6 +33,7 @@ import java.net.*; import java.io.*; import sun.net.www.protocol.file.FileURLConnection; +import static java.net.Proxy.NO_PROXY; public class B5052093 implements HttpCallback { private static TestHttpServer server; @@ -68,7 +69,7 @@ server = new TestHttpServer(new B5052093(), 1, 10, loopback, 0); try { URL url = new URL("http://" + server.getAuthority() + "/foo"); - URLConnection conn = url.openConnection(); + URLConnection conn = url.openConnection(NO_PROXY); int i = conn.getContentLength(); long l = conn.getContentLengthLong(); if (i != -1 || l != testSize) { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/DisconnectAfterEOF.java --- a/test/jdk/java/net/URLConnection/DisconnectAfterEOF.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/DisconnectAfterEOF.java Mon Sep 30 20:26:28 2019 -0400 @@ -33,8 +33,7 @@ import java.io.*; import java.util.*; import jdk.test.lib.net.URIBuilder; - - +import static java.net.Proxy.NO_PROXY; public class DisconnectAfterEOF { @@ -217,7 +216,7 @@ } static URLConnection doRequest(String uri) throws IOException { - URLConnection uc = (new URL(uri)).openConnection(); + URLConnection uc = (new URL(uri)).openConnection(NO_PROXY); uc.setDoOutput(true); OutputStream out = uc.getOutputStream(); out.write(new byte[16000]); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/HttpContinueStackOverflow.java --- a/test/jdk/java/net/URLConnection/HttpContinueStackOverflow.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/HttpContinueStackOverflow.java Mon Sep 30 20:26:28 2019 -0400 @@ -38,8 +38,8 @@ import java.net.Socket; import java.net.URL; import java.net.HttpURLConnection; - import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; public class HttpContinueStackOverflow { @@ -93,7 +93,7 @@ .path("/anything.html") .toURL(); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(NO_PROXY); conn.getResponseCode(); System.out.println("TEST PASSED"); } diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/Redirect307Test.java --- a/test/jdk/java/net/URLConnection/Redirect307Test.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/Redirect307Test.java Mon Sep 30 20:26:28 2019 -0400 @@ -29,8 +29,8 @@ */ import java.io.*; import java.net.*; - import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; class RedirServer extends Thread { @@ -113,7 +113,7 @@ .loopback() .port(port) .toURL(); - URLConnection conURL = url.openConnection(); + URLConnection conURL = url.openConnection(NO_PROXY); conURL.setDoInput(true); conURL.setAllowUserInteraction(false); conURL.setUseCaches(false); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/Responses.java --- a/test/jdk/java/net/URLConnection/Responses.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/Responses.java Mon Sep 30 20:26:28 2019 -0400 @@ -29,6 +29,7 @@ */ import java.net.*; import java.io.*; +import static java.net.Proxy.NO_PROXY; public class Responses { @@ -149,7 +150,7 @@ System.out.println("Test with response: >" + tests[i][0] + "<"); URL url = new URL("http://" + authority + "/" + i); - HttpURLConnection http = (HttpURLConnection)url.openConnection(); + HttpURLConnection http = (HttpURLConnection)url.openConnection(NO_PROXY); try { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/URLConnectionHeaders.java --- a/test/jdk/java/net/URLConnection/URLConnectionHeaders.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/URLConnectionHeaders.java Mon Sep 30 20:26:28 2019 -0400 @@ -35,6 +35,7 @@ import java.util.*; import java.io.*; import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; public class URLConnectionHeaders { @@ -94,7 +95,7 @@ .port(port) .path("/index.html") .toURL(); - URLConnection uc = url.openConnection(); + URLConnection uc = url.openConnection(NO_PROXY); // add request properties uc.addRequestProperty("Cookie", "cookie1"); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLConnection/contentHandler/UserContentHandler.java --- a/test/jdk/java/net/URLConnection/contentHandler/UserContentHandler.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLConnection/contentHandler/UserContentHandler.java Mon Sep 30 20:26:28 2019 -0400 @@ -40,6 +40,7 @@ import java.io.*; import java.util.*; import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; public class UserContentHandler implements Runnable { @@ -98,7 +99,7 @@ .path("/anything.txt") .toURL(); - if (!(u.openConnection().getContent() instanceof String)) { + if (!(u.openConnection(NO_PROXY).getContent() instanceof String)) { throw new RuntimeException("Load user defined content handler failed."); } else { System.err.println("Load user defined content handler succeed!"); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/URLPermission/OpenURL.java --- a/test/jdk/java/net/URLPermission/OpenURL.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/URLPermission/OpenURL.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.net.*; import java.io.*; import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; public class OpenURL { @@ -46,7 +47,7 @@ .path("/a/b") .toURL(); System.out.println("URL: " + url); - HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); + HttpURLConnection urlc = (HttpURLConnection)url.openConnection(NO_PROXY); InputStream is = urlc.getInputStream(); // error will throw exception other than SecurityException } catch (SecurityException e) { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/httpclient/ManyRequestsLegacy.java --- a/test/jdk/java/net/httpclient/ManyRequestsLegacy.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/httpclient/ManyRequestsLegacy.java Mon Sep 30 20:26:28 2019 -0400 @@ -74,6 +74,7 @@ import java.util.logging.Logger; import java.util.logging.Level; import jdk.test.lib.net.SimpleSSLContext; +import static java.net.Proxy.NO_PROXY; public class ManyRequestsLegacy { @@ -159,7 +160,7 @@ long start = System.nanoTime(); try { CompletableFuture cf = new CompletableFuture<>(); - URLConnection urlc = r.uri().toURL().openConnection(); + URLConnection urlc = r.uri().toURL().openConnection(NO_PROXY); HttpURLConnection httpc = (HttpURLConnection)urlc; httpc.setRequestMethod(r.method()); for (String s : r.headers().map().keySet()) { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/httpclient/PlainProxyConnectionTest.java --- a/test/jdk/java/net/httpclient/PlainProxyConnectionTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/httpclient/PlainProxyConnectionTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -44,6 +44,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.stream.Collectors; +import static java.net.Proxy.NO_PROXY; /** * @test @@ -139,7 +140,7 @@ throws IOException { connections.clear(); System.out.println("Verifying communication with server"); - try (InputStream is = uri.toURL().openConnection().getInputStream()) { + try (InputStream is = uri.toURL().openConnection(NO_PROXY).getInputStream()) { String resp = new String(is.readAllBytes(), StandardCharsets.UTF_8); System.out.println(resp); if (!RESPONSE.equals(resp)) { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/net/httpclient/ProxyTest.java --- a/test/jdk/java/net/httpclient/ProxyTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/net/httpclient/ProxyTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import jdk.test.lib.net.SimpleSSLContext; +import static java.net.Proxy.NO_PROXY; /** * @test @@ -167,7 +168,7 @@ System.out.println("Verifying communication with server"); URI uri = new URI("https://localhost:" + server.getAddress().getPort() + PATH + "x"); - try (InputStream is = uri.toURL().openConnection().getInputStream()) { + try (InputStream is = uri.toURL().openConnection(NO_PROXY).getInputStream()) { String resp = new String(is.readAllBytes(), StandardCharsets.UTF_8); System.out.println(resp); if (!RESPONSE.equals(resp)) { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,4 +1,5 @@ /* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java --- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java Mon Sep 30 20:26:28 2019 -0400 @@ -22,9 +22,9 @@ */ /* @test - * @bug 8181493 + * @bug 8181493 8231174 * @summary Verify that nanosecond precision is maintained for file timestamps - * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "solaris") + * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "solaris") | (os.family == "windows") * @modules java.base/sun.nio.fs:+open */ @@ -40,14 +40,21 @@ import java.util.concurrent.TimeUnit; public class SetTimesNanos { + private static final boolean IS_WINDOWS = + System.getProperty("os.name").startsWith("Windows"); + public static void main(String[] args) throws Exception { - // Check whether futimens() system call is supported - Class unixNativeDispatcherClass = Class.forName("sun.nio.fs.UnixNativeDispatcher"); - Method futimensSupported = unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); - futimensSupported.setAccessible(true); - if (!(boolean)futimensSupported.invoke(null)) { - System.err.println("futimens() system call not supported; skipping test"); - return; + if (!IS_WINDOWS) { + // Check whether futimens() system call is supported + Class unixNativeDispatcherClass = + Class.forName("sun.nio.fs.UnixNativeDispatcher"); + Method futimensSupported = + unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); + futimensSupported.setAccessible(true); + if (!(boolean)futimensSupported.invoke(null)) { + System.err.println("futimens() not supported; skipping test"); + return; + } } Path dirPath = Path.of("test"); @@ -56,7 +63,8 @@ System.out.format("FileStore: \"%s\" on %s (%s)%n", dir, store.name(), store.type()); - Set testedTypes = Set.of("apfs", "ext4", "xfs", "zfs"); + Set testedTypes = IS_WINDOWS ? + Set.of("NTFS") : Set.of("apfs", "ext4", "xfs", "zfs"); if (!testedTypes.contains(store.type())) { System.err.format("%s not in %s; skipping test", store.type(), testedTypes); return; @@ -77,6 +85,11 @@ Files.getFileAttributeView(path, BasicFileAttributeView.class); view.setTimes(pathTime, pathTime, null); + // Windows file time resolution is 100ns so truncate + if (IS_WINDOWS) { + timeNanos = 100L*(timeNanos/100L); + } + // Read attributes BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/security/Provider/GetServiceRace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/security/Provider/GetServiceRace.java Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8231387 + * @library ../testlibrary + * @summary make sure getService() avoids a race + * @author Tianmin Shi + */ + +import java.security.Provider; + +public class GetServiceRace { + + private static final Provider testProvider; + static { + testProvider = new Provider("MyProvider", 1.0, "test") { + }; + testProvider.put("CertificateFactory.Fixed", "MyCertificateFactory"); + } + + private static final int NUMBER_OF_RETRIEVERS = 3; + private static final int TEST_TIME_MS = 1000; + + public static boolean testFailed = false; + + public static void main(String[] args) throws Exception { + Updater updater = new Updater(); + updater.start(); + Retriever [] retrievers = new Retriever[NUMBER_OF_RETRIEVERS]; + for (int i=0; i(); + var random = new Random(); + for (int i = 0; i < 100; i++) { + var r = random.nextInt(100); + stack.push(r); + intArray[i] = r; + } + List list = Arrays.asList(intArray); + return new Object[][]{ + {list, true, "Arrays.asList"}, + {stack, true, "Stack"}, + {new ArrayList<>(list), true, "ArrayList"}, + {new LinkedList<>(list), false, "LinkedList"}, + {new Vector<>(list), true, "Vector"}, + {new CopyOnWriteArrayList<>(list), true, "CopyOnWriteArrayList"} + }; + } - boolean random = t instanceof RandomAccess; - if ((ut instanceof RandomAccess) != random) - throw new Exception( - "Unmodifiable fails to preserve RandomAccess: " + i); - if ((st instanceof RandomAccess) != random) - throw new Exception( - "Synchronized fails to preserve RandomAccess: " + i); + @Test(dataProvider = "testLists") + public void testRandomAccess(List list, boolean expectedRA, String failMsg) { + + var actualRA = list instanceof RandomAccess; + assertEquals(actualRA, expectedRA, failMsg); + + List unmodList = Collections.unmodifiableList(list); + List syncList = Collections.synchronizedList(list); + assertEquals((unmodList instanceof RandomAccess), actualRA, + "Unmodifiable fails to preserve RandomAccess"); + assertEquals((syncList instanceof RandomAccess), actualRA, + "Synchronized fails to preserve RandomAccess"); - while (t.size() > 0) { - t = t.subList(0, t.size() - 1); - if ((t instanceof RandomAccess) != random) - throw new Exception( - "SubList fails to preserve RandomAccess: " + i - + ", " + t.size()); + while (list.size() > 0) { + list = list.subList(0, list.size() - 1); + assertEquals((list instanceof RandomAccess), actualRA, + "SubList fails to preserve RandomAccess: " + list.size()); - ut = ut.subList(0, ut.size() - 1); - if ((ut instanceof RandomAccess) != random) - throw new Exception( - "SubList(unmodifiable) fails to preserve RandomAccess: " - + i + ", " + ut.size()); + unmodList = unmodList.subList(0, unmodList.size() - 1); + assertEquals((unmodList instanceof RandomAccess), actualRA, + "SubList(unmodifiable) fails to preserve RandomAccess: " + + unmodList.size()); + + syncList = syncList.subList(0, syncList.size() - 1); + assertEquals((syncList instanceof RandomAccess), actualRA, + "SubList(synchronized) fails to preserve RandomAccess: " + + syncList.size()); + } + } - st = st.subList(0, st.size() - 1); - if ((st instanceof RandomAccess) != random) - throw new Exception( - "SubList(synchronized) fails to preserve RandomAccess: " - + i + ", " + st.size()); - } - } + @Test(dataProvider = "testLists") + public void testListCopy(List list, boolean expectedRA, String failMsg) { + ArrayList testCollection = new ArrayList<>(Collections.nCopies(100, 0)); + // Test that copy works on random & sequential access + Collections.copy(list, testCollection); + assertEquals(list, testCollection, "Copy failed: " + failMsg); + } + + @Test(dataProvider = "testLists") + public void testListFill(List list, boolean expectedRA, String failMsg) { + ArrayList testCollection = new ArrayList<>(Collections.nCopies(100, 0)); + // Test that copy works on random & sequential access + Collections.fill(list, 0); + assertEquals(list, testCollection, "Fill failed: " + failMsg); + } - // Test that shuffle works the same on random and sequential access - List al = new ArrayList(); - for (int j = 0; j < 100; j++) - al.add(Integer.valueOf(2 * j)); - List ll = new LinkedList(al); - Random r1 = new Random(666), r2 = new Random(666); - for (int i = 0; i < 100; i++) { - Collections.shuffle(al, r1); - Collections.shuffle(ll, r2); - if (!al.equals(ll)) - throw new Exception("Shuffle failed: " + i); - } + /* + * Test that shuffle and binarySearch work the same on random and sequential access lists. + */ + @DataProvider(name = "testFactoryLists") + public Object[][] testDataFactory() { + return new Object[][]{ + {"ArrayList -> LinkedList", supplier(ArrayList::new), copyCtor(LinkedList::new)}, + {"CopyOnWriteArrayList -> Stack", supplier(CopyOnWriteArrayList::new), + copyCtor((list) -> { var s = new Stack();s.addAll(list);return s; })} + }; + } + + private Supplier> supplier(Supplier> supplier) { + return supplier; + } - // Test that fill works on random & sequential access - List gumbyParade = Collections.nCopies(100, "gumby"); - Collections.fill(al, "gumby"); - if (!al.equals(gumbyParade)) - throw new Exception("ArrayList fill failed"); - Collections.fill(ll, "gumby"); - if (!ll.equals(gumbyParade)) - throw new Exception("LinkedList fill failed"); + private Function, List> copyCtor(Function, List> ctor) { + return ctor; + } + + @Test(dataProvider = "testFactoryLists") + public void testListShuffle(String description, Supplier> randomAccessListSupplier, + Function, List> otherListFactory) { - // Test that copy works on random & sequential access - List pokeyParade = Collections.nCopies(100, "pokey"); - Collections.copy(al, pokeyParade); - if (!al.equals(pokeyParade)) - throw new Exception("ArrayList copy failed"); - Collections.copy(ll, pokeyParade); - if (!ll.equals(pokeyParade)) - throw new Exception("LinkedList copy failed"); + //e.g: ArrayList al = new ArrayList<>(); + List l1 = randomAccessListSupplier.get(); + for (int j = 0; j < 100; j++) { + l1.add(Integer.valueOf(2 * j)); + } + // e.g: List ll = new LinkedList<>(al); + List l2 = otherListFactory.apply(l1); + for (int i = 0; i < 100; i++) { + Collections.shuffle(l1, new Random(666)); + Collections.shuffle(l2, new Random(666)); + assertEquals(l1, l2, "Shuffle failed: " + description); + } + } - // Test that binarySearch works the same on random & sequential access - al = new ArrayList(); - for (int i = 0; i < 10000; i++) - al.add(Integer.valueOf(2 * i)); - ll = new LinkedList(al); + @Test(dataProvider = "testFactoryLists") + public void testListBinarySearch(String description, Supplier> randomAccessListSupplier, + Function, List> otherListFactory) { + + //e.g: ArrayList al = new ArrayList<>(); + List l1 = randomAccessListSupplier.get(); + for (int i = 0; i < 10000; i++) { + l1.add(Integer.valueOf(2 * i)); + } + // e.g: List ll = new LinkedList<>(al); + List l2 = otherListFactory.apply(l1); for (int i = 0; i < 500; i++) { - Integer key = Integer.valueOf(r1.nextInt(20000)); - if (Collections.binarySearch(al, key) != Collections - .binarySearch(ll, key)) - throw new Exception("Binary search failed: " + i); + Integer key = Integer.valueOf(new Random(666).nextInt(20000)); + assertEquals(Collections.binarySearch(l1, key), Collections + .binarySearch(l2, key), "Binary search failed: " + description); } } } diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/util/concurrent/tck/JSR166TestCase.java --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java Mon Sep 30 20:26:28 2019 -0400 @@ -76,6 +76,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.management.ManagementFactory; +import java.lang.management.LockInfo; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.lang.reflect.Constructor; @@ -270,6 +271,9 @@ } } + private static final ThreadMXBean THREAD_MXBEAN + = ManagementFactory.getThreadMXBean(); + /** * The scaling factor to apply to standard delays used in tests. * May be initialized from any of: @@ -1157,9 +1161,8 @@ } } - ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); System.err.println("------ stacktrace dump start ------"); - for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) + for (ThreadInfo info : THREAD_MXBEAN.dumpAllThreads(true, true)) if (threadOfInterest(info)) System.err.print(info); System.err.println("------ stacktrace dump end ------"); @@ -1188,6 +1191,17 @@ } /** + * Returns the thread's blocker's class name, if any, else null. + */ + String blockerClassName(Thread thread) { + ThreadInfo threadInfo; LockInfo lockInfo; + if ((threadInfo = THREAD_MXBEAN.getThreadInfo(thread.getId(), 0)) != null + && (lockInfo = threadInfo.getLockInfo()) != null) + return lockInfo.getClassName(); + return null; + } + + /** * Checks that future.get times out, with the default timeout of * {@code timeoutMillis()}. */ @@ -1486,6 +1500,14 @@ } /** + * Returns a new started daemon Thread running the given action, + * wrapped in a CheckedRunnable. + */ + Thread newStartedThread(Action action) { + return newStartedThread(checkedRunnable(action)); + } + + /** * Waits for the specified time (in milliseconds) for the thread * to terminate (using {@link Thread#join(long)}), else interrupts * the thread (in the hope that it may terminate later) and fails. @@ -1532,6 +1554,13 @@ } } + Runnable checkedRunnable(Action action) { + return new CheckedRunnable() { + public void realRun() throws Throwable { + action.run(); + }}; + } + public abstract class ThreadShouldThrow extends Thread { protected abstract void realRun() throws Throwable; diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/util/concurrent/tck/ReentrantLockTest.java --- a/test/jdk/java/util/concurrent/tck/ReentrantLockTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/util/concurrent/tck/ReentrantLockTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -39,10 +39,13 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import junit.framework.Test; @@ -1222,4 +1225,65 @@ assertFalse(thread.isAlive()); } } + + /** + * ThreadMXBean reports the blockers that we expect. + */ + public void testBlockers() { + if (!testImplementationDetails) return; + final boolean fair = randomBoolean(); + final boolean timedAcquire = randomBoolean(); + final boolean timedAwait = randomBoolean(); + final String syncClassName = fair + ? "ReentrantLock$FairSync" + : "ReentrantLock$NonfairSync"; + final String conditionClassName + = "AbstractQueuedSynchronizer$ConditionObject"; + final Thread.State expectedAcquireState = timedAcquire + ? Thread.State.TIMED_WAITING + : Thread.State.WAITING; + final Thread.State expectedAwaitState = timedAwait + ? Thread.State.TIMED_WAITING + : Thread.State.WAITING; + final Lock lock = new ReentrantLock(fair); + final Condition condition = lock.newCondition(); + final AtomicBoolean conditionSatisfied = new AtomicBoolean(false); + lock.lock(); + final Thread thread = newStartedThread((Action) () -> { + if (timedAcquire) + lock.tryLock(LONGER_DELAY_MS, MILLISECONDS); + else + lock.lock(); + while (!conditionSatisfied.get()) + if (timedAwait) + condition.await(LONGER_DELAY_MS, MILLISECONDS); + else + condition.await(); + }); + Callable waitingForLock = () -> { + String className; + return thread.getState() == expectedAcquireState + && (className = blockerClassName(thread)) != null + && className.endsWith(syncClassName); + }; + waitForThreadToEnterWaitState(thread, waitingForLock); + + lock.unlock(); + Callable waitingForCondition = () -> { + String className; + return thread.getState() == expectedAwaitState + && (className = blockerClassName(thread)) != null + && className.endsWith(conditionClassName); + }; + waitForThreadToEnterWaitState(thread, waitingForCondition); + + // politely release the waiter + conditionSatisfied.set(true); + lock.lock(); + try { + condition.signal(); + } finally { lock.unlock(); } + + awaitTermination(thread); + } } diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java --- a/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -38,6 +38,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Condition; @@ -1707,4 +1708,64 @@ assertTrue(lock.writeLock().toString().contains("Unlocked")); } + /** + * ThreadMXBean reports the blockers that we expect. + */ + public void testBlockers() { + if (!testImplementationDetails) return; + final boolean fair = randomBoolean(); + final boolean timedAcquire = randomBoolean(); + final boolean timedAwait = randomBoolean(); + final String syncClassName = fair + ? "ReentrantReadWriteLock$FairSync" + : "ReentrantReadWriteLock$NonfairSync"; + final String conditionClassName + = "AbstractQueuedSynchronizer$ConditionObject"; + final Thread.State expectedAcquireState = timedAcquire + ? Thread.State.TIMED_WAITING + : Thread.State.WAITING; + final Thread.State expectedAwaitState = timedAwait + ? Thread.State.TIMED_WAITING + : Thread.State.WAITING; + final Lock lock = new ReentrantReadWriteLock(fair).writeLock(); + final Condition condition = lock.newCondition(); + final AtomicBoolean conditionSatisfied = new AtomicBoolean(false); + lock.lock(); + final Thread thread = newStartedThread((Action) () -> { + if (timedAcquire) + lock.tryLock(LONGER_DELAY_MS, MILLISECONDS); + else + lock.lock(); + while (!conditionSatisfied.get()) + if (timedAwait) + condition.await(LONGER_DELAY_MS, MILLISECONDS); + else + condition.await(); + }); + Callable waitingForLock = () -> { + String className; + return thread.getState() == expectedAcquireState + && (className = blockerClassName(thread)) != null + && className.endsWith(syncClassName); + }; + waitForThreadToEnterWaitState(thread, waitingForLock); + + lock.unlock(); + Callable waitingForCondition = () -> { + String className; + return thread.getState() == expectedAwaitState + && (className = blockerClassName(thread)) != null + && className.endsWith(conditionClassName); + }; + waitForThreadToEnterWaitState(thread, waitingForCondition); + + // politely release the waiter + conditionSatisfied.set(true); + lock.lock(); + try { + condition.signal(); + } finally { lock.unlock(); } + + awaitTermination(thread); + } } diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/java/util/concurrent/tck/tck.policy --- a/test/jdk/java/util/concurrent/tck/tck.policy Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/java/util/concurrent/tck/tck.policy Mon Sep 30 20:26:28 2019 -0400 @@ -12,4 +12,6 @@ permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.io.FilePermission "<>", "read"; permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + // Allows test methods to inspect test thread state + permission java.lang.management.ManagementPermission "monitor"; }; diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/javax/swing/JInternalFrame/8145896/TestJInternalFrameMaximize.java --- a/test/jdk/javax/swing/JInternalFrame/8145896/TestJInternalFrameMaximize.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/javax/swing/JInternalFrame/8145896/TestJInternalFrameMaximize.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,13 @@ /* * @test * @key headful - * @bug 8145896 + * @bug 8145896 8194944 * @summary JInternalFrame setMaximum before adding to desktop throws null pointer exception * @library ../../regtesthelpers * @build Util * @run main TestJInternalFrameMaximize */ + import java.awt.Point; import java.awt.Robot; import java.awt.event.ActionEvent; @@ -55,18 +56,27 @@ private static JMenuItem menuItem; private static Robot robot; private static volatile String errorMessage = ""; + private static volatile boolean isFrameShowing; public static void main(String[] args) throws Exception { robot = new Robot(); + robot.setAutoDelay(100); UIManager.LookAndFeelInfo[] lookAndFeelArray = UIManager.getInstalledLookAndFeels(); for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { - String lookAndFeelString = lookAndFeelItem.getClassName(); - if (tryLookAndFeel(lookAndFeelString)) { - createUI(); + try { + String lookAndFeelString = lookAndFeelItem.getClassName(); + if (tryLookAndFeel(lookAndFeelString)) { + createUI(); + robot.waitForIdle(); + blockTillDisplayed(frame); + executeTest(); + robot.delay(1000); + } + } finally { + frame.dispose(); + isFrameShowing = false; robot.waitForIdle(); - executeTest(); - robot.delay(1000); } } if (!"".equals(errorMessage)) { @@ -113,8 +123,6 @@ } catch (PropertyVetoException ex) { } catch (RuntimeException ex) { errorMessage = "Test Failed"; - } finally { - frame.dispose(); } }); menu.add(menuItem); @@ -124,8 +132,21 @@ }); } + private static void blockTillDisplayed(JFrame frame) throws Exception { + while (!isFrameShowing) { + try { + SwingUtilities.invokeAndWait(()-> isFrameShowing = frame.isShowing()); + if (!isFrameShowing) { + Thread.sleep(1000); + } + } catch (InterruptedException ex) { + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + } + private static void executeTest() throws Exception { - Point point = Util.getCenterPoint(menu); performMouseOperations(point); point = Util.getCenterPoint(menuItem); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/javax/swing/plaf/metal/MetalIcons/MetalHiDPIIconsTest.java --- a/test/jdk/javax/swing/plaf/metal/MetalIcons/MetalHiDPIIconsTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/javax/swing/plaf/metal/MetalIcons/MetalHiDPIIconsTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8160986 8174845 8176883 + * @bug 8160986 8174845 8176883 8165828 * @summary Bad rendering of Swing UI controls with Metal L&F on HiDPI display * @run main/manual MetalHiDPIIconsTest */ @@ -50,7 +50,7 @@ + "Verify that icons are painted smoothly for standard Swing UI controls.\n\n" + "If the display does not support HiDPI mode press PASS.\n\n" + "1. Run the SwingSet2 demo on HiDPI Display.\n" - + "2. Select Metal Look and Feel\n" + + "2. Select Java Look and Feel. It is equivalent to Metal Look And Feel\n" + "3. Check that the icons are painted smoothly on Swing UI controls like:\n" + " - JRadioButton\n" + " - JCheckBox\n" diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java --- a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java Mon Sep 30 20:26:28 2019 -0400 @@ -25,6 +25,7 @@ package jdk.jfr.jcmd; +import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; @@ -56,8 +57,8 @@ private static final String SAMPLE_THREADS = "samplethreads"; private static final String UNSUPPORTED_OPTION = "unsupportedoption"; - private static final String REPOSITORYPATH_1 = "./repo1"; - private static final String REPOSITORYPATH_2 = "./repo2"; + private static final String REPOSITORYPATH_1 = "." + File.pathSeparator + "repo1"; + private static final String REPOSITORYPATH_2 = "." + File.pathSeparator + "repo2"; private static final String REPOSITORYPATH_SETTING_1 = "repositorypath="+REPOSITORYPATH_1; private static final String REPOSITORYPATH_SETTING_2 = "repositorypath="+REPOSITORYPATH_2; diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/java2d/marlin/FlipBitTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/sun/java2d/marlin/FlipBitTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; + + +/** + * Tests calculating user space line with a negative determinant (flip). + * + * @test + * @summary verify that flipped transformed lines are properly rasterized + * @bug 8230728 + */ +public class FlipBitTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(final String[] args) { + + final int size = 100; + + // First display which renderer is tested: + // JDK9 only: + System.setProperty("sun.java2d.renderer.verbose", "true"); + + System.out.println("FlipBitTest: size = " + size); + + final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + + final AffineTransform at = new AffineTransform(); + at.setToScale(1, -1.01); + g2d.setTransform(at); + + g2d.translate(0, -image.getHeight()); + g2d.setPaint(Color.WHITE); + g2d.fill(new Rectangle(image.getWidth(), image.getHeight())); + + g2d.setPaint(Color.BLACK); + g2d.setStroke(new BasicStroke(0.1f)); + g2d.draw(new Ellipse2D.Double(25, 25, 50, 50)); + + if (SAVE_IMAGE) { + try { + final File file = new File("FlipBitTest.png"); + + System.out.println("Writing file: " + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + boolean nonWhitePixelFound = false; + for (int x = 0; x < image.getWidth(); ++x) { + if (image.getRGB(x, 50) != Color.WHITE.getRGB()) { + nonWhitePixelFound = true; + break; + } + } + if (!nonWhitePixelFound) { + throw new IllegalStateException("The ellipse was not drawn"); + } + } finally { + g2d.dispose(); + } + } +} diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java --- a/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java Mon Sep 30 20:26:28 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,6 @@ import java.util.HashSet; import sun.java2d.DestSurfaceProvider; import sun.java2d.Surface; -import sun.java2d.pipe.BufferedContext; import sun.java2d.pipe.RenderQueue; import sun.java2d.pipe.hw.AccelGraphicsConfig; import sun.java2d.pipe.hw.AccelSurface; @@ -161,8 +160,6 @@ AccelGraphicsConfig agc = (AccelGraphicsConfig) gc; printAGC(agc); - testContext(agc); - VolatileImage vi = gc.createCompatibleVolatileImage(10, 10); vi.validate(gc); if (vi instanceof DestSurfaceProvider) { @@ -250,22 +247,6 @@ } } - private static void testContext(final AccelGraphicsConfig agc) { - BufferedContext c = agc.getContext(); - - RenderQueue rq = c.getRenderQueue(); - rq.lock(); - try { - c.saveState(); - rq.flushNow(); - c.restoreState(); - rq.flushNow(); - System.out.println("Passed: Save/Restore"); - } finally { - rq.unlock(); - } - } - private static void testForNPEDuringCreation(AccelGraphicsConfig agc) { int iterations = 100; HashSet vis = new HashSet(); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/java2d/pipe/hw/RSLContextInvalidationTest/RSLContextInvalidationTest.java --- a/test/jdk/sun/java2d/pipe/hw/RSLContextInvalidationTest/RSLContextInvalidationTest.java Mon Sep 30 20:16:48 2019 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @key headful - * @bug 6764257 8198613 - * @summary Tests that the color is reset properly after save/restore context - * @author Dmitri.Trembovetski@sun.com: area=Graphics - * @modules java.desktop/sun.java2d - * java.desktop/sun.java2d.pipe - * java.desktop/sun.java2d.pipe.hw - * @compile -XDignore.symbol.file=true RSLContextInvalidationTest.java - * @run main/othervm RSLContextInvalidationTest - * @run main/othervm -Dsun.java2d.noddraw=true RSLContextInvalidationTest - */ - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.image.BufferedImage; -import java.awt.image.VolatileImage; -import sun.java2d.DestSurfaceProvider; -import sun.java2d.Surface; -import sun.java2d.pipe.RenderQueue; -import sun.java2d.pipe.hw.*; - -public class RSLContextInvalidationTest { - - public static void main(String[] args) { - GraphicsEnvironment ge = - GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice gd = ge.getDefaultScreenDevice(); - GraphicsConfiguration gc = gd.getDefaultConfiguration(); - VolatileImage vi = gc.createCompatibleVolatileImage(100, 100); - vi.validate(gc); - VolatileImage vi1 = gc.createCompatibleVolatileImage(100, 100); - vi1.validate(gc); - - if (!(vi instanceof DestSurfaceProvider)) { - System.out.println("Test considered PASSED: no HW acceleration"); - return; - } - - DestSurfaceProvider p = (DestSurfaceProvider)vi; - Surface s = p.getDestSurface(); - if (!(s instanceof AccelSurface)) { - System.out.println("Test considered PASSED: no HW acceleration"); - return; - } - AccelSurface dst = (AccelSurface)s; - - Graphics g = vi.createGraphics(); - g.drawImage(vi1, 95, 95, null); - g.setColor(Color.red); - g.fillRect(0, 0, 100, 100); - g.setColor(Color.black); - g.fillRect(0, 0, 100, 100); - // after this the validated context color is black - - RenderQueue rq = dst.getContext().getRenderQueue(); - rq.lock(); - try { - dst.getContext().saveState(); - dst.getContext().restoreState(); - } finally { - rq.unlock(); - } - - // this will cause ResetPaint (it will set color to extended EA=ff, - // which is ffffffff==Color.white) - g.drawImage(vi1, 95, 95, null); - - // now try filling with black again, but it will come up as white - // because this fill rect won't validate the color properly - g.setColor(Color.black); - g.fillRect(0, 0, 100, 100); - - BufferedImage bi = vi.getSnapshot(); - if (bi.getRGB(50, 50) != Color.black.getRGB()) { - throw new RuntimeException("Test FAILED: found color="+ - Integer.toHexString(bi.getRGB(50, 50))+" instead of "+ - Integer.toHexString(Color.black.getRGB())); - } - - System.out.println("Test PASSED."); - } -} diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java --- a/test/jdk/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java Mon Sep 30 20:26:28 2019 -0400 @@ -33,6 +33,7 @@ import java.net.*; import java.io.*; import jdk.test.lib.net.URIBuilder; +import static java.net.Proxy.NO_PROXY; public class KeepAliveTimerThread { static class Fetcher implements Runnable { @@ -44,7 +45,7 @@ public void run() { try { - InputStream in = url.openConnection().getInputStream(); + InputStream in = url.openConnection(NO_PROXY).getInputStream(); byte b[] = new byte[128]; int n; do { diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/net/www/protocol/http/UserAuth.java --- a/test/jdk/sun/net/www/protocol/http/UserAuth.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/sun/net/www/protocol/http/UserAuth.java Mon Sep 30 20:26:28 2019 -0400 @@ -35,7 +35,7 @@ import java.io.*; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; - +import static java.net.Proxy.NO_PROXY; public class UserAuth { @@ -61,7 +61,7 @@ // GET Request URL url = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/redirect/"); - HttpURLConnection uc = (HttpURLConnection)url.openConnection(); + HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY); uc.setRequestProperty("Authorization", "testString:ValueDoesNotMatter"); int resp = uc.getResponseCode(); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/net/www/protocol/http/UserCookie.java --- a/test/jdk/sun/net/www/protocol/http/UserCookie.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/sun/net/www/protocol/http/UserCookie.java Mon Sep 30 20:26:28 2019 -0400 @@ -33,6 +33,7 @@ import com.sun.net.httpserver.*; import java.util.*; import java.io.*; +import static java.net.Proxy.NO_PROXY; public class UserCookie { @@ -59,7 +60,7 @@ InetSocketAddress address = httpServer.getAddress(); URL url = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test/"); - HttpURLConnection uc = (HttpURLConnection)url.openConnection(); + HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY); uc.setRequestProperty("Cookie", "value=ValueDoesNotMatter"); int resp = uc.getResponseCode(); diff -r 7cd20dbeee36 -r 18e27ee2276b test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java --- a/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java Mon Sep 30 20:26:28 2019 -0400 @@ -39,6 +39,7 @@ import java.util.Map; import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.JDKToolFinder; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.hprof.parser.HprofReader; @@ -47,40 +48,42 @@ public class JShellHeapDumpTest { - protected static Process process; - - private static long pid; + protected static Process jShellProcess; public static void launch(String expectedMessage, List toolArgs) throws IOException { try { launchJshell(); + long jShellPID = jShellProcess.pid(); - System.out.println("Starting " + toolArgs.get(0) + " against " + pid); + System.out.println("Starting " + toolArgs.get(0) + " against " + jShellPID); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); for (String cmd : toolArgs) { launcher.addToolArg(cmd); } - launcher.addToolArg("--pid=" + Long.toString(pid)); + launcher.addToolArg("--pid=" + Long.toString(jShellPID)); ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand()); - processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); - System.out.println("stdout:"); + System.out.println("jhsdb jmap stdout:"); System.out.println(output.getStdout()); - System.out.println("stderr:"); + System.out.println("jhsdb jmap stderr:"); System.out.println(output.getStderr()); - output.shouldNotContain("null"); + System.out.println("###### End of all output:"); output.shouldHaveExitValue(0); } catch (Exception ex) { throw new RuntimeException("Test ERROR " + ex, ex); } finally { - if (process.isAlive()) { - process.destroy(); - } + if (jShellProcess.isAlive()) { + System.out.println("Destroying jshell"); + jShellProcess.destroy(); + System.out.println("Jshell destroyed"); + } else { + System.out.println("Jshell not alive"); + } } } @@ -102,38 +105,45 @@ } public static void testHeapDump() throws IOException { - File dump = new File("jhsdb.jmap.heap." + + File hprofFile = new File("jhsdb.jmap.heap." + System.currentTimeMillis() + ".hprof"); - if (dump.exists()) { - dump.delete(); + if (hprofFile.exists()) { + hprofFile.delete(); } launch("heap written to", "jmap", - "--binaryheap", "--dumpfile=" + dump.getAbsolutePath()); + "--binaryheap", "--dumpfile=" + hprofFile.getAbsolutePath()); + + assertTrue(hprofFile.exists() && hprofFile.isFile(), + "Could not create dump file " + hprofFile.getAbsolutePath()); - assertTrue(dump.exists() && dump.isFile(), - "Could not create dump file " + dump.getAbsolutePath()); + printStackTraces(hprofFile.getAbsolutePath()); - printStackTraces(dump.getAbsolutePath()); - - dump.delete(); + System.out.println("hprof file size: " + hprofFile.length()); + hprofFile.delete(); } public static void launchJshell() throws IOException { System.out.println("Starting Jshell"); - String jdkPath = System.getProperty("test.jdk"); - if (jdkPath == null) { - // we are not under jtreg, try env - Map env = System.getenv(); - jdkPath = env.get("TESTJAVA"); + long startTime = System.currentTimeMillis(); + try { + ProcessBuilder pb = new ProcessBuilder(JDKToolFinder.getTestJDKTool("jshell")); + jShellProcess = ProcessTools.startProcess("JShell", pb, + s -> { // warm-up predicate + return s.contains("Welcome to JShell"); + }); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); } - if (jdkPath == null) { - throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set"); + + long elapsedTime = System.currentTimeMillis() - startTime; + System.out.println("Jshell Started in " + elapsedTime + "ms"); + + // Give jshell a chance to fully start up. This makes SA more stable for the jmap dump. + try { + Thread.sleep(2000); + } catch (Exception e) { } - String osname = System.getProperty("os.name"); - String jshell = jdkPath + ((osname.startsWith("window")) ? "/bin/jshell.exe" : "/bin/jshell"); - process = Runtime.getRuntime().exec(jshell); - pid = process.pid(); } public static void main(String[] args) throws Exception { diff -r 7cd20dbeee36 -r 18e27ee2276b test/lib/jdk/test/lib/SA/SATestUtils.java --- a/test/lib/jdk/test/lib/SA/SATestUtils.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/lib/jdk/test/lib/SA/SATestUtils.java Mon Sep 30 20:26:28 2019 -0400 @@ -22,12 +22,18 @@ */ package jdk.test.lib.SA; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.List; -import java.util.ArrayList; +import java.util.concurrent.TimeUnit; +import java.util.zip.GZIPInputStream; + import jdk.test.lib.Asserts; import jdk.test.lib.Platform; -import java.util.concurrent.TimeUnit; +import jtreg.SkippedException; public class SATestUtils { @@ -77,4 +83,22 @@ outStringList.addAll(cmdStringList); return outStringList; } + + public static void unzipCores(File dir) { + File[] gzCores = dir.listFiles((directory, name) -> name.matches("core(\\.\\d+)?\\.gz")); + for (File gzCore : gzCores) { + String coreFileName = gzCore.getName().replace(".gz", ""); + System.out.println("Unzipping core into " + coreFileName); + try (GZIPInputStream gzis = new GZIPInputStream(new FileInputStream(gzCore)); + FileOutputStream fos = new FileOutputStream(coreFileName)) { + byte[] buffer = new byte[1024]; + int length; + while ((length = gzis.read(buffer)) > 0) { + fos.write(buffer, 0, length); + } + } catch (IOException e) { + throw new SkippedException("Not able to unzip file: " + gzCore.getAbsolutePath(), e); + } + } + } } diff -r 7cd20dbeee36 -r 18e27ee2276b test/lib/sun/hotspot/WhiteBox.java --- a/test/lib/sun/hotspot/WhiteBox.java Mon Sep 30 20:16:48 2019 -0400 +++ b/test/lib/sun/hotspot/WhiteBox.java Mon Sep 30 20:26:28 2019 -0400 @@ -511,6 +511,7 @@ // Safepoint Checking public native void assertMatchingSafepointCalls(boolean mutexSafepointValue, boolean attemptedNoSafepointValue); + public native void assertSpecialLock(boolean allowVMBlock, boolean safepointCheck); // Sharing & archiving public native String getDefaultArchivePath(); diff -r 7cd20dbeee36 -r 18e27ee2276b test/micro/org/openjdk/bench/java/lang/StackWalkBench.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/java/lang/StackWalkBench.java Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import java.lang.StackWalker.StackFrame; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Benchmarks for java.lang.StackWalker + */ +@State(value=Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class StackWalkBench { + private static final StackWalker WALKER_DEFAULT = StackWalker.getInstance(); + + private static final StackWalker WALKER_CLASS = + StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + + // TestStack will add this number of calls to the call stack + @Param({"4", "100", "1000"}) + // For more thorough testing, consider: + // @Param({"4", "10", "100", "256", "1000"}) + public int depth; + + // Only used by swFilterCallerClass, to specify (roughly) how far back the + // call stack the target class will be found. Not needed by other + // benchmarks, so not a @Param by default. + // @Param({"4"}) + public int mark = 4; + + /** Build a call stack of a given size, then run trigger code in it. + * (Does not account for existing frames higher up in the JMH machinery). + */ + public static class TestStack { + final long fence; + long current; + final Runnable trigger; + + public TestStack(long max, Runnable trigger) { + this.fence = max; + this.current = 0; + this.trigger = trigger; + } + + public void start() { + one(); + } + + public void one() { + if (check()) { + two(); + } + } + + void two() { + if (check()) { + three(); + } + } + + private void three() { + if (check()) { + one(); + } + } + + boolean check() { + if (++current == fence) { + trigger.run(); + return false; + } else { + return true; + } + } + } + + /* Class to look for when testing filtering */ + static class TestMarker { + public void call(MarkedTestStack test) { + test.marked(); + } + } + + /** Call stack to test filtering. + * TestMarker will make a call on the stack. + */ + static class MarkedTestStack extends TestStack { + long mark; + + /** + * @param mark How far back the stack should the TestMarker be found? + */ + public MarkedTestStack(long max, long mark, Runnable trigger) { + super(max, trigger); + if (mark > max) { + throw new IllegalArgumentException("mark must be <= max"); + } + this.mark = max - mark; // Count backwards from the completed call stack + } + @Override + public void start() { + if (mark == 0) { + mark(); + } else { + super.one(); + } + } + @Override + boolean check() { + if (++current == mark) { + mark(); + return false; + } else if (current == fence) { + trigger.run(); + return false; + } else { + return true; + } + } + void mark() { + new TestMarker().call(this); + } + public void marked() { + if (current < fence) { + if (check()) { + one(); + } + } else { + trigger.run(); + } + } + } + + /** + * StackWalker.forEach() with default options + */ + @Benchmark + public void forEach_DefaultOpts(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + WALKER_DEFAULT.forEach(localBH::consume); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * Use Stackwalker.walk() to fetch class names + */ + @Benchmark + public void walk_ClassNames(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + WALKER_DEFAULT.walk(s -> { + s.map(StackFrame::getClassName).forEach(localBH::consume); + return null; + }); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * Use Stackwalker.walk() to fetch method names + */ + @Benchmark + public void walk_MethodNames(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + WALKER_DEFAULT.walk( s -> { + s.map(StackFrame::getMethodName).forEach(localBH::consume); + return null; + }); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * Use Stackwalker.walk() to fetch declaring class instances + */ + @Benchmark + public void walk_DeclaringClass(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + WALKER_CLASS.walk(s -> { + s.map(StackFrame::getDeclaringClass).forEach(localBH::consume); + return null; + }); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * Use StackWalker.walk() to fetch StackTraceElements + */ + @Benchmark + public void walk_StackTraceElements(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + WALKER_DEFAULT.walk(s -> { + s.map(StackFrame::toStackTraceElement).forEach(localBH::consume); + return null; + }); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * StackWalker.getCallerClass() + */ + @Benchmark + public void getCallerClass(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + localBH.consume(WALKER_CLASS.getCallerClass()); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * Use StackWalker.walk() to filter the StackFrames, looking for the + * TestMarker class, which will be (approximately) 'mark' calls back up the + * call stack. + */ + @Benchmark + public void walk_filterCallerClass(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + + new MarkedTestStack(depth, mark, new Runnable() { + public void run() { + // To be comparable with Reflection.getCallerClass(), return the Class object + WALKER_CLASS.walk(s -> { + localBH.consume(s.filter(f -> TestMarker.class.equals(f.getDeclaringClass())).findFirst().get().getDeclaringClass()); + return null; + }); + done[0] = true; + } + }).start(); + + if (!done[0]) { + throw new RuntimeException(); + } + } + + /** + * Use StackWalker.walk() to filter the StackFrames, looking for the + * TestMarker class, which will be (approximately) depth/2 calls back up the + * call stack. + */ + @Benchmark + public void walk_filterCallerClassHalfStack(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + + new MarkedTestStack(depth, depth / 2, new Runnable() { + public void run() { + // To be comparable with Reflection.getCallerClass(), return the Class object + WALKER_CLASS.walk(s -> { + localBH.consume(s.filter((f) -> TestMarker.class.equals(f.getDeclaringClass())).findFirst().get().getDeclaringClass()); + return null; + }); + done[0] = true; + } + }).start(); + + if (!done[0]) { + throw new RuntimeException(); + } + } + + // TODO: add swConsumeFramesWithReflection + // TODO: add swFilterOutStreamClasses + +// // This benchmark is for collecting performance counter data +// static PerfCounter streamTime = PerfCounter.newPerfCounter("jdk.stackwalk.testStreamsElapsedTime"); +// static PerfCounter numStream = PerfCounter.newPerfCounter("jdk.stackwalk.numTestStreams"); +// // @Benchmark +// public void swStkFrmsTimed(Blackhole bh) { +// final Blackhole localBH = bh; +// final boolean[] done = {false}; +// new TestStack(depth, new Runnable() { +// public void run() { +// long t0 = System.nanoTime(); +// WALKER_DEFAULT.forEach(localBH::consume); +// streamTime.addElapsedTimeFrom(t0); +// numStream.increment(); +// done[0] = true; +// } +// }).start(); +// if (!done[0]) { +// throw new RuntimeException(); +// } +// } +} diff -r 7cd20dbeee36 -r 18e27ee2276b test/micro/org/openjdk/bench/java/util/logging/LoggingRuntimeMicros.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/java/util/logging/LoggingRuntimeMicros.java Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.logging; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.LogRecord; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +@State(value = Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class LoggingRuntimeMicros { + + // TestStack will add this number of calls to the call stack + @Param({"4", "100", "1000"}) + // For more thorough testing, consider: + // @Param({"4", "10", "100", "256", "1000"}) + public int depth; + + /** Logging handler for testing logging calls. */ + @State(value = Scope.Thread) // create a separate one for each worker thread + public static class TestHandler extends java.util.logging.Handler { + private final static AtomicInteger serialNum = new AtomicInteger(0); + + private final java.util.logging.Logger logger; + private volatile LogRecord record; + + public TestHandler() { + // Each instance uses its own logger + logger = java.util.logging.Logger.getLogger("StackWalkBench" + serialNum.incrementAndGet()); + logger.setUseParentHandlers(false); + logger.addHandler(this); + } + + @Override + public void publish(LogRecord record) { + record.getSourceMethodName(); + this.record = record; + } + + private LogRecord reset() { + LogRecord record = this.record; + this.record = null; + return record; + } + + public final LogRecord testInferCaller(String msg) { + logger.info(msg); + LogRecord rec = this.reset(); + if (!"testInferCaller".equals(rec.getSourceMethodName())) { + throw new RuntimeException("bad caller: " + + rec.getSourceClassName() + "." + + rec.getSourceMethodName()); + } + return rec; + } + + public final LogRecord testLogp(String msg) { + logger.logp(java.util.logging.Level.INFO, "foo", "bar", msg); + LogRecord rec = this.reset(); + if (!"bar".equals(rec.getSourceMethodName())) { + throw new RuntimeException("bad caller: " + + rec.getSourceClassName() + "." + + rec.getSourceMethodName()); + } + return rec; + } + @Override public void flush() {} + @Override public void close() throws SecurityException {} + } + + /** Build a call stack of a given size, then run trigger code in it. + * (Does not account for existing frames higher up in the JMH machinery). + */ + static class TestStack { + final long fence; + long current; + final Runnable trigger; + + TestStack(long max, Runnable trigger) { + this.fence = max; + this.current = 0; + this.trigger = trigger; + } + + public void start() { + one(); + } + + public void one() { + if (check()) { + two(); + } + } + + void two() { + if (check()) { + three(); + } + } + + private void three() { + if (check()) { + one(); + } + } + + boolean check() { + if (++current == fence) { + trigger.run(); + return false; + } else { + return true; + } + } + } + + @Benchmark + public void testLoggingInferCaller(TestHandler handler, Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + localBH.consume(handler.testInferCaller("test")); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + @Benchmark + public void testLoggingLogp(TestHandler handler, Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + localBH.consume(handler.testLogp("test")); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } +} diff -r 7cd20dbeee36 -r 18e27ee2276b test/micro/org/openjdk/bench/vm/lang/ThrowableRuntimeMicros.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/vm/lang/ThrowableRuntimeMicros.java Mon Sep 30 20:26:28 2019 -0400 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.lang; + +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +@State(value = Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ThrowableRuntimeMicros { + + // TestStack will add this number of calls to the call stack + @Param({"4", "100", "1000"}) + // For more thorough testing, consider: + // @Param({"4", "10", "100", "256", "1000"}) + public int depth; + + /** Build a call stack of a given size, then run trigger code in it. + * (Does not account for existing frames higher up in the JMH machinery). + */ + static class TestStack { + final long fence; + long current; + final Runnable trigger; + + TestStack(long max, Runnable trigger) { + this.fence = max; + this.current = 0; + this.trigger = trigger; + } + + public void start() { + one(); + } + + public void one() { + if (check()) { + two(); + } + } + + void two() { + if (check()) { + three(); + } + } + + private void three() { + if (check()) { + one(); + } + } + + boolean check() { + if (++current == fence) { + trigger.run(); + return false; + } else { + return true; + } + } + } + + @Benchmark + public void testThrowableInit(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + localBH.consume(new Throwable()); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + @Benchmark + public void testThrowableGetStackTrace(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + localBH.consume(new Throwable().getStackTrace()); + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } + + @Benchmark + public void testThrowableSTEtoString(Blackhole bh) { + final Blackhole localBH = bh; + final boolean[] done = {false}; + new TestStack(depth, new Runnable() { + public void run() { + Throwable t = new Throwable(); + for (StackTraceElement ste : t.getStackTrace()) { + localBH.consume(ste.toString()); + } + done[0] = true; + } + }).start(); + if (!done[0]) { + throw new RuntimeException(); + } + } +}