--- a/make/CreateJmods.gmk Wed Oct 09 23:21:07 2019 +0200
+++ b/make/CreateJmods.gmk Wed Oct 09 23:22:56 2019 +0200
@@ -86,16 +86,18 @@
# from there. These files were explicitly filtered or modified in <module>-copy
# targets. For the rest, just pick up everything from the source legal dirs.
LEGAL_NOTICES := \
- $(SUPPORT_OUTPUTDIR)/modules_legal/common \
+ $(wildcard $(SUPPORT_OUTPUTDIR)/modules_legal/common) \
$(if $(wildcard $(SUPPORT_OUTPUTDIR)/modules_legal/$(MODULE)), \
$(wildcard $(SUPPORT_OUTPUTDIR)/modules_legal/$(MODULE)), \
$(call FindModuleLegalSrcDirs, $(MODULE)) \
)
-LEGAL_NOTICES_PATH := $(call PathList, $(LEGAL_NOTICES))
-DEPS += $(call FindFiles, $(LEGAL_NOTICES))
+ifneq ($(strip $(LEGAL_NOTICES)), )
+ LEGAL_NOTICES_PATH := $(call PathList, $(LEGAL_NOTICES))
+ DEPS += $(call FindFiles, $(LEGAL_NOTICES))
-JMOD_FLAGS += --legal-notices $(LEGAL_NOTICES_PATH)
+ JMOD_FLAGS += --legal-notices $(LEGAL_NOTICES_PATH)
+endif
ifeq ($(filter-out jdk.incubator.%, $(MODULE)), )
JMOD_FLAGS += --do-not-resolve-by-default
--- a/src/hotspot/cpu/aarch64/aarch64.ad Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/aarch64.ad Wed Oct 09 23:22:56 2019 +0200
@@ -2513,17 +2513,8 @@
__ INSN(REG, as_Register(BASE)); \
}
-typedef void (MacroAssembler::* mem_insn)(Register Rt, const Address &adr);
-typedef void (MacroAssembler::* mem_float_insn)(FloatRegister Rt, const Address &adr);
-typedef void (MacroAssembler::* mem_vector_insn)(FloatRegister Rt,
- MacroAssembler::SIMD_RegVariant T, const Address &adr);
-
- // Used for all non-volatile memory accesses. The use of
- // $mem->opcode() to discover whether this pattern uses sign-extended
- // offsets is something of a kludge.
- static void loadStore(MacroAssembler masm, mem_insn insn,
- Register reg, int opcode,
- Register base, int index, int size, int disp)
+
+static Address mem2address(int opcode, Register base, int index, int size, int disp)
{
Address::extend scale;
@@ -2542,16 +2533,34 @@
}
if (index == -1) {
- (masm.*insn)(reg, Address(base, disp));
+ return Address(base, disp);
} else {
assert(disp == 0, "unsupported address mode: disp = %d", disp);
- (masm.*insn)(reg, Address(base, as_Register(index), scale));
+ return Address(base, as_Register(index), scale);
}
}
+
+typedef void (MacroAssembler::* mem_insn)(Register Rt, const Address &adr);
+typedef void (MacroAssembler::* mem_insn2)(Register Rt, Register adr);
+typedef void (MacroAssembler::* mem_float_insn)(FloatRegister Rt, const Address &adr);
+typedef void (MacroAssembler::* mem_vector_insn)(FloatRegister Rt,
+ MacroAssembler::SIMD_RegVariant T, const Address &adr);
+
+ // Used for all non-volatile memory accesses. The use of
+ // $mem->opcode() to discover whether this pattern uses sign-extended
+ // offsets is something of a kludge.
+ static void loadStore(MacroAssembler masm, mem_insn insn,
+ Register reg, int opcode,
+ Register base, int index, int size, int disp)
+ {
+ Address addr = mem2address(opcode, base, index, size, disp);
+ (masm.*insn)(reg, addr);
+ }
+
static void loadStore(MacroAssembler masm, mem_float_insn insn,
- FloatRegister reg, int opcode,
- Register base, int index, int size, int disp)
+ FloatRegister reg, int opcode,
+ Register base, int index, int size, int disp)
{
Address::extend scale;
@@ -2573,8 +2582,8 @@
}
static void loadStore(MacroAssembler masm, mem_vector_insn insn,
- FloatRegister reg, MacroAssembler::SIMD_RegVariant T,
- int opcode, Register base, int index, int size, int disp)
+ FloatRegister reg, MacroAssembler::SIMD_RegVariant T,
+ int opcode, Register base, int index, int size, int disp)
{
if (index == -1) {
(masm.*insn)(reg, T, Address(base, disp));
@@ -3791,7 +3800,7 @@
static const int hi[Op_RegL + 1] = { // enum name
0, // Op_Node
0, // Op_Set
- OptoReg::Bad, // Op_RegN
+ OptoReg::Bad, // Op_RegN
OptoReg::Bad, // Op_RegI
R0_H_num, // Op_RegP
OptoReg::Bad, // Op_RegF
@@ -6923,7 +6932,7 @@
instruct loadP(iRegPNoSp dst, memory mem)
%{
match(Set dst (LoadP mem));
- predicate(!needs_acquiring_load(n));
+ predicate(!needs_acquiring_load(n) && (n->as_Load()->barrier_data() == 0));
ins_cost(4 * INSN_COST);
format %{ "ldr $dst, $mem\t# ptr" %}
@@ -7616,6 +7625,7 @@
instruct loadP_volatile(iRegPNoSp dst, /* sync_memory*/indirect mem)
%{
match(Set dst (LoadP mem));
+ predicate(n->as_Load()->barrier_data() == 0);
ins_cost(VOLATILE_REF_COST);
format %{ "ldar $dst, $mem\t# ptr" %}
@@ -8552,6 +8562,7 @@
instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+ predicate(n->as_LoadStore()->barrier_data() == 0);
ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
@@ -8665,7 +8676,7 @@
instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
- predicate(needs_acquiring_load_exclusive(n));
+ predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));
match(Set res (CompareAndSwapP mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
@@ -8796,6 +8807,7 @@
%}
instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ predicate(n->as_LoadStore()->barrier_data() == 0);
match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
ins_cost(2 * VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
@@ -8895,7 +8907,7 @@
%}
instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
- predicate(needs_acquiring_load_exclusive(n));
+ predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));
match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
ins_cost(VOLATILE_REF_COST);
effect(TEMP_DEF res, KILL cr);
@@ -8996,6 +9008,7 @@
%}
instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ predicate(n->as_LoadStore()->barrier_data() == 0);
match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
@@ -9103,8 +9116,8 @@
%}
instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
- predicate(needs_acquiring_load_exclusive(n));
match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+ predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));
ins_cost(VOLATILE_REF_COST);
effect(KILL cr);
format %{
@@ -9154,6 +9167,7 @@
%}
instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) %{
+ predicate(n->as_LoadStore()->barrier_data() == 0);
match(Set prev (GetAndSetP mem newv));
ins_cost(2 * VOLATILE_REF_COST);
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
@@ -9197,7 +9211,7 @@
%}
instruct get_and_setPAcq(indirect mem, iRegP newv, iRegPNoSp prev) %{
- predicate(needs_acquiring_load_exclusive(n));
+ predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));
match(Set prev (GetAndSetP mem newv));
ins_cost(VOLATILE_REF_COST);
format %{ "atomic_xchg_acq $prev, $newv, [$mem]" %}
--- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -162,16 +162,12 @@
// Creation also verifies the object.
NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
-#ifndef PRODUCT
- NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
- // read the value once
- volatile intptr_t data = method_holder->data();
- assert(data == 0 || data == (intptr_t)callee(),
- "a) MT-unsafe modification of inline cache");
- assert(data == 0 || jump->jump_destination() == entry,
- "b) MT-unsafe modification of inline cache");
+#ifdef ASSERT
+ NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address());
+ verify_mt_safe(callee, entry, method_holder, jump);
#endif
+
// Update stub.
method_holder->set_data((intptr_t)callee());
NativeGeneralJump::insert_unconditional(method_holder->next_instruction_address(), entry);
--- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -24,22 +24,23 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/codeBlob.hpp"
+#include "code/vmreg.inline.hpp"
#include "gc/z/zBarrier.inline.hpp"
#include "gc/z/zBarrierSet.hpp"
#include "gc/z/zBarrierSetAssembler.hpp"
#include "gc/z/zBarrierSetRuntime.hpp"
+#include "gc/z/zThreadLocalData.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "utilities/macros.hpp"
#ifdef COMPILER1
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "gc/z/c1/zBarrierSetC1.hpp"
#endif // COMPILER1
-
-#include "gc/z/zThreadLocalData.hpp"
-
-ZBarrierSetAssembler::ZBarrierSetAssembler() :
- _load_barrier_slow_stub(),
- _load_barrier_weak_slow_stub() {}
+#ifdef COMPILER2
+#include "gc/z/c2/zBarrierSetC2.hpp"
+#endif // COMPILER2
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -66,7 +67,7 @@
assert_different_registers(rscratch1, rscratch2, src.base());
assert_different_registers(rscratch1, rscratch2, dst);
- RegSet savedRegs = RegSet::range(r0,r28) - RegSet::of(dst, rscratch1, rscratch2);
+ RegSet savedRegs = RegSet::range(r0, r28) - RegSet::of(dst, rscratch1, rscratch2);
Label done;
@@ -206,7 +207,8 @@
// The Address offset is too large to direct load - -784. Our range is +127, -128.
__ mov(tmp, (long int)(in_bytes(ZThreadLocalData::address_bad_mask_offset()) -
- in_bytes(JavaThread::jni_environment_offset())));
+ in_bytes(JavaThread::jni_environment_offset())));
+
// Load address bad mask
__ add(tmp, jni_env, tmp);
__ ldr(tmp, Address(tmp));
@@ -294,12 +296,12 @@
__ prologue("zgc_load_barrier stub", false);
// We don't use push/pop_clobbered_registers() - we need to pull out the result from r0.
- for (int i = 0; i < 32; i +=2) {
- __ stpd(as_FloatRegister(i), as_FloatRegister(i+1), Address(__ pre(sp,-16)));
+ for (int i = 0; i < 32; i += 2) {
+ __ stpd(as_FloatRegister(i), as_FloatRegister(i + 1), Address(__ pre(sp,-16)));
}
- RegSet saveRegs = RegSet::range(r0,r28) - RegSet::of(r0);
- __ push(saveRegs, sp);
+ const RegSet save_regs = RegSet::range(r1, r28);
+ __ push(save_regs, sp);
// Setup arguments
__ load_parameter(0, c_rarg0);
@@ -307,98 +309,161 @@
__ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2);
- __ pop(saveRegs, sp);
+ __ pop(save_regs, sp);
- for (int i = 30; i >0; i -=2) {
- __ ldpd(as_FloatRegister(i), as_FloatRegister(i+1), Address(__ post(sp, 16)));
- }
+ for (int i = 30; i >= 0; i -= 2) {
+ __ ldpd(as_FloatRegister(i), as_FloatRegister(i + 1), Address(__ post(sp, 16)));
+ }
__ epilogue();
}
#endif // COMPILER1
+#ifdef COMPILER2
+
+OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) {
+ if (!OptoReg::is_reg(opto_reg)) {
+ return OptoReg::Bad;
+ }
+
+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg);
+ if (vm_reg->is_FloatRegister()) {
+ return opto_reg & ~1;
+ }
+
+ return opto_reg;
+}
+
#undef __
-#define __ cgen->assembler()->
+#define __ _masm->
+
+class ZSaveLiveRegisters {
+private:
+ MacroAssembler* const _masm;
+ RegSet _gp_regs;
+ RegSet _fp_regs;
+
+public:
+ void initialize(ZLoadBarrierStubC2* stub) {
+ // Create mask of live registers
+ RegMask live = stub->live();
-// Generates a register specific stub for calling
-// ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or
-// ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded().
-//
-// The raddr register serves as both input and output for this stub. When the stub is
-// called the raddr register contains the object field address (oop*) where the bad oop
-// was loaded from, which caused the slow path to be taken. On return from the stub the
-// raddr register contains the good/healed oop returned from
-// ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or
-// ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded().
-static address generate_load_barrier_stub(StubCodeGenerator* cgen, Register raddr, DecoratorSet decorators) {
- // Don't generate stub for invalid registers
- if (raddr == zr || raddr == r29 || raddr == r30) {
- return NULL;
+ // Record registers that needs to be saved/restored
+ while (live.is_NotEmpty()) {
+ const OptoReg::Name opto_reg = live.find_first_elem();
+ live.Remove(opto_reg);
+ if (OptoReg::is_reg(opto_reg)) {
+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg);
+ if (vm_reg->is_Register()) {
+ _gp_regs += RegSet::of(vm_reg->as_Register());
+ } else if (vm_reg->is_FloatRegister()) {
+ _fp_regs += RegSet::of((Register)vm_reg->as_FloatRegister());
+ } else {
+ fatal("Unknown register type");
+ }
+ }
+ }
+
+ // Remove C-ABI SOE registers, scratch regs and _ref register that will be updated
+ _gp_regs -= RegSet::range(r19, r30) + RegSet::of(r8, r9, stub->ref());
+ }
+
+ ZSaveLiveRegisters(MacroAssembler* masm, ZLoadBarrierStubC2* stub) :
+ _masm(masm),
+ _gp_regs(),
+ _fp_regs() {
+
+ // Figure out what registers to save/restore
+ initialize(stub);
+
+ // Save registers
+ __ push(_gp_regs, sp);
+ __ push_fp(_fp_regs, sp);
}
- // Create stub name
- char name[64];
- const bool weak = (decorators & ON_WEAK_OOP_REF) != 0;
- os::snprintf(name, sizeof(name), "zgc_load_barrier%s_stub_%s", weak ? "_weak" : "", raddr->name());
+ ~ZSaveLiveRegisters() {
+ // Restore registers
+ __ pop_fp(_fp_regs, sp);
+ __ pop(_gp_regs, sp);
+ }
+};
+
+#undef __
+#define __ _masm->
- __ align(CodeEntryAlignment);
- StubCodeMark mark(cgen, "StubRoutines", os::strdup(name, mtCode));
- address start = __ pc();
+class ZSetupArguments {
+private:
+ MacroAssembler* const _masm;
+ const Register _ref;
+ const Address _ref_addr;
+
+public:
+ ZSetupArguments(MacroAssembler* masm, ZLoadBarrierStubC2* stub) :
+ _masm(masm),
+ _ref(stub->ref()),
+ _ref_addr(stub->ref_addr()) {
- // Save live registers
- RegSet savedRegs = RegSet::range(r0,r18) - RegSet::of(raddr);
-
- __ enter();
- __ push(savedRegs, sp);
-
- // Setup arguments
- if (raddr != c_rarg1) {
- __ mov(c_rarg1, raddr);
+ // Setup arguments
+ if (_ref_addr.base() == noreg) {
+ // No self healing
+ if (_ref != c_rarg0) {
+ __ mov(c_rarg0, _ref);
+ }
+ __ mov(c_rarg1, 0);
+ } else {
+ // Self healing
+ if (_ref == c_rarg0) {
+ // _ref is already at correct place
+ __ lea(c_rarg1, _ref_addr);
+ } else if (_ref != c_rarg1) {
+ // _ref is in wrong place, but not in c_rarg1, so fix it first
+ __ lea(c_rarg1, _ref_addr);
+ __ mov(c_rarg0, _ref);
+ } else if (_ref_addr.base() != c_rarg0 && _ref_addr.index() != c_rarg0) {
+ assert(_ref == c_rarg1, "Mov ref first, vacating c_rarg0");
+ __ mov(c_rarg0, _ref);
+ __ lea(c_rarg1, _ref_addr);
+ } else {
+ assert(_ref == c_rarg1, "Need to vacate c_rarg1 and _ref_addr is using c_rarg0");
+ if (_ref_addr.base() == c_rarg0 || _ref_addr.index() == c_rarg0) {
+ __ mov(rscratch2, c_rarg1);
+ __ lea(c_rarg1, _ref_addr);
+ __ mov(c_rarg0, rscratch2);
+ } else {
+ ShouldNotReachHere();
+ }
+ }
+ }
}
- __ ldr(c_rarg0, Address(raddr));
+ ~ZSetupArguments() {
+ // Transfer result
+ if (_ref != r0) {
+ __ mov(_ref, r0);
+ }
+ }
+};
+
+#undef __
+#define __ masm->
- // Call barrier function
- __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), c_rarg0, c_rarg1);
+void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const {
+ BLOCK_COMMENT("ZLoadBarrierStubC2");
+
+ // Stub entry
+ __ bind(*stub->entry());
- // Move result returned in r0 to raddr, if needed
- if (raddr != r0) {
- __ mov(raddr, r0);
+ {
+ ZSaveLiveRegisters save_live_registers(masm, stub);
+ ZSetupArguments setup_arguments(masm, stub);
+ __ mov(rscratch1, stub->slow_path());
+ __ blr(rscratch1);
}
- __ pop(savedRegs, sp);
- __ leave();
- __ ret(lr);
-
- return start;
+ // Stub exit
+ __ b(*stub->continuation());
}
#undef __
-static void barrier_stubs_init_inner(const char* label, const DecoratorSet decorators, address* stub) {
- const int nregs = 28; // Exclude FP, XZR, SP from calculation.
- const int code_size = nregs * 254; // Rough estimate of code size
-
- ResourceMark rm;
-
- CodeBuffer buf(BufferBlob::create(label, code_size));
- StubCodeGenerator cgen(&buf);
-
- for (int i = 0; i < nregs; i++) {
- const Register reg = as_Register(i);
- stub[i] = generate_load_barrier_stub(&cgen, reg, decorators);
- }
-}
-
-void ZBarrierSetAssembler::barrier_stubs_init() {
- barrier_stubs_init_inner("zgc_load_barrier_stubs", ON_STRONG_OOP_REF, _load_barrier_slow_stub);
- barrier_stubs_init_inner("zgc_load_barrier_weak_stubs", ON_WEAK_OOP_REF, _load_barrier_weak_slow_stub);
-}
-
-address ZBarrierSetAssembler::load_barrier_slow_stub(Register reg) {
- return _load_barrier_slow_stub[reg->encoding()];
-}
-
-address ZBarrierSetAssembler::load_barrier_weak_slow_stub(Register reg) {
- return _load_barrier_weak_slow_stub[reg->encoding()];
-}
+#endif // COMPILER2
--- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -24,6 +24,12 @@
#ifndef CPU_AARCH64_GC_Z_ZBARRIERSETASSEMBLER_AARCH64_HPP
#define CPU_AARCH64_GC_Z_ZBARRIERSETASSEMBLER_AARCH64_HPP
+#include "code/vmreg.hpp"
+#include "oops/accessDecorators.hpp"
+#ifdef COMPILER2
+#include "opto/optoreg.hpp"
+#endif // COMPILER2
+
#ifdef COMPILER1
class LIR_Assembler;
class LIR_OprDesc;
@@ -32,14 +38,13 @@
class ZLoadBarrierStubC1;
#endif // COMPILER1
+#ifdef COMPILER2
+class Node;
+class ZLoadBarrierStubC2;
+#endif // COMPILER2
+
class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase {
-private:
- address _load_barrier_slow_stub[RegisterImpl::number_of_registers];
- address _load_barrier_weak_slow_stub[RegisterImpl::number_of_registers];
-
public:
- ZBarrierSetAssembler();
-
virtual void load_at(MacroAssembler* masm,
DecoratorSet decorators,
BasicType type,
@@ -83,10 +88,13 @@
DecoratorSet decorators) const;
#endif // COMPILER1
- virtual void barrier_stubs_init();
+#ifdef COMPILER2
+ OptoReg::Name refine_register(const Node* node,
+ OptoReg::Name opto_reg);
- address load_barrier_slow_stub(Register reg);
- address load_barrier_weak_slow_stub(Register reg);
+ void generate_c2_load_barrier_stub(MacroAssembler* masm,
+ ZLoadBarrierStubC2* stub) const;
+#endif // COMPILER2
};
#endif // CPU_AARCH64_GC_Z_ZBARRIERSETASSEMBLER_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad Wed Oct 09 23:22:56 2019 +0200
@@ -24,155 +24,244 @@
source_hpp %{
#include "gc/z/c2/zBarrierSetC2.hpp"
+#include "gc/z/zThreadLocalData.hpp"
%}
source %{
-#include "gc/z/zBarrierSetAssembler.hpp"
-
-static void z_load_barrier_slow_reg(MacroAssembler& _masm, Register dst,
- Register base, int index, int scale,
- int disp, bool weak) {
- const address stub = weak ? ZBarrierSet::assembler()->load_barrier_weak_slow_stub(dst)
- : ZBarrierSet::assembler()->load_barrier_slow_stub(dst);
+static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) {
+ ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, weak);
+ __ ldr(tmp, Address(rthread, ZThreadLocalData::address_bad_mask_offset()));
+ __ andr(tmp, tmp, ref);
+ __ cbnz(tmp, *stub->entry());
+ __ bind(*stub->continuation());
+}
- if (index == -1) {
- if (disp != 0) {
- __ lea(dst, Address(base, disp));
- } else {
- __ mov(dst, base);
- }
- } else {
- Register index_reg = as_Register(index);
- if (disp == 0) {
- __ lea(dst, Address(base, index_reg, Address::lsl(scale)));
- } else {
- __ lea(dst, Address(base, disp));
- __ lea(dst, Address(dst, index_reg, Address::lsl(scale)));
- }
- }
-
- __ far_call(RuntimeAddress(stub));
+static void z_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) {
+ ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, false /* weak */);
+ __ b(*stub->entry());
+ __ bind(*stub->continuation());
}
%}
-//
-// Execute ZGC load barrier (strong) slow path
-//
-instruct loadBarrierSlowReg(iRegP dst, memory src, rFlagsReg cr,
- vRegD_V0 v0, vRegD_V1 v1, vRegD_V2 v2, vRegD_V3 v3, vRegD_V4 v4,
- vRegD_V5 v5, vRegD_V6 v6, vRegD_V7 v7, vRegD_V8 v8, vRegD_V9 v9,
- vRegD_V10 v10, vRegD_V11 v11, vRegD_V12 v12, vRegD_V13 v13, vRegD_V14 v14,
- vRegD_V15 v15, vRegD_V16 v16, vRegD_V17 v17, vRegD_V18 v18, vRegD_V19 v19,
- vRegD_V20 v20, vRegD_V21 v21, vRegD_V22 v22, vRegD_V23 v23, vRegD_V24 v24,
- vRegD_V25 v25, vRegD_V26 v26, vRegD_V27 v27, vRegD_V28 v28, vRegD_V29 v29,
- vRegD_V30 v30, vRegD_V31 v31) %{
- match(Set dst (LoadBarrierSlowReg src dst));
- predicate(!n->as_LoadBarrierSlowReg()->is_weak());
+// Load Pointer
+instruct zLoadP(iRegPNoSp dst, memory mem, rFlagsReg cr)
+%{
+ match(Set dst (LoadP mem));
+ predicate(UseZGC && !needs_acquiring_load(n) && (n->as_Load()->barrier_data() == ZLoadBarrierStrong));
+ effect(TEMP dst, KILL cr);
- effect(KILL cr,
- KILL v0, KILL v1, KILL v2, KILL v3, KILL v4, KILL v5, KILL v6, KILL v7,
- KILL v8, KILL v9, KILL v10, KILL v11, KILL v12, KILL v13, KILL v14,
- KILL v15, KILL v16, KILL v17, KILL v18, KILL v19, KILL v20, KILL v21,
- KILL v22, KILL v23, KILL v24, KILL v25, KILL v26, KILL v27, KILL v28,
- KILL v29, KILL v30, KILL v31);
+ ins_cost(4 * INSN_COST);
- format %{ "lea $dst, $src\n\t"
- "call #ZLoadBarrierSlowPath" %}
+ format %{ "ldr $dst, $mem" %}
ins_encode %{
- z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$base$$Register,
- $src$$index, $src$$scale, $src$$disp, false);
+ const Address ref_addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+ __ ldr($dst$$Register, ref_addr);
+ if (barrier_data() != ZLoadBarrierElided) {
+ z_load_barrier(_masm, this, ref_addr, $dst$$Register, rscratch2 /* tmp */, false /* weak */);
+ }
%}
- ins_pipe(pipe_slow);
+
+ ins_pipe(iload_reg_mem);
%}
-//
-// Execute ZGC load barrier (weak) slow path
-//
-instruct loadBarrierWeakSlowReg(iRegP dst, memory src, rFlagsReg cr,
- vRegD_V0 v0, vRegD_V1 v1, vRegD_V2 v2, vRegD_V3 v3, vRegD_V4 v4,
- vRegD_V5 v5, vRegD_V6 v6, vRegD_V7 v7, vRegD_V8 v8, vRegD_V9 v9,
- vRegD_V10 v10, vRegD_V11 v11, vRegD_V12 v12, vRegD_V13 v13, vRegD_V14 v14,
- vRegD_V15 v15, vRegD_V16 v16, vRegD_V17 v17, vRegD_V18 v18, vRegD_V19 v19,
- vRegD_V20 v20, vRegD_V21 v21, vRegD_V22 v22, vRegD_V23 v23, vRegD_V24 v24,
- vRegD_V25 v25, vRegD_V26 v26, vRegD_V27 v27, vRegD_V28 v28, vRegD_V29 v29,
- vRegD_V30 v30, vRegD_V31 v31) %{
- match(Set dst (LoadBarrierSlowReg src dst));
- predicate(n->as_LoadBarrierSlowReg()->is_weak());
+// Load Weak Pointer
+instruct zLoadWeakP(iRegPNoSp dst, memory mem, rFlagsReg cr)
+%{
+ match(Set dst (LoadP mem));
+ predicate(UseZGC && !needs_acquiring_load(n) && (n->as_Load()->barrier_data() == ZLoadBarrierWeak));
+ effect(TEMP dst, KILL cr);
- effect(KILL cr,
- KILL v0, KILL v1, KILL v2, KILL v3, KILL v4, KILL v5, KILL v6, KILL v7,
- KILL v8, KILL v9, KILL v10, KILL v11, KILL v12, KILL v13, KILL v14,
- KILL v15, KILL v16, KILL v17, KILL v18, KILL v19, KILL v20, KILL v21,
- KILL v22, KILL v23, KILL v24, KILL v25, KILL v26, KILL v27, KILL v28,
- KILL v29, KILL v30, KILL v31);
+ ins_cost(4 * INSN_COST);
- format %{ "lea $dst, $src\n\t"
- "call #ZLoadBarrierSlowPath" %}
+ format %{ "ldr $dst, $mem" %}
ins_encode %{
- z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$base$$Register,
- $src$$index, $src$$scale, $src$$disp, true);
+ const Address ref_addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+ __ ldr($dst$$Register, ref_addr);
+ z_load_barrier(_masm, this, ref_addr, $dst$$Register, rscratch2 /* tmp */, true /* weak */);
%}
- ins_pipe(pipe_slow);
+
+ ins_pipe(iload_reg_mem);
%}
+// Load Pointer Volatile
+instruct zLoadPVolatile(iRegPNoSp dst, indirect mem /* sync_memory */, rFlagsReg cr)
+%{
+ match(Set dst (LoadP mem));
+ predicate(UseZGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() == ZLoadBarrierStrong);
+ effect(TEMP dst, KILL cr);
-// Specialized versions of compareAndExchangeP that adds a keepalive that is consumed
-// but doesn't affect output.
+ ins_cost(VOLATILE_REF_COST);
-instruct z_compareAndExchangeP(iRegPNoSp res, indirect mem,
- iRegP oldval, iRegP newval, iRegP keepalive,
- rFlagsReg cr) %{
- match(Set res (ZCompareAndExchangeP (Binary mem keepalive) (Binary oldval newval)));
- ins_cost(2 * VOLATILE_REF_COST);
- effect(TEMP_DEF res, KILL cr);
- format %{
- "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
+ format %{ "ldar $dst, $mem\t" %}
+
+ ins_encode %{
+ __ ldar($dst$$Register, $mem$$Register);
+ if (barrier_data() != ZLoadBarrierElided) {
+ z_load_barrier(_masm, this, Address($mem$$Register), $dst$$Register, rscratch2 /* tmp */, false /* weak */);
+ }
%}
- ins_encode %{
- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
- Assembler::xword, /*acquire*/ false, /*release*/ true,
- /*weak*/ false, $res$$Register);
- %}
- ins_pipe(pipe_slow);
+
+ ins_pipe(pipe_serial);
%}
-instruct z_compareAndSwapP(iRegINoSp res,
- indirect mem,
- iRegP oldval, iRegP newval, iRegP keepalive,
- rFlagsReg cr) %{
-
- match(Set res (ZCompareAndSwapP (Binary mem keepalive) (Binary oldval newval)));
- match(Set res (ZWeakCompareAndSwapP (Binary mem keepalive) (Binary oldval newval)));
+instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+ predicate(UseZGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(KILL cr, TEMP_DEF res);
ins_cost(2 * VOLATILE_REF_COST);
- effect(KILL cr);
+ format %{ "cmpxchg $mem, $oldval, $newval\n\t"
+ "cset $res, EQ" %}
- format %{
- "cmpxchg $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
- "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
- %}
-
- ins_encode(aarch64_enc_cmpxchg(mem, oldval, newval),
- aarch64_enc_cset_eq(res));
+ ins_encode %{
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ false /* acquire */, true /* release */, false /* weak */, rscratch2);
+ __ cset($res$$Register, Assembler::EQ);
+ if (barrier_data() != ZLoadBarrierElided) {
+ Label good;
+ __ ldr(rscratch1, Address(rthread, ZThreadLocalData::address_bad_mask_offset()));
+ __ andr(rscratch1, rscratch1, rscratch2);
+ __ cbz(rscratch1, good);
+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), rscratch2 /* ref */, rscratch1 /* tmp */);
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ false /* acquire */, true /* release */, false /* weak */, rscratch2);
+ __ cset($res$$Register, Assembler::EQ);
+ __ bind(good);
+ }
+ %}
ins_pipe(pipe_slow);
%}
+instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+ predicate(UseZGC && needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong));
+ effect(KILL cr, TEMP_DEF res);
-instruct z_get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev,
- iRegP keepalive) %{
- match(Set prev (ZGetAndSetP mem (Binary newv keepalive)));
+ ins_cost(2 * VOLATILE_REF_COST);
+
+ format %{ "cmpxchg $mem, $oldval, $newval\n\t"
+ "cset $res, EQ" %}
+
+ ins_encode %{
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ true /* acquire */, true /* release */, false /* weak */, rscratch2);
+ __ cset($res$$Register, Assembler::EQ);
+ if (barrier_data() != ZLoadBarrierElided) {
+ Label good;
+ __ ldr(rscratch1, Address(rthread, ZThreadLocalData::address_bad_mask_offset()));
+ __ andr(rscratch1, rscratch1, rscratch2);
+ __ cbz(rscratch1, good);
+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), rscratch2 /* ref */, rscratch1 /* tmp */ );
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ true /* acquire */, true /* release */, false /* weak */, rscratch2);
+ __ cset($res$$Register, Assembler::EQ);
+ __ bind(good);
+ }
+ %}
+
+ ins_pipe(pipe_slow);
+%}
+
+instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
+ predicate(UseZGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(TEMP_DEF res, KILL cr);
ins_cost(2 * VOLATILE_REF_COST);
- format %{ "atomic_xchg $prev, $newv, [$mem]" %}
+
+ format %{ "cmpxchg $res = $mem, $oldval, $newval" %}
+
+ ins_encode %{
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ false /* acquire */, true /* release */, false /* weak */, $res$$Register);
+ if (barrier_data() != ZLoadBarrierElided) {
+ Label good;
+ __ ldr(rscratch1, Address(rthread, ZThreadLocalData::address_bad_mask_offset()));
+ __ andr(rscratch1, rscratch1, $res$$Register);
+ __ cbz(rscratch1, good);
+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, rscratch1 /* tmp */);
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ false /* acquire */, true /* release */, false /* weak */, $res$$Register);
+ __ bind(good);
+ }
+ %}
+
+ ins_pipe(pipe_slow);
+%}
+
+instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
+ predicate(UseZGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(TEMP_DEF res, KILL cr);
+
+ ins_cost(2 * VOLATILE_REF_COST);
+
+ format %{ "cmpxchg $res = $mem, $oldval, $newval" %}
+
ins_encode %{
- __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base));
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ true /* acquire */, true /* release */, false /* weak */, $res$$Register);
+ if (barrier_data() != ZLoadBarrierElided) {
+ Label good;
+ __ ldr(rscratch1, Address(rthread, ZThreadLocalData::address_bad_mask_offset()));
+ __ andr(rscratch1, rscratch1, $res$$Register);
+ __ cbz(rscratch1, good);
+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, rscratch1 /* tmp */);
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
+ true /* acquire */, true /* release */, false /* weak */, $res$$Register);
+ __ bind(good);
+ }
+ %}
+
+ ins_pipe(pipe_slow);
+%}
+
+instruct zGetAndSetP(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{
+ match(Set prev (GetAndSetP mem newv));
+ predicate(UseZGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(TEMP_DEF prev, KILL cr);
+
+ ins_cost(2 * VOLATILE_REF_COST);
+
+ format %{ "atomic_xchg $prev, $newv, [$mem]" %}
+
+ ins_encode %{
+ __ atomic_xchg($prev$$Register, $newv$$Register, $mem$$Register);
+ if (barrier_data() != ZLoadBarrierElided) {
+ z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, rscratch2 /* tmp */, false /* weak */);
+ }
+ %}
+
+ ins_pipe(pipe_serial);
+%}
+
+instruct zGetAndSetPAcq(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{
+ match(Set prev (GetAndSetP mem newv));
+ predicate(UseZGC && needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong));
+ effect(TEMP_DEF prev, KILL cr);
+
+ ins_cost(VOLATILE_REF_COST);
+
+ format %{ "atomic_xchg_acq $prev, $newv, [$mem]" %}
+
+ ins_encode %{
+ __ atomic_xchgal($prev$$Register, $newv$$Register, $mem$$Register);
+ if (barrier_data() != ZLoadBarrierElided) {
+ z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, rscratch2 /* tmp */, false /* weak */);
+ }
%}
ins_pipe(pipe_serial);
%}
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -2132,6 +2132,65 @@
return count;
}
+
+// Push lots of registers in the bit set supplied. Don't push sp.
+// Return the number of words pushed
+int MacroAssembler::push_fp(unsigned int bitset, Register stack) {
+ int words_pushed = 0;
+
+ // Scan bitset to accumulate register pairs
+ unsigned char regs[32];
+ int count = 0;
+ for (int reg = 0; reg <= 31; reg++) {
+ if (1 & bitset)
+ regs[count++] = reg;
+ bitset >>= 1;
+ }
+ regs[count++] = zr->encoding_nocheck();
+ count &= ~1; // Only push an even number of regs
+
+ // Always pushing full 128 bit registers.
+ if (count) {
+ stpq(as_FloatRegister(regs[0]), as_FloatRegister(regs[1]), Address(pre(stack, -count * wordSize * 2)));
+ words_pushed += 2;
+ }
+ for (int i = 2; i < count; i += 2) {
+ stpq(as_FloatRegister(regs[i]), as_FloatRegister(regs[i+1]), Address(stack, i * wordSize * 2));
+ words_pushed += 2;
+ }
+
+ assert(words_pushed == count, "oops, pushed != count");
+ return count;
+}
+
+int MacroAssembler::pop_fp(unsigned int bitset, Register stack) {
+ int words_pushed = 0;
+
+ // Scan bitset to accumulate register pairs
+ unsigned char regs[32];
+ int count = 0;
+ for (int reg = 0; reg <= 31; reg++) {
+ if (1 & bitset)
+ regs[count++] = reg;
+ bitset >>= 1;
+ }
+ regs[count++] = zr->encoding_nocheck();
+ count &= ~1;
+
+ for (int i = 2; i < count; i += 2) {
+ ldpq(as_FloatRegister(regs[i]), as_FloatRegister(regs[i+1]), Address(stack, i * wordSize * 2));
+ words_pushed += 2;
+ }
+ if (count) {
+ ldpq(as_FloatRegister(regs[0]), as_FloatRegister(regs[1]), Address(post(stack, count * wordSize * 2)));
+ words_pushed += 2;
+ }
+
+ assert(words_pushed == count, "oops, pushed != count");
+
+ return count;
+}
+
#ifdef ASSERT
void MacroAssembler::verify_heapbase(const char* msg) {
#if 0
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -442,12 +442,18 @@
int push(unsigned int bitset, Register stack);
int pop(unsigned int bitset, Register stack);
+ int push_fp(unsigned int bitset, Register stack);
+ int pop_fp(unsigned int bitset, Register stack);
+
void mov(Register dst, Address a);
public:
void push(RegSet regs, Register stack) { if (regs.bits()) push(regs.bits(), stack); }
void pop(RegSet regs, Register stack) { if (regs.bits()) pop(regs.bits(), stack); }
+ void push_fp(RegSet regs, Register stack) { if (regs.bits()) push_fp(regs.bits(), stack); }
+ void pop_fp(RegSet regs, Register stack) { if (regs.bits()) pop_fp(regs.bits(), stack); }
+
// Push and pop everything that might be clobbered by a native
// runtime call except rscratch1 and rscratch2. (They are always
// scratch, so we don't have to protect them.) Only save the lower
--- a/src/hotspot/cpu/aarch64/register_aarch64.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -230,6 +230,11 @@
return *this;
}
+ RegSet &operator-=(const RegSet aSet) {
+ *this = *this - aSet;
+ return *this;
+ }
+
static RegSet of(Register r1) {
return RegSet(r1);
}
--- a/src/hotspot/cpu/arm/compiledIC_arm.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -115,16 +115,7 @@
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
-
-#ifdef ASSERT
- // read the value once
- volatile intptr_t data = method_holder->data();
- volatile address destination = jump->jump_destination();
- assert(data == 0 || data == (intptr_t)callee(),
- "a) MT-unsafe modification of inline cache");
- assert(destination == (address)-1 || destination == entry,
- "b) MT-unsafe modification of inline cache");
-#endif
+ verify_mt_safe(callee, entry, method_holder, jump);
// Update stub.
method_holder->set_data((intptr_t)callee());
--- a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -178,15 +178,7 @@
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
-#ifdef ASSERT
- // read the value once
- volatile intptr_t data = method_holder->data();
- volatile address destination = jump->jump_destination();
- assert(data == 0 || data == (intptr_t)callee(),
- "a) MT-unsafe modification of inline cache");
- assert(destination == (address)-1 || destination == entry,
- "b) MT-unsafe modification of inline cache");
-#endif
+ verify_mt_safe(callee, entry, method_holder, jump);
// Update stub.
method_holder->set_data((intptr_t)callee());
--- a/src/hotspot/cpu/s390/compiledIC_s390.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/s390/compiledIC_s390.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -104,19 +104,7 @@
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
-
-#ifdef ASSERT
- // A generated lambda form might be deleted from the Lambdaform
- // cache in MethodTypeForm. If a jit compiled lambdaform method
- // becomes not entrant and the cache access returns null, the new
- // resolve will lead to a new generated LambdaForm.
- volatile intptr_t data = method_holder->data();
- volatile address destination = jump->jump_destination();
- assert(data == 0 || data == (intptr_t)callee() || callee->is_compiled_lambda_form(),
- "a) MT-unsafe modification of inline cache");
- assert(destination == (address)-1 || destination == entry,
- "b) MT-unsafe modification of inline cache");
-#endif
+ verify_mt_safe(callee, entry, method_holder, jump);
// Update stub.
method_holder->set_data((intptr_t)callee(), relocInfo::metadata_type);
--- a/src/hotspot/cpu/sparc/compiledIC_sparc.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/sparc/compiledIC_sparc.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,16 +104,7 @@
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
-
-#ifdef ASSERT
- // read the value once
- volatile intptr_t data = method_holder->data();
- volatile address destination = jump->jump_destination();
- assert(data == 0 || data == (intptr_t)callee(),
- "a) MT-unsafe modification of inline cache");
- assert(destination == (address)-1 || destination == entry,
- "b) MT-unsafe modification of inline cache");
-#endif
+ verify_mt_safe(callee, entry, method_holder, jump);
// Update stub.
method_holder->set_data((intptr_t)callee());
--- a/src/hotspot/cpu/x86/compiledIC_x86.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/compiledIC_x86.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -157,16 +157,7 @@
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
-
-#ifdef ASSERT
- Method* old_method = reinterpret_cast<Method*>(method_holder->data());
- address destination = jump->jump_destination();
- assert(old_method == NULL || old_method == callee() ||
- !old_method->method_holder()->is_loader_alive(),
- "a) MT-unsafe modification of inline cache");
- assert(destination == (address)-1 || destination == entry,
- "b) MT-unsafe modification of inline cache");
-#endif
+ verify_mt_safe(callee, entry, method_holder, jump);
// Update stub.
method_holder->set_data((intptr_t)callee());
--- a/src/hotspot/cpu/x86/gc/z/zArguments_x86.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/gc/z/zArguments_x86.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -23,20 +23,7 @@
#include "precompiled.hpp"
#include "gc/z/zArguments.hpp"
-#include "runtime/globals.hpp"
-#include "runtime/globals_extension.hpp"
-#include "utilities/debug.hpp"
void ZArguments::initialize_platform() {
-#ifdef COMPILER2
- // The C2 barrier slow path expects vector registers to be least
- // 16 bytes wide, which is the minimum width available on all
- // x86-64 systems. However, the user could have speficied a lower
- // number on the command-line, in which case we print a warning
- // and raise it to 16.
- if (MaxVectorSize < 16) {
- warning("ZGC requires MaxVectorSize to be at least 16");
- FLAG_SET_DEFAULT(MaxVectorSize, 16);
- }
-#endif
+ // Does nothing
}
--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -24,22 +24,22 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/codeBlob.hpp"
+#include "code/vmreg.inline.hpp"
#include "gc/z/zBarrier.inline.hpp"
#include "gc/z/zBarrierSet.hpp"
#include "gc/z/zBarrierSetAssembler.hpp"
#include "gc/z/zBarrierSetRuntime.hpp"
#include "memory/resourceArea.hpp"
-#include "runtime/stubCodeGenerator.hpp"
+#include "runtime/sharedRuntime.hpp"
#include "utilities/macros.hpp"
#ifdef COMPILER1
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "gc/z/c1/zBarrierSetC1.hpp"
#endif // COMPILER1
-
-ZBarrierSetAssembler::ZBarrierSetAssembler() :
- _load_barrier_slow_stub(),
- _load_barrier_weak_slow_stub() {}
+#ifdef COMPILER2
+#include "gc/z/c2/zBarrierSetC2.hpp"
+#endif // COMPILER2
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -344,137 +344,327 @@
#endif // COMPILER1
+#ifdef COMPILER2
+
+OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) {
+ if (!OptoReg::is_reg(opto_reg)) {
+ return OptoReg::Bad;
+ }
+
+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg);
+ if (vm_reg->is_XMMRegister()) {
+ opto_reg &= ~15;
+ switch (node->ideal_reg()) {
+ case Op_VecX:
+ opto_reg |= 2;
+ break;
+ case Op_VecY:
+ opto_reg |= 4;
+ break;
+ case Op_VecZ:
+ opto_reg |= 8;
+ break;
+ default:
+ opto_reg |= 1;
+ break;
+ }
+ }
+
+ return opto_reg;
+}
+
+// We use the vec_spill_helper from the x86.ad file to avoid reinventing this wheel
+extern int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
+ int stack_offset, int reg, uint ireg, outputStream* st);
+
#undef __
-#define __ cgen->assembler()->
+#define __ _masm->
+
+class ZSaveLiveRegisters {
+private:
+ struct XMMRegisterData {
+ XMMRegister _reg;
+ int _size;
+
+ // Used by GrowableArray::find()
+ bool operator == (const XMMRegisterData& other) {
+ return _reg == other._reg;
+ }
+ };
+
+ MacroAssembler* const _masm;
+ GrowableArray<Register> _gp_registers;
+ GrowableArray<XMMRegisterData> _xmm_registers;
+ int _spill_size;
+ int _spill_offset;
-// Generates a register specific stub for calling
-// ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or
-// ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded().
-//
-// The raddr register serves as both input and output for this stub. When the stub is
-// called the raddr register contains the object field address (oop*) where the bad oop
-// was loaded from, which caused the slow path to be taken. On return from the stub the
-// raddr register contains the good/healed oop returned from
-// ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or
-// ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded().
-static address generate_load_barrier_stub(StubCodeGenerator* cgen, Register raddr, DecoratorSet decorators) {
- // Don't generate stub for invalid registers
- if (raddr == rsp || raddr == r15) {
- return NULL;
+ static int xmm_compare_register_size(XMMRegisterData* left, XMMRegisterData* right) {
+ if (left->_size == right->_size) {
+ return 0;
+ }
+
+ return (left->_size < right->_size) ? -1 : 1;
+ }
+
+ static int xmm_slot_size(OptoReg::Name opto_reg) {
+ // The low order 4 bytes denote what size of the XMM register is live
+ return (opto_reg & 15) << 3;
+ }
+
+ static uint xmm_ideal_reg_for_size(int reg_size) {
+ switch (reg_size) {
+ case 8:
+ return Op_VecD;
+ case 16:
+ return Op_VecX;
+ case 32:
+ return Op_VecY;
+ case 64:
+ return Op_VecZ;
+ default:
+ fatal("Invalid register size %d", reg_size);
+ return 0;
+ }
+ }
+
+ bool xmm_needs_vzeroupper() const {
+ return _xmm_registers.is_nonempty() && _xmm_registers.at(0)._size > 16;
+ }
+
+ void xmm_register_save(const XMMRegisterData& reg_data) {
+ const OptoReg::Name opto_reg = OptoReg::as_OptoReg(reg_data._reg->as_VMReg());
+ const uint ideal_reg = xmm_ideal_reg_for_size(reg_data._size);
+ _spill_offset -= reg_data._size;
+ vec_spill_helper(__ code(), false /* do_size */, false /* is_load */, _spill_offset, opto_reg, ideal_reg, tty);
+ }
+
+ void xmm_register_restore(const XMMRegisterData& reg_data) {
+ const OptoReg::Name opto_reg = OptoReg::as_OptoReg(reg_data._reg->as_VMReg());
+ const uint ideal_reg = xmm_ideal_reg_for_size(reg_data._size);
+ vec_spill_helper(__ code(), false /* do_size */, true /* is_load */, _spill_offset, opto_reg, ideal_reg, tty);
+ _spill_offset += reg_data._size;
+ }
+
+ void gp_register_save(Register reg) {
+ _spill_offset -= 8;
+ __ movq(Address(rsp, _spill_offset), reg);
+ }
+
+ void gp_register_restore(Register reg) {
+ __ movq(reg, Address(rsp, _spill_offset));
+ _spill_offset += 8;
}
- // Create stub name
- char name[64];
- const bool weak = (decorators & ON_WEAK_OOP_REF) != 0;
- os::snprintf(name, sizeof(name), "zgc_load_barrier%s_stub_%s", weak ? "_weak" : "", raddr->name());
+ void initialize(ZLoadBarrierStubC2* stub) {
+ // Create mask of caller saved registers that need to
+ // be saved/restored if live
+ RegMask caller_saved;
+ caller_saved.Insert(OptoReg::as_OptoReg(rax->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(rcx->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(rdx->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(rsi->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(rdi->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(r8->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(r9->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(r10->as_VMReg()));
+ caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg()));
+ caller_saved.Remove(OptoReg::as_OptoReg(stub->ref()->as_VMReg()));
- __ align(CodeEntryAlignment);
- StubCodeMark mark(cgen, "StubRoutines", os::strdup(name, mtCode));
- address start = __ pc();
+ // Create mask of live registers
+ RegMask live = stub->live();
+ if (stub->tmp() != noreg) {
+ live.Insert(OptoReg::as_OptoReg(stub->tmp()->as_VMReg()));
+ }
+
+ int gp_spill_size = 0;
+ int xmm_spill_size = 0;
+
+ // Record registers that needs to be saved/restored
+ while (live.is_NotEmpty()) {
+ const OptoReg::Name opto_reg = live.find_first_elem();
+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg);
+
+ live.Remove(opto_reg);
- // Save live registers
- if (raddr != rax) {
- __ push(rax);
- }
- if (raddr != rcx) {
- __ push(rcx);
- }
- if (raddr != rdx) {
- __ push(rdx);
- }
- if (raddr != rsi) {
- __ push(rsi);
- }
- if (raddr != rdi) {
- __ push(rdi);
- }
- if (raddr != r8) {
- __ push(r8);
- }
- if (raddr != r9) {
- __ push(r9);
- }
- if (raddr != r10) {
- __ push(r10);
- }
- if (raddr != r11) {
- __ push(r11);
+ if (vm_reg->is_Register()) {
+ if (caller_saved.Member(opto_reg)) {
+ _gp_registers.append(vm_reg->as_Register());
+ gp_spill_size += 8;
+ }
+ } else if (vm_reg->is_XMMRegister()) {
+ // We encode in the low order 4 bits of the opto_reg, how large part of the register is live
+ const VMReg vm_reg_base = OptoReg::as_VMReg(opto_reg & ~15);
+ const int reg_size = xmm_slot_size(opto_reg);
+ const XMMRegisterData reg_data = { vm_reg_base->as_XMMRegister(), reg_size };
+ const int reg_index = _xmm_registers.find(reg_data);
+ if (reg_index == -1) {
+ // Not previously appended
+ _xmm_registers.append(reg_data);
+ xmm_spill_size += reg_size;
+ } else {
+ // Previously appended, update size
+ const int reg_size_prev = _xmm_registers.at(reg_index)._size;
+ if (reg_size > reg_size_prev) {
+ _xmm_registers.at_put(reg_index, reg_data);
+ xmm_spill_size += reg_size - reg_size_prev;
+ }
+ }
+ } else {
+ fatal("Unexpected register type");
+ }
+ }
+
+ // Sort by size, largest first
+ _xmm_registers.sort(xmm_compare_register_size);
+
+ // Stack pointer must be 16 bytes aligned for the call
+ _spill_offset = _spill_size = align_up(xmm_spill_size + gp_spill_size, 16);
}
- // Setup arguments
- if (raddr != c_rarg1) {
- __ movq(c_rarg1, raddr);
- }
- __ movq(c_rarg0, Address(raddr, 0));
+public:
+ ZSaveLiveRegisters(MacroAssembler* masm, ZLoadBarrierStubC2* stub) :
+ _masm(masm),
+ _gp_registers(),
+ _xmm_registers(),
+ _spill_size(0),
+ _spill_offset(0) {
- // Call barrier function
- __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), c_rarg0, c_rarg1);
+ //
+ // Stack layout after registers have been spilled:
+ //
+ // | ... | original rsp, 16 bytes aligned
+ // ------------------
+ // | zmm0 high |
+ // | ... |
+ // | zmm0 low | 16 bytes aligned
+ // | ... |
+ // | ymm1 high |
+ // | ... |
+ // | ymm1 low | 16 bytes aligned
+ // | ... |
+ // | xmmN high |
+ // | ... |
+ // | xmmN low | 8 bytes aligned
+ // | reg0 | 8 bytes aligned
+ // | reg1 |
+ // | ... |
+ // | regN | new rsp, if 16 bytes aligned
+ // | <padding> | else new rsp, 16 bytes aligned
+ // ------------------
+ //
- // Move result returned in rax to raddr, if needed
- if (raddr != rax) {
- __ movq(raddr, rax);
+ // Figure out what registers to save/restore
+ initialize(stub);
+
+ // Allocate stack space
+ if (_spill_size > 0) {
+ __ subptr(rsp, _spill_size);
+ }
+
+ // Save XMM/YMM/ZMM registers
+ for (int i = 0; i < _xmm_registers.length(); i++) {
+ xmm_register_save(_xmm_registers.at(i));
+ }
+
+ if (xmm_needs_vzeroupper()) {
+ __ vzeroupper();
+ }
+
+ // Save general purpose registers
+ for (int i = 0; i < _gp_registers.length(); i++) {
+ gp_register_save(_gp_registers.at(i));
+ }
}
- // Restore saved registers
- if (raddr != r11) {
- __ pop(r11);
- }
- if (raddr != r10) {
- __ pop(r10);
- }
- if (raddr != r9) {
- __ pop(r9);
- }
- if (raddr != r8) {
- __ pop(r8);
+ ~ZSaveLiveRegisters() {
+ // Restore general purpose registers
+ for (int i = _gp_registers.length() - 1; i >= 0; i--) {
+ gp_register_restore(_gp_registers.at(i));
+ }
+
+ __ vzeroupper();
+
+ // Restore XMM/YMM/ZMM registers
+ for (int i = _xmm_registers.length() - 1; i >= 0; i--) {
+ xmm_register_restore(_xmm_registers.at(i));
+ }
+
+ // Free stack space
+ if (_spill_size > 0) {
+ __ addptr(rsp, _spill_size);
+ }
}
- if (raddr != rdi) {
- __ pop(rdi);
- }
- if (raddr != rsi) {
- __ pop(rsi);
- }
- if (raddr != rdx) {
- __ pop(rdx);
- }
- if (raddr != rcx) {
- __ pop(rcx);
- }
- if (raddr != rax) {
- __ pop(rax);
+};
+
+class ZSetupArguments {
+private:
+ MacroAssembler* const _masm;
+ const Register _ref;
+ const Address _ref_addr;
+
+public:
+ ZSetupArguments(MacroAssembler* masm, ZLoadBarrierStubC2* stub) :
+ _masm(masm),
+ _ref(stub->ref()),
+ _ref_addr(stub->ref_addr()) {
+
+ // Setup arguments
+ if (_ref_addr.base() == noreg) {
+ // No self healing
+ if (_ref != c_rarg0) {
+ __ movq(c_rarg0, _ref);
+ }
+ __ xorq(c_rarg1, c_rarg1);
+ } else {
+ // Self healing
+ if (_ref == c_rarg0) {
+ __ lea(c_rarg1, _ref_addr);
+ } else if (_ref != c_rarg1) {
+ __ lea(c_rarg1, _ref_addr);
+ __ movq(c_rarg0, _ref);
+ } else if (_ref_addr.base() != c_rarg0 && _ref_addr.index() != c_rarg0) {
+ __ movq(c_rarg0, _ref);
+ __ lea(c_rarg1, _ref_addr);
+ } else {
+ __ xchgq(c_rarg0, c_rarg1);
+ if (_ref_addr.base() == c_rarg0) {
+ __ lea(c_rarg1, Address(c_rarg1, _ref_addr.index(), _ref_addr.scale(), _ref_addr.disp()));
+ } else if (_ref_addr.index() == c_rarg0) {
+ __ lea(c_rarg1, Address(_ref_addr.base(), c_rarg1, _ref_addr.scale(), _ref_addr.disp()));
+ } else {
+ ShouldNotReachHere();
+ }
+ }
+ }
}
- __ ret(0);
+ ~ZSetupArguments() {
+ // Transfer result
+ if (_ref != rax) {
+ __ movq(_ref, rax);
+ }
+ }
+};
+
+#undef __
+#define __ masm->
- return start;
+void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const {
+ BLOCK_COMMENT("ZLoadBarrierStubC2");
+
+ // Stub entry
+ __ bind(*stub->entry());
+
+ {
+ ZSaveLiveRegisters save_live_registers(masm, stub);
+ ZSetupArguments setup_arguments(masm, stub);
+ __ call(RuntimeAddress(stub->slow_path()));
+ }
+
+ // Stub exit
+ __ jmp(*stub->continuation());
}
#undef __
-static void barrier_stubs_init_inner(const char* label, const DecoratorSet decorators, address* stub) {
- const int nregs = RegisterImpl::number_of_registers;
- const int code_size = nregs * 128; // Rough estimate of code size
-
- ResourceMark rm;
-
- CodeBuffer buf(BufferBlob::create(label, code_size));
- StubCodeGenerator cgen(&buf);
-
- for (int i = 0; i < nregs; i++) {
- const Register reg = as_Register(i);
- stub[i] = generate_load_barrier_stub(&cgen, reg, decorators);
- }
-}
-
-void ZBarrierSetAssembler::barrier_stubs_init() {
- barrier_stubs_init_inner("zgc_load_barrier_stubs", ON_STRONG_OOP_REF, _load_barrier_slow_stub);
- barrier_stubs_init_inner("zgc_load_barrier_weak_stubs", ON_WEAK_OOP_REF, _load_barrier_weak_slow_stub);
-}
-
-address ZBarrierSetAssembler::load_barrier_slow_stub(Register reg) {
- return _load_barrier_slow_stub[reg->encoding()];
-}
-
-address ZBarrierSetAssembler::load_barrier_weak_slow_stub(Register reg) {
- return _load_barrier_weak_slow_stub[reg->encoding()];
-}
+#endif // COMPILER2
--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -24,6 +24,14 @@
#ifndef CPU_X86_GC_Z_ZBARRIERSETASSEMBLER_X86_HPP
#define CPU_X86_GC_Z_ZBARRIERSETASSEMBLER_X86_HPP
+#include "code/vmreg.hpp"
+#include "oops/accessDecorators.hpp"
+#ifdef COMPILER2
+#include "opto/optoreg.hpp"
+#endif // COMPILER2
+
+class MacroAssembler;
+
#ifdef COMPILER1
class LIR_Assembler;
class LIR_OprDesc;
@@ -32,14 +40,13 @@
class ZLoadBarrierStubC1;
#endif // COMPILER1
+#ifdef COMPILER2
+class Node;
+class ZLoadBarrierStubC2;
+#endif // COMPILER2
+
class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase {
-private:
- address _load_barrier_slow_stub[RegisterImpl::number_of_registers];
- address _load_barrier_weak_slow_stub[RegisterImpl::number_of_registers];
-
public:
- ZBarrierSetAssembler();
-
virtual void load_at(MacroAssembler* masm,
DecoratorSet decorators,
BasicType type,
@@ -82,10 +89,13 @@
DecoratorSet decorators) const;
#endif // COMPILER1
- virtual void barrier_stubs_init();
+#ifdef COMPILER2
+ OptoReg::Name refine_register(const Node* node,
+ OptoReg::Name opto_reg);
- address load_barrier_slow_stub(Register reg);
- address load_barrier_weak_slow_stub(Register reg);
+ void generate_c2_load_barrier_stub(MacroAssembler* masm,
+ ZLoadBarrierStubC2* stub) const;
+#endif // COMPILER2
};
#endif // CPU_X86_GC_Z_ZBARRIERSETASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad Wed Oct 09 23:22:56 2019 +0200
@@ -24,190 +24,144 @@
source_hpp %{
#include "gc/z/c2/zBarrierSetC2.hpp"
+#include "gc/z/zThreadLocalData.hpp"
%}
source %{
-#include "gc/z/zBarrierSetAssembler.hpp"
+static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) {
+ ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, weak);
+ __ testptr(ref, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset()));
+ __ jcc(Assembler::notZero, *stub->entry());
+ __ bind(*stub->continuation());
+}
-static void z_load_barrier_slow_reg(MacroAssembler& _masm, Register dst, Address src, bool weak) {
- assert(dst != rsp, "Invalid register");
- assert(dst != r15, "Invalid register");
-
- const address stub = weak ? ZBarrierSet::assembler()->load_barrier_weak_slow_stub(dst)
- : ZBarrierSet::assembler()->load_barrier_slow_stub(dst);
- __ lea(dst, src);
- __ call(RuntimeAddress(stub));
+static void z_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) {
+ ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, false /* weak */);
+ __ jmp(*stub->entry());
+ __ bind(*stub->continuation());
}
%}
-// For XMM and YMM enabled processors
-instruct zLoadBarrierSlowRegXmmAndYmm(rRegP dst, memory src, rFlagsReg cr,
- rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
- rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
- rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
- rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15) %{
- match(Set dst (LoadBarrierSlowReg src dst));
- predicate(UseAVX <= 2 && !n->as_LoadBarrierSlowReg()->is_weak());
+// Load Pointer
+instruct zLoadP(rRegP dst, memory mem, rFlagsReg cr)
+%{
+ predicate(UseZGC && n->as_Load()->barrier_data() == ZLoadBarrierStrong);
+ match(Set dst (LoadP mem));
+ effect(KILL cr, TEMP dst);
- effect(KILL cr,
- KILL x0, KILL x1, KILL x2, KILL x3,
- KILL x4, KILL x5, KILL x6, KILL x7,
- KILL x8, KILL x9, KILL x10, KILL x11,
- KILL x12, KILL x13, KILL x14, KILL x15);
+ ins_cost(125);
- format %{ "lea $dst, $src\n\t"
- "call #ZLoadBarrierSlowPath" %}
+ format %{ "movq $dst, $mem" %}
ins_encode %{
- z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, false /* weak */);
+ __ movptr($dst$$Register, $mem$$Address);
+ if (barrier_data() != ZLoadBarrierElided) {
+ z_load_barrier(_masm, this, $mem$$Address, $dst$$Register, noreg /* tmp */, false /* weak */);
+ }
%}
- ins_pipe(pipe_slow);
+
+ ins_pipe(ialu_reg_mem);
%}
-// For ZMM enabled processors
-instruct zLoadBarrierSlowRegZmm(rRegP dst, memory src, rFlagsReg cr,
- rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
- rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
- rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
- rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15,
- rxmm16 x16, rxmm17 x17, rxmm18 x18, rxmm19 x19,
- rxmm20 x20, rxmm21 x21, rxmm22 x22, rxmm23 x23,
- rxmm24 x24, rxmm25 x25, rxmm26 x26, rxmm27 x27,
- rxmm28 x28, rxmm29 x29, rxmm30 x30, rxmm31 x31) %{
+// Load Weak Pointer
+instruct zLoadWeakP(rRegP dst, memory mem, rFlagsReg cr)
+%{
+ predicate(UseZGC && n->as_Load()->barrier_data() == ZLoadBarrierWeak);
+ match(Set dst (LoadP mem));
+ effect(KILL cr, TEMP dst);
- match(Set dst (LoadBarrierSlowReg src dst));
- predicate(UseAVX == 3 && !n->as_LoadBarrierSlowReg()->is_weak());
+ ins_cost(125);
- effect(KILL cr,
- KILL x0, KILL x1, KILL x2, KILL x3,
- KILL x4, KILL x5, KILL x6, KILL x7,
- KILL x8, KILL x9, KILL x10, KILL x11,
- KILL x12, KILL x13, KILL x14, KILL x15,
- KILL x16, KILL x17, KILL x18, KILL x19,
- KILL x20, KILL x21, KILL x22, KILL x23,
- KILL x24, KILL x25, KILL x26, KILL x27,
- KILL x28, KILL x29, KILL x30, KILL x31);
-
- format %{ "lea $dst, $src\n\t"
- "call #ZLoadBarrierSlowPath" %}
+ format %{ "movq $dst, $mem" %}
ins_encode %{
- z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, false /* weak */);
+ __ movptr($dst$$Register, $mem$$Address);
+ z_load_barrier(_masm, this, $mem$$Address, $dst$$Register, noreg /* tmp */, true /* weak */);
%}
- ins_pipe(pipe_slow);
-%}
-
-// For XMM and YMM enabled processors
-instruct zLoadBarrierWeakSlowRegXmmAndYmm(rRegP dst, memory src, rFlagsReg cr,
- rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
- rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
- rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
- rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15) %{
- match(Set dst (LoadBarrierSlowReg src dst));
- predicate(UseAVX <= 2 && n->as_LoadBarrierSlowReg()->is_weak());
- effect(KILL cr,
- KILL x0, KILL x1, KILL x2, KILL x3,
- KILL x4, KILL x5, KILL x6, KILL x7,
- KILL x8, KILL x9, KILL x10, KILL x11,
- KILL x12, KILL x13, KILL x14, KILL x15);
-
- format %{ "lea $dst, $src\n\t"
- "call #ZLoadBarrierSlowPath" %}
-
- ins_encode %{
- z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, true /* weak */);
- %}
- ins_pipe(pipe_slow);
+ ins_pipe(ialu_reg_mem);
%}
-// For ZMM enabled processors
-instruct zLoadBarrierWeakSlowRegZmm(rRegP dst, memory src, rFlagsReg cr,
- rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
- rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
- rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
- rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15,
- rxmm16 x16, rxmm17 x17, rxmm18 x18, rxmm19 x19,
- rxmm20 x20, rxmm21 x21, rxmm22 x22, rxmm23 x23,
- rxmm24 x24, rxmm25 x25, rxmm26 x26, rxmm27 x27,
- rxmm28 x28, rxmm29 x29, rxmm30 x30, rxmm31 x31) %{
+instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{
+ match(Set oldval (CompareAndExchangeP mem (Binary oldval newval)));
+ predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(KILL cr, TEMP tmp);
- match(Set dst (LoadBarrierSlowReg src dst));
- predicate(UseAVX == 3 && n->as_LoadBarrierSlowReg()->is_weak());
-
- effect(KILL cr,
- KILL x0, KILL x1, KILL x2, KILL x3,
- KILL x4, KILL x5, KILL x6, KILL x7,
- KILL x8, KILL x9, KILL x10, KILL x11,
- KILL x12, KILL x13, KILL x14, KILL x15,
- KILL x16, KILL x17, KILL x18, KILL x19,
- KILL x20, KILL x21, KILL x22, KILL x23,
- KILL x24, KILL x25, KILL x26, KILL x27,
- KILL x28, KILL x29, KILL x30, KILL x31);
-
- format %{ "lea $dst, $src\n\t"
- "call #ZLoadBarrierSlowPath" %}
+ format %{ "lock\n\t"
+ "cmpxchgq $newval, $mem" %}
ins_encode %{
- z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, true /* weak */);
+ if (barrier_data() != ZLoadBarrierElided) {
+ __ movptr($tmp$$Register, $oldval$$Register);
+ }
+ __ lock();
+ __ cmpxchgptr($newval$$Register, $mem$$Address);
+ if (barrier_data() != ZLoadBarrierElided) {
+ Label good;
+ __ testptr($oldval$$Register, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset()));
+ __ jcc(Assembler::zero, good);
+ z_load_barrier_slow_path(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register);
+ __ movptr($oldval$$Register, $tmp$$Register);
+ __ lock();
+ __ cmpxchgptr($newval$$Register, $mem$$Address);
+ __ bind(good);
+ }
%}
- ins_pipe(pipe_slow);
+
+ ins_pipe(pipe_cmpxchg);
%}
-// Specialized versions of compareAndExchangeP that adds a keepalive that is consumed
-// but doesn't affect output.
+instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{
+ match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+ match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+ predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(KILL cr, KILL oldval, TEMP tmp);
+
+ format %{ "lock\n\t"
+ "cmpxchgq $newval, $mem\n\t"
+ "sete $res\n\t"
+ "movzbl $res, $res" %}
-instruct z_compareAndExchangeP(
- memory mem_ptr,
- rax_RegP oldval, rRegP newval, rRegP keepalive,
- rFlagsReg cr) %{
- predicate(VM_Version::supports_cx8());
- match(Set oldval (ZCompareAndExchangeP (Binary mem_ptr keepalive) (Binary oldval newval)));
- effect(KILL cr);
+ ins_encode %{
+ if (barrier_data() != ZLoadBarrierElided) {
+ __ movptr($tmp$$Register, $oldval$$Register);
+ }
+ __ lock();
+ __ cmpxchgptr($newval$$Register, $mem$$Address);
+ if (barrier_data() != ZLoadBarrierElided) {
+ Label good;
+ __ testptr($oldval$$Register, Address(r15_thread, ZThreadLocalData::address_bad_mask_offset()));
+ __ jcc(Assembler::zero, good);
+ z_load_barrier_slow_path(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register);
+ __ movptr($oldval$$Register, $tmp$$Register);
+ __ lock();
+ __ cmpxchgptr($newval$$Register, $mem$$Address);
+ __ bind(good);
+ __ cmpptr($tmp$$Register, $oldval$$Register);
+ }
+ __ setb(Assembler::equal, $res$$Register);
+ __ movzbl($res$$Register, $res$$Register);
+ %}
- format %{ "cmpxchgq $mem_ptr,$newval\t# "
- "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
- opcode(0x0F, 0xB1);
- ins_encode(lock_prefix,
- REX_reg_mem_wide(newval, mem_ptr),
- OpcP, OpcS,
- reg_mem(newval, mem_ptr) // lock cmpxchg
- );
- ins_pipe( pipe_cmpxchg );
+ ins_pipe(pipe_cmpxchg);
%}
-instruct z_compareAndSwapP(rRegI res,
- memory mem_ptr,
- rax_RegP oldval, rRegP newval, rRegP keepalive,
- rFlagsReg cr) %{
- predicate(VM_Version::supports_cx8());
- match(Set res (ZCompareAndSwapP (Binary mem_ptr keepalive) (Binary oldval newval)));
- match(Set res (ZWeakCompareAndSwapP (Binary mem_ptr keepalive) (Binary oldval newval)));
- effect(KILL cr, KILL oldval);
+instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{
+ match(Set newval (GetAndSetP mem newval));
+ predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong);
+ effect(KILL cr);
+
+ format %{ "xchgq $newval, $mem" %}
- format %{ "cmpxchgq $mem_ptr,$newval\t# "
- "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
- "sete $res\n\t"
- "movzbl $res, $res" %}
- opcode(0x0F, 0xB1);
- ins_encode(lock_prefix,
- REX_reg_mem_wide(newval, mem_ptr),
- OpcP, OpcS,
- reg_mem(newval, mem_ptr),
- REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete
- REX_reg_breg(res, res), // movzbl
- Opcode(0xF), Opcode(0xB6), reg_reg(res, res));
- ins_pipe( pipe_cmpxchg );
+ ins_encode %{
+ __ xchgptr($newval$$Register, $mem$$Address);
+ if (barrier_data() != ZLoadBarrierElided) {
+ z_load_barrier(_masm, this, Address(noreg, 0), $newval$$Register, noreg /* tmp */, false /* weak */);
+ }
+ %}
+
+ ins_pipe(pipe_cmpxchg);
%}
-
-instruct z_xchgP( memory mem, rRegP newval, rRegP keepalive) %{
- match(Set newval (ZGetAndSetP mem (Binary newval keepalive)));
- format %{ "XCHGQ $newval,[$mem]" %}
- ins_encode %{
- __ xchgq($newval$$Register, $mem$$Address);
- %}
- ins_pipe( pipe_cmpxchg );
-%}
--- a/src/hotspot/cpu/x86/x86.ad Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/x86.ad Wed Oct 09 23:22:56 2019 +0200
@@ -1097,138 +1097,6 @@
reg_class_dynamic vectorz_reg(vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() %} );
reg_class_dynamic vectorz_reg_vl(vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() && VM_Version::supports_avx512vl() %} );
-reg_class xmm0_reg(XMM0, XMM0b, XMM0c, XMM0d);
-reg_class ymm0_reg(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM0h);
-reg_class zmm0_reg(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM0h, XMM0i, XMM0j, XMM0k, XMM0l, XMM0m, XMM0n, XMM0o, XMM0p);
-
-reg_class xmm1_reg(XMM1, XMM1b, XMM1c, XMM1d);
-reg_class ymm1_reg(XMM1, XMM1b, XMM1c, XMM1d, XMM1e, XMM1f, XMM1g, XMM1h);
-reg_class zmm1_reg(XMM1, XMM1b, XMM1c, XMM1d, XMM1e, XMM1f, XMM1g, XMM1h, XMM1i, XMM1j, XMM1k, XMM1l, XMM1m, XMM1n, XMM1o, XMM1p);
-
-reg_class xmm2_reg(XMM2, XMM2b, XMM2c, XMM2d);
-reg_class ymm2_reg(XMM2, XMM2b, XMM2c, XMM2d, XMM2e, XMM2f, XMM2g, XMM2h);
-reg_class zmm2_reg(XMM2, XMM2b, XMM2c, XMM2d, XMM2e, XMM2f, XMM2g, XMM2h, XMM2i, XMM2j, XMM2k, XMM2l, XMM2m, XMM2n, XMM2o, XMM2p);
-
-reg_class xmm3_reg(XMM3, XMM3b, XMM3c, XMM3d);
-reg_class ymm3_reg(XMM3, XMM3b, XMM3c, XMM3d, XMM3e, XMM3f, XMM3g, XMM3h);
-reg_class zmm3_reg(XMM3, XMM3b, XMM3c, XMM3d, XMM3e, XMM3f, XMM3g, XMM3h, XMM3i, XMM3j, XMM3k, XMM3l, XMM3m, XMM3n, XMM3o, XMM3p);
-
-reg_class xmm4_reg(XMM4, XMM4b, XMM4c, XMM4d);
-reg_class ymm4_reg(XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h);
-reg_class zmm4_reg(XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h, XMM4i, XMM4j, XMM4k, XMM4l, XMM4m, XMM4n, XMM4o, XMM4p);
-
-reg_class xmm5_reg(XMM5, XMM5b, XMM5c, XMM5d);
-reg_class ymm5_reg(XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h);
-reg_class zmm5_reg(XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h, XMM5i, XMM5j, XMM5k, XMM5l, XMM5m, XMM5n, XMM5o, XMM5p);
-
-reg_class xmm6_reg(XMM6, XMM6b, XMM6c, XMM6d);
-reg_class ymm6_reg(XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h);
-reg_class zmm6_reg(XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h, XMM6i, XMM6j, XMM6k, XMM6l, XMM6m, XMM6n, XMM6o, XMM6p);
-
-reg_class xmm7_reg(XMM7, XMM7b, XMM7c, XMM7d);
-reg_class ymm7_reg(XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h);
-reg_class zmm7_reg(XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p);
-
-#ifdef _LP64
-
-reg_class xmm8_reg(XMM8, XMM8b, XMM8c, XMM8d);
-reg_class ymm8_reg(XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h);
-reg_class zmm8_reg(XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p);
-
-reg_class xmm9_reg(XMM9, XMM9b, XMM9c, XMM9d);
-reg_class ymm9_reg(XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h);
-reg_class zmm9_reg(XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h, XMM9i, XMM9j, XMM9k, XMM9l, XMM9m, XMM9n, XMM9o, XMM9p);
-
-reg_class xmm10_reg(XMM10, XMM10b, XMM10c, XMM10d);
-reg_class ymm10_reg(XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h);
-reg_class zmm10_reg(XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h, XMM10i, XMM10j, XMM10k, XMM10l, XMM10m, XMM10n, XMM10o, XMM10p);
-
-reg_class xmm11_reg(XMM11, XMM11b, XMM11c, XMM11d);
-reg_class ymm11_reg(XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h);
-reg_class zmm11_reg(XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h, XMM11i, XMM11j, XMM11k, XMM11l, XMM11m, XMM11n, XMM11o, XMM11p);
-
-reg_class xmm12_reg(XMM12, XMM12b, XMM12c, XMM12d);
-reg_class ymm12_reg(XMM12, XMM12b, XMM12c, XMM12d, XMM12e, XMM12f, XMM12g, XMM12h);
-reg_class zmm12_reg(XMM12, XMM12b, XMM12c, XMM12d, XMM12e, XMM12f, XMM12g, XMM12h, XMM12i, XMM12j, XMM12k, XMM12l, XMM12m, XMM12n, XMM12o, XMM12p);
-
-reg_class xmm13_reg(XMM13, XMM13b, XMM13c, XMM13d);
-reg_class ymm13_reg(XMM13, XMM13b, XMM13c, XMM13d, XMM13e, XMM13f, XMM13g, XMM13h);
-reg_class zmm13_reg(XMM13, XMM13b, XMM13c, XMM13d, XMM13e, XMM13f, XMM13g, XMM13h, XMM13i, XMM13j, XMM13k, XMM13l, XMM13m, XMM13n, XMM13o, XMM13p);
-
-reg_class xmm14_reg(XMM14, XMM14b, XMM14c, XMM14d);
-reg_class ymm14_reg(XMM14, XMM14b, XMM14c, XMM14d, XMM14e, XMM14f, XMM14g, XMM14h);
-reg_class zmm14_reg(XMM14, XMM14b, XMM14c, XMM14d, XMM14e, XMM14f, XMM14g, XMM14h, XMM14i, XMM14j, XMM14k, XMM14l, XMM14m, XMM14n, XMM14o, XMM14p);
-
-reg_class xmm15_reg(XMM15, XMM15b, XMM15c, XMM15d);
-reg_class ymm15_reg(XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h);
-reg_class zmm15_reg(XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p);
-
-reg_class xmm16_reg(XMM16, XMM16b, XMM16c, XMM16d);
-reg_class ymm16_reg(XMM16, XMM16b, XMM16c, XMM16d, XMM16e, XMM16f, XMM16g, XMM16h);
-reg_class zmm16_reg(XMM16, XMM16b, XMM16c, XMM16d, XMM16e, XMM16f, XMM16g, XMM16h, XMM16i, XMM16j, XMM16k, XMM16l, XMM16m, XMM16n, XMM16o, XMM16p);
-
-reg_class xmm17_reg(XMM17, XMM17b, XMM17c, XMM17d);
-reg_class ymm17_reg(XMM17, XMM17b, XMM17c, XMM17d, XMM17e, XMM17f, XMM17g, XMM17h);
-reg_class zmm17_reg(XMM17, XMM17b, XMM17c, XMM17d, XMM17e, XMM17f, XMM17g, XMM17h, XMM17i, XMM17j, XMM17k, XMM17l, XMM17m, XMM17n, XMM17o, XMM17p);
-
-reg_class xmm18_reg(XMM18, XMM18b, XMM18c, XMM18d);
-reg_class ymm18_reg(XMM18, XMM18b, XMM18c, XMM18d, XMM18e, XMM18f, XMM18g, XMM18h);
-reg_class zmm18_reg(XMM18, XMM18b, XMM18c, XMM18d, XMM18e, XMM18f, XMM18g, XMM18h, XMM18i, XMM18j, XMM18k, XMM18l, XMM18m, XMM18n, XMM18o, XMM18p);
-
-reg_class xmm19_reg(XMM19, XMM19b, XMM19c, XMM19d);
-reg_class ymm19_reg(XMM19, XMM19b, XMM19c, XMM19d, XMM19e, XMM19f, XMM19g, XMM19h);
-reg_class zmm19_reg(XMM19, XMM19b, XMM19c, XMM19d, XMM19e, XMM19f, XMM19g, XMM19h, XMM19i, XMM19j, XMM19k, XMM19l, XMM19m, XMM19n, XMM19o, XMM19p);
-
-reg_class xmm20_reg(XMM20, XMM20b, XMM20c, XMM20d);
-reg_class ymm20_reg(XMM20, XMM20b, XMM20c, XMM20d, XMM20e, XMM20f, XMM20g, XMM20h);
-reg_class zmm20_reg(XMM20, XMM20b, XMM20c, XMM20d, XMM20e, XMM20f, XMM20g, XMM20h, XMM20i, XMM20j, XMM20k, XMM20l, XMM20m, XMM20n, XMM20o, XMM20p);
-
-reg_class xmm21_reg(XMM21, XMM21b, XMM21c, XMM21d);
-reg_class ymm21_reg(XMM21, XMM21b, XMM21c, XMM21d, XMM21e, XMM21f, XMM21g, XMM21h);
-reg_class zmm21_reg(XMM21, XMM21b, XMM21c, XMM21d, XMM21e, XMM21f, XMM21g, XMM21h, XMM21i, XMM21j, XMM21k, XMM21l, XMM21m, XMM21n, XMM21o, XMM21p);
-
-reg_class xmm22_reg(XMM22, XMM22b, XMM22c, XMM22d);
-reg_class ymm22_reg(XMM22, XMM22b, XMM22c, XMM22d, XMM22e, XMM22f, XMM22g, XMM22h);
-reg_class zmm22_reg(XMM22, XMM22b, XMM22c, XMM22d, XMM22e, XMM22f, XMM22g, XMM22h, XMM22i, XMM22j, XMM22k, XMM22l, XMM22m, XMM22n, XMM22o, XMM22p);
-
-reg_class xmm23_reg(XMM23, XMM23b, XMM23c, XMM23d);
-reg_class ymm23_reg(XMM23, XMM23b, XMM23c, XMM23d, XMM23e, XMM23f, XMM23g, XMM23h);
-reg_class zmm23_reg(XMM23, XMM23b, XMM23c, XMM23d, XMM23e, XMM23f, XMM23g, XMM23h, XMM23i, XMM23j, XMM23k, XMM23l, XMM23m, XMM23n, XMM23o, XMM23p);
-
-reg_class xmm24_reg(XMM24, XMM24b, XMM24c, XMM24d);
-reg_class ymm24_reg(XMM24, XMM24b, XMM24c, XMM24d, XMM24e, XMM24f, XMM24g, XMM24h);
-reg_class zmm24_reg(XMM24, XMM24b, XMM24c, XMM24d, XMM24e, XMM24f, XMM24g, XMM24h, XMM24i, XMM24j, XMM24k, XMM24l, XMM24m, XMM24n, XMM24o, XMM24p);
-
-reg_class xmm25_reg(XMM25, XMM25b, XMM25c, XMM25d);
-reg_class ymm25_reg(XMM25, XMM25b, XMM25c, XMM25d, XMM25e, XMM25f, XMM25g, XMM25h);
-reg_class zmm25_reg(XMM25, XMM25b, XMM25c, XMM25d, XMM25e, XMM25f, XMM25g, XMM25h, XMM25i, XMM25j, XMM25k, XMM25l, XMM25m, XMM25n, XMM25o, XMM25p);
-
-reg_class xmm26_reg(XMM26, XMM26b, XMM26c, XMM26d);
-reg_class ymm26_reg(XMM26, XMM26b, XMM26c, XMM26d, XMM26e, XMM26f, XMM26g, XMM26h);
-reg_class zmm26_reg(XMM26, XMM26b, XMM26c, XMM26d, XMM26e, XMM26f, XMM26g, XMM26h, XMM26i, XMM26j, XMM26k, XMM26l, XMM26m, XMM26n, XMM26o, XMM26p);
-
-reg_class xmm27_reg(XMM27, XMM27b, XMM27c, XMM27d);
-reg_class ymm27_reg(XMM27, XMM27b, XMM27c, XMM27d, XMM27e, XMM27f, XMM27g, XMM27h);
-reg_class zmm27_reg(XMM27, XMM27b, XMM27c, XMM27d, XMM27e, XMM27f, XMM27g, XMM27h, XMM27i, XMM27j, XMM27k, XMM27l, XMM27m, XMM27n, XMM27o, XMM27p);
-
-reg_class xmm28_reg(XMM28, XMM28b, XMM28c, XMM28d);
-reg_class ymm28_reg(XMM28, XMM28b, XMM28c, XMM28d, XMM28e, XMM28f, XMM28g, XMM28h);
-reg_class zmm28_reg(XMM28, XMM28b, XMM28c, XMM28d, XMM28e, XMM28f, XMM28g, XMM28h, XMM28i, XMM28j, XMM28k, XMM28l, XMM28m, XMM28n, XMM28o, XMM28p);
-
-reg_class xmm29_reg(XMM29, XMM29b, XMM29c, XMM29d);
-reg_class ymm29_reg(XMM29, XMM29b, XMM29c, XMM29d, XMM29e, XMM29f, XMM29g, XMM29h);
-reg_class zmm29_reg(XMM29, XMM29b, XMM29c, XMM29d, XMM29e, XMM29f, XMM29g, XMM29h, XMM29i, XMM29j, XMM29k, XMM29l, XMM29m, XMM29n, XMM29o, XMM29p);
-
-reg_class xmm30_reg(XMM30, XMM30b, XMM30c, XMM30d);
-reg_class ymm30_reg(XMM30, XMM30b, XMM30c, XMM30d, XMM30e, XMM30f, XMM30g, XMM30h);
-reg_class zmm30_reg(XMM30, XMM30b, XMM30c, XMM30d, XMM30e, XMM30f, XMM30g, XMM30h, XMM30i, XMM30j, XMM30k, XMM30l, XMM30m, XMM30n, XMM30o, XMM30p);
-
-reg_class xmm31_reg(XMM31, XMM31b, XMM31c, XMM31d);
-reg_class ymm31_reg(XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h);
-reg_class zmm31_reg(XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h, XMM31i, XMM31j, XMM31k, XMM31l, XMM31m, XMM31n, XMM31o, XMM31p);
-
-#endif
-
%}
@@ -1800,8 +1668,8 @@
return (UseAVX > 2) ? 6 : 4;
}
-static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
- int stack_offset, int reg, uint ireg, outputStream* st) {
+int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
+ int stack_offset, int reg, uint ireg, outputStream* st) {
// In 64-bit VM size calculation is very complex. Emitting instructions
// into scratch buffer is used to get size in 64-bit VM.
LP64_ONLY( assert(!do_size, "this method calculates size only for 32-bit VM"); )
--- a/src/hotspot/cpu/x86/x86_64.ad Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/cpu/x86/x86_64.ad Wed Oct 09 23:22:56 2019 +0200
@@ -1058,8 +1058,8 @@
static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
int src_hi, int dst_hi, uint ireg, outputStream* st);
-static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
- int stack_offset, int reg, uint ireg, outputStream* st);
+int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
+ int stack_offset, int reg, uint ireg, outputStream* st);
static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset,
int dst_offset, uint ireg, outputStream* st) {
@@ -4260,200 +4260,6 @@
%}
%}
-// Operands for bound floating pointer register arguments
-operand rxmm0() %{
- constraint(ALLOC_IN_RC(xmm0_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm1() %{
- constraint(ALLOC_IN_RC(xmm1_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm2() %{
- constraint(ALLOC_IN_RC(xmm2_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm3() %{
- constraint(ALLOC_IN_RC(xmm3_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm4() %{
- constraint(ALLOC_IN_RC(xmm4_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm5() %{
- constraint(ALLOC_IN_RC(xmm5_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm6() %{
- constraint(ALLOC_IN_RC(xmm6_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm7() %{
- constraint(ALLOC_IN_RC(xmm7_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm8() %{
- constraint(ALLOC_IN_RC(xmm8_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm9() %{
- constraint(ALLOC_IN_RC(xmm9_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm10() %{
- constraint(ALLOC_IN_RC(xmm10_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm11() %{
- constraint(ALLOC_IN_RC(xmm11_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm12() %{
- constraint(ALLOC_IN_RC(xmm12_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm13() %{
- constraint(ALLOC_IN_RC(xmm13_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm14() %{
- constraint(ALLOC_IN_RC(xmm14_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm15() %{
- constraint(ALLOC_IN_RC(xmm15_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm16() %{
- constraint(ALLOC_IN_RC(xmm16_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm17() %{
- constraint(ALLOC_IN_RC(xmm17_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm18() %{
- constraint(ALLOC_IN_RC(xmm18_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm19() %{
- constraint(ALLOC_IN_RC(xmm19_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm20() %{
- constraint(ALLOC_IN_RC(xmm20_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm21() %{
- constraint(ALLOC_IN_RC(xmm21_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm22() %{
- constraint(ALLOC_IN_RC(xmm22_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm23() %{
- constraint(ALLOC_IN_RC(xmm23_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm24() %{
- constraint(ALLOC_IN_RC(xmm24_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm25() %{
- constraint(ALLOC_IN_RC(xmm25_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm26() %{
- constraint(ALLOC_IN_RC(xmm26_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm27() %{
- constraint(ALLOC_IN_RC(xmm27_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm28() %{
- constraint(ALLOC_IN_RC(xmm28_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm29() %{
- constraint(ALLOC_IN_RC(xmm29_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm30() %{
- constraint(ALLOC_IN_RC(xmm30_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-operand rxmm31() %{
- constraint(ALLOC_IN_RC(xmm31_reg));
- match(VecX);
- format%{%}
- interface(REG_INTER);
-%}
-
//----------OPERAND CLASSES----------------------------------------------------
// Operand Classes are groups of operands that are used as to simplify
// instruction definitions by not requiring the AD writer to specify separate
@@ -5346,6 +5152,7 @@
instruct loadP(rRegP dst, memory mem)
%{
match(Set dst (LoadP mem));
+ predicate(n->as_Load()->barrier_data() == 0);
ins_cost(125); // XXX
format %{ "movq $dst, $mem\t# ptr" %}
@@ -7794,6 +7601,7 @@
rax_RegP oldval, rRegP newval,
rFlagsReg cr)
%{
+ predicate(n->as_LoadStore()->barrier_data() == 0);
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
@@ -7845,7 +7653,7 @@
rax_RegP oldval, rRegP newval,
rFlagsReg cr)
%{
- predicate(VM_Version::supports_cx8());
+ predicate(VM_Version::supports_cx8() && n->as_LoadStore()->barrier_data() == 0);
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
effect(KILL cr, KILL oldval);
@@ -8087,7 +7895,7 @@
rax_RegP oldval, rRegP newval,
rFlagsReg cr)
%{
- predicate(VM_Version::supports_cx8());
+ predicate(VM_Version::supports_cx8() && n->as_LoadStore()->barrier_data() == 0);
match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
effect(KILL cr);
@@ -8232,6 +8040,7 @@
instruct xchgP( memory mem, rRegP newval) %{
match(Set newval (GetAndSetP mem newval));
+ predicate(n->as_LoadStore()->barrier_data() == 0);
format %{ "XCHGQ $newval,[$mem]" %}
ins_encode %{
__ xchgq($newval$$Register, $mem$$Address);
@@ -11974,6 +11783,7 @@
instruct compP_rReg_mem(rFlagsRegU cr, rRegP op1, memory op2)
%{
match(Set cr (CmpP op1 (LoadP op2)));
+ predicate(n->in(2)->as_Load()->barrier_data() == 0);
ins_cost(500); // XXX
format %{ "cmpq $op1, $op2\t# ptr" %}
@@ -11999,7 +11809,8 @@
// and raw pointers have no anti-dependencies.
instruct compP_mem_rReg(rFlagsRegU cr, rRegP op1, memory op2)
%{
- predicate(n->in(2)->in(2)->bottom_type()->reloc() == relocInfo::none);
+ predicate(n->in(2)->in(2)->bottom_type()->reloc() == relocInfo::none &&
+ n->in(2)->as_Load()->barrier_data() == 0);
match(Set cr (CmpP op1 (LoadP op2)));
format %{ "cmpq $op1, $op2\t# raw ptr" %}
@@ -12024,7 +11835,8 @@
// any compare to a zero should be eq/neq.
instruct testP_mem(rFlagsReg cr, memory op, immP0 zero)
%{
- predicate(!UseCompressedOops || (CompressedOops::base() != NULL));
+ predicate((!UseCompressedOops || (CompressedOops::base() != NULL)) &&
+ n->in(1)->as_Load()->barrier_data() == 0);
match(Set cr (CmpP (LoadP op) zero));
ins_cost(500); // XXX
@@ -12037,7 +11849,9 @@
instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero)
%{
- predicate(UseCompressedOops && (CompressedOops::base() == NULL) && (CompressedKlassPointers::base() == NULL));
+ predicate(UseCompressedOops && (CompressedOops::base() == NULL) &&
+ (CompressedKlassPointers::base() == NULL) &&
+ n->in(1)->as_Load()->barrier_data() == 0);
match(Set cr (CmpP (LoadP mem) zero));
format %{ "cmpq R12, $mem\t# ptr (R12_heapbase==0)" %}
--- a/src/hotspot/share/adlc/formssel.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/adlc/formssel.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -773,11 +773,6 @@
!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
-#if INCLUDE_ZGC
- !strcmp(_matrule->_rChild->_opType,"ZGetAndSetP") ||
- !strcmp(_matrule->_rChild->_opType,"ZCompareAndExchangeP") ||
- !strcmp(_matrule->_rChild->_opType,"LoadBarrierSlowReg") ||
-#endif
#if INCLUDE_SHENANDOAHGC
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
@@ -3510,9 +3505,6 @@
"StoreCM",
"GetAndSetB", "GetAndSetS", "GetAndAddI", "GetAndSetI", "GetAndSetP",
"GetAndAddB", "GetAndAddS", "GetAndAddL", "GetAndSetL", "GetAndSetN",
-#if INCLUDE_ZGC
- "ZGetAndSetP", "ZCompareAndSwapP", "ZCompareAndExchangeP", "ZWeakCompareAndSwapP",
-#endif
"ClearArray"
};
int cnt = sizeof(needs_ideal_memory_list)/sizeof(char*);
--- a/src/hotspot/share/ci/ciEnv.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/ci/ciEnv.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -238,6 +238,7 @@
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
_jvmti_can_pop_frame = JvmtiExport::can_pop_frame();
+ _jvmti_can_get_owned_monitor_info = JvmtiExport::can_get_owned_monitor_info();
}
bool ciEnv::jvmti_state_changed() const {
@@ -262,6 +263,10 @@
JvmtiExport::can_pop_frame()) {
return true;
}
+ if (!_jvmti_can_get_owned_monitor_info &&
+ JvmtiExport::can_get_owned_monitor_info()) {
+ return true;
+ }
return false;
}
--- a/src/hotspot/share/ci/ciEnv.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/ci/ciEnv.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -73,6 +73,7 @@
bool _jvmti_can_access_local_variables;
bool _jvmti_can_post_on_exceptions;
bool _jvmti_can_pop_frame;
+ bool _jvmti_can_get_owned_monitor_info; // includes can_get_owned_monitor_stack_depth_info
// Cache DTrace flags
bool _dtrace_extended_probes;
@@ -347,6 +348,7 @@
}
bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; }
bool jvmti_can_post_on_exceptions() const { return _jvmti_can_post_on_exceptions; }
+ bool jvmti_can_get_owned_monitor_info() const { return _jvmti_can_get_owned_monitor_info; }
// Cache DTrace flags
void cache_dtrace_flags();
--- a/src/hotspot/share/classfile/systemDictionary.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1205,10 +1205,8 @@
TempNewSymbol pkg_name = NULL;
PackageEntry* pkg_entry = NULL;
ModuleEntry* mod_entry = NULL;
- const char* pkg_string = NULL;
pkg_name = InstanceKlass::package_from_name(class_name, CHECK_false);
if (pkg_name != NULL) {
- pkg_string = pkg_name->as_C_string();
if (loader_data != NULL) {
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
}
@@ -1245,7 +1243,7 @@
// 3. or, the class is from an unamed module
if (!ent->is_modules_image() && ik->is_shared_boot_class()) {
// the class is from the -Xbootclasspath/a
- if (pkg_string == NULL ||
+ if (pkg_name == NULL ||
pkg_entry == NULL ||
pkg_entry->in_unnamed_module()) {
assert(mod_entry == NULL ||
@@ -1257,8 +1255,7 @@
return false;
} else {
bool res = SystemDictionaryShared::is_shared_class_visible_for_classloader(
- ik, class_loader, pkg_string, pkg_name,
- pkg_entry, mod_entry, CHECK_(false));
+ ik, class_loader, pkg_name, pkg_entry, mod_entry, CHECK_(false));
return res;
}
}
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -657,7 +657,6 @@
bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
InstanceKlass* ik,
Handle class_loader,
- const char* pkg_string,
Symbol* pkg_name,
PackageEntry* pkg_entry,
ModuleEntry* mod_entry,
@@ -684,7 +683,7 @@
}
} else if (SystemDictionary::is_system_class_loader(class_loader())) {
assert(ent != NULL, "shared class for system loader should have valid SharedClassPathEntry");
- if (pkg_string == NULL) {
+ if (pkg_name == NULL) {
// The archived class is in the unnamed package. Currently, the boot image
// does not contain any class in the unnamed package.
assert(!ent->is_modules_image(), "Class in the unnamed package must be from the classpath");
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -240,7 +240,6 @@
static bool is_sharing_possible(ClassLoaderData* loader_data);
static bool is_shared_class_visible_for_classloader(InstanceKlass* ik,
Handle class_loader,
- const char* pkg_string,
Symbol* pkg_name,
PackageEntry* pkg_entry,
ModuleEntry* mod_entry,
--- a/src/hotspot/share/code/compiledIC.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/code/compiledIC.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -741,4 +741,22 @@
tty->cr();
}
+void CompiledDirectStaticCall::verify_mt_safe(const methodHandle& callee, address entry,
+ NativeMovConstReg* method_holder,
+ NativeJump* jump) {
+ // A generated lambda form might be deleted from the Lambdaform
+ // cache in MethodTypeForm. If a jit compiled lambdaform method
+ // becomes not entrant and the cache access returns null, the new
+ // resolve will lead to a new generated LambdaForm.
+ Method* old_method = reinterpret_cast<Method*>(method_holder->data());
+ assert(old_method == NULL || old_method == callee() ||
+ callee->is_compiled_lambda_form() ||
+ !old_method->method_holder()->is_loader_alive() ||
+ old_method->is_old(), // may be race patching deoptimized nmethod due to redefinition.
+ "a) MT-unsafe modification of inline cache");
+
+ address destination = jump->jump_destination();
+ assert(destination == (address)-1 || destination == entry,
+ "b) MT-unsafe modification of inline cache");
+}
#endif // !PRODUCT
--- a/src/hotspot/share/code/compiledIC.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/code/compiledIC.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -402,6 +402,9 @@
// Also used by CompiledIC
void set_to_interpreted(const methodHandle& callee, address entry);
+ void verify_mt_safe(const methodHandle& callee, address entry,
+ NativeMovConstReg* method_holder,
+ NativeJump* jump) PRODUCT_RETURN;
#if INCLUDE_AOT
void set_to_far(const methodHandle& callee, address entry);
#endif
--- a/src/hotspot/share/compiler/compilerDirectives.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/compiler/compilerDirectives.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -66,8 +66,7 @@
cflags(VectorizeDebug, uintx, 0, VectorizeDebug) \
cflags(CloneMapDebug, bool, false, CloneMapDebug) \
cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel) \
- cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit) \
-ZGC_ONLY(cflags(ZTraceLoadBarriers, bool, false, ZTraceLoadBarriers))
+ cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit)
#else
#define compilerdirectives_c2_flags(cflags)
#endif
--- a/src/hotspot/share/gc/g1/g1Analytics.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1Analytics.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -78,6 +78,8 @@
_alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_prev_collection_pause_end_ms(0.0),
_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
+ _concurrent_refine_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+ _logged_cards_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_logged_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_scan_hcc_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
@@ -102,6 +104,10 @@
int index = MIN2(ParallelGCThreads - 1, 7u);
_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
+ // Start with inverse of maximum STW cost.
+ _concurrent_refine_rate_ms_seq->add(1/cost_per_logged_card_ms_defaults[0]);
+ // Some applications have very low rates for logging cards.
+ _logged_cards_rate_ms_seq->add(0.0);
_cost_per_logged_card_ms_seq->add(cost_per_logged_card_ms_defaults[index]);
_cost_scan_hcc_seq->add(0.0);
_young_cards_per_entry_ratio_seq->add(young_cards_per_entry_ratio_defaults[index]);
@@ -159,6 +165,14 @@
(pause_time_ms * _recent_prev_end_times_for_all_gcs_sec->num()) / interval_ms;
}
+void G1Analytics::report_concurrent_refine_rate_ms(double cards_per_ms) {
+ _concurrent_refine_rate_ms_seq->add(cards_per_ms);
+}
+
+void G1Analytics::report_logged_cards_rate_ms(double cards_per_ms) {
+ _logged_cards_rate_ms_seq->add(cards_per_ms);
+}
+
void G1Analytics::report_cost_per_logged_card_ms(double cost_per_logged_card_ms) {
_cost_per_logged_card_ms_seq->add(cost_per_logged_card_ms);
}
@@ -223,6 +237,14 @@
return get_new_prediction(_alloc_rate_ms_seq);
}
+double G1Analytics::predict_concurrent_refine_rate_ms() const {
+ return get_new_prediction(_concurrent_refine_rate_ms_seq);
+}
+
+double G1Analytics::predict_logged_cards_rate_ms() const {
+ return get_new_prediction(_logged_cards_rate_ms_seq);
+}
+
double G1Analytics::predict_cost_per_logged_card_ms() const {
return get_new_prediction(_cost_per_logged_card_ms_seq);
}
--- a/src/hotspot/share/gc/g1/g1Analytics.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1Analytics.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -46,6 +46,8 @@
double _prev_collection_pause_end_ms;
TruncatedSeq* _rs_length_diff_seq;
+ TruncatedSeq* _concurrent_refine_rate_ms_seq;
+ TruncatedSeq* _logged_cards_rate_ms_seq;
TruncatedSeq* _cost_per_logged_card_ms_seq;
TruncatedSeq* _cost_scan_hcc_seq;
TruncatedSeq* _young_cards_per_entry_ratio_seq;
@@ -99,6 +101,8 @@
void report_concurrent_mark_remark_times_ms(double ms);
void report_concurrent_mark_cleanup_times_ms(double ms);
void report_alloc_rate_ms(double alloc_rate);
+ void report_concurrent_refine_rate_ms(double cards_per_ms);
+ void report_logged_cards_rate_ms(double cards_per_ms);
void report_cost_per_logged_card_ms(double cost_per_logged_card_ms);
void report_cost_scan_hcc(double cost_scan_hcc);
void report_cost_per_remset_card_ms(double cost_per_remset_card_ms, bool for_young_gc);
@@ -116,6 +120,8 @@
double predict_alloc_rate_ms() const;
int num_alloc_rate_ms() const;
+ double predict_concurrent_refine_rate_ms() const;
+ double predict_logged_cards_rate_ms() const;
double predict_cost_per_logged_card_ms() const;
double predict_scan_hcc_ms() const;
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -409,7 +409,7 @@
guarantee(target_pause_time_ms > 0.0,
"target_pause_time_ms = %1.6lf should be positive", target_pause_time_ms);
- size_t pending_cards = _policy->pending_cards();
+ size_t pending_cards = _policy->pending_cards_at_gc_start();
double base_time_ms = _policy->predict_base_elapsed_time_ms(pending_cards);
double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -412,6 +412,22 @@
dcqs.notify_if_necessary();
}
+G1ConcurrentRefine::RefinementStats G1ConcurrentRefine::total_refinement_stats() const {
+ struct CollectData : public ThreadClosure {
+ Tickspan _total_time;
+ size_t _total_cards;
+ CollectData() : _total_time(), _total_cards(0) {}
+ virtual void do_thread(Thread* t) {
+ G1ConcurrentRefineThread* crt = static_cast<G1ConcurrentRefineThread*>(t);
+ _total_time += crt->total_refinement_time();
+ _total_cards += crt->total_refined_cards();
+ }
+ } collector;
+ // Cast away const so we can call non-modifying closure on threads.
+ const_cast<G1ConcurrentRefine*>(this)->threads_do(&collector);
+ return RefinementStats(collector._total_time, collector._total_cards);
+}
+
size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
return activation_level(thresholds);
@@ -432,7 +448,8 @@
}
}
-bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
+bool G1ConcurrentRefine::do_refinement_step(uint worker_id,
+ size_t* total_refined_cards) {
G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
size_t curr_cards = dcqs.num_cards();
@@ -448,5 +465,6 @@
// Process the next buffer, if there are enough left.
return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(),
- deactivation_threshold(worker_id));
+ deactivation_threshold(worker_id),
+ total_refined_cards);
}
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -27,6 +27,7 @@
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
+#include "utilities/ticks.hpp"
// Forward decl
class G1ConcurrentRefine;
@@ -118,11 +119,22 @@
// Adjust refinement thresholds based on work done during the pause and the goal time.
void adjust(double logged_cards_scan_time, size_t processed_logged_cards, double goal_ms);
+ struct RefinementStats {
+ Tickspan _time;
+ size_t _cards;
+ RefinementStats(Tickspan time, size_t cards) : _time(time), _cards(cards) {}
+ };
+
+ RefinementStats total_refinement_stats() const;
+
// Cards in the dirty card queue set.
size_t activation_threshold(uint worker_id) const;
size_t deactivation_threshold(uint worker_id) const;
- // Perform a single refinement step. Called by the refinement threads when woken up.
- bool do_refinement_step(uint worker_id);
+
+ // Perform a single refinement step; called by the refinement
+ // threads. Returns true if there was refinement work available.
+ // Increments *total_refined_cards.
+ bool do_refinement_step(uint worker_id, size_t* total_refined_cards);
// Iterate over all concurrent refinement threads applying the given closure.
void threads_do(ThreadClosure *tc);
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -37,6 +37,8 @@
ConcurrentGCThread(),
_vtime_start(0.0),
_vtime_accum(0.0),
+ _total_refinement_time(),
+ _total_refined_cards(0),
_worker_id(worker_id),
_active(false),
_monitor(NULL),
@@ -101,11 +103,12 @@
break;
}
- size_t buffers_processed = 0;
log_debug(gc, refine)("Activated worker %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
_worker_id, _cr->activation_threshold(_worker_id),
G1BarrierSet::dirty_card_queue_set().num_cards());
+ size_t start_total_refined_cards = _total_refined_cards; // For logging.
+
{
SuspendibleThreadSetJoiner sts_join;
@@ -115,20 +118,22 @@
continue; // Re-check for termination after yield delay.
}
- if (!_cr->do_refinement_step(_worker_id)) {
- break;
+ Ticks start_time = Ticks::now();
+ if (!_cr->do_refinement_step(_worker_id, &_total_refined_cards)) {
+ break; // No cards to process.
}
- ++buffers_processed;
+ _total_refinement_time += (Ticks::now() - start_time);
}
}
deactivate();
log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT
- ", current: " SIZE_FORMAT ", buffers processed: "
- SIZE_FORMAT,
+ ", current: " SIZE_FORMAT ", refined cards: "
+ SIZE_FORMAT ", total refined cards: " SIZE_FORMAT,
_worker_id, _cr->deactivation_threshold(_worker_id),
G1BarrierSet::dirty_card_queue_set().num_cards(),
- buffers_processed);
+ _total_refined_cards - start_total_refined_cards,
+ _total_refined_cards);
if (os::supports_vtime()) {
_vtime_accum = (os::elapsedVTime() - _vtime_start);
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -26,6 +26,7 @@
#define SHARE_GC_G1_G1CONCURRENTREFINETHREAD_HPP
#include "gc/shared/concurrentGCThread.hpp"
+#include "utilities/ticks.hpp"
// Forward Decl.
class G1ConcurrentRefine;
@@ -38,6 +39,10 @@
double _vtime_start; // Initial virtual time.
double _vtime_accum; // Accumulated virtual time.
+
+ Tickspan _total_refinement_time;
+ size_t _total_refined_cards;
+
uint _worker_id;
bool _active;
@@ -61,6 +66,9 @@
// Activate this thread.
void activate();
+ Tickspan total_refinement_time() const { return _total_refinement_time; }
+ size_t total_refined_cards() const { return _total_refined_cards; }
+
// Total virtual time so far.
double vtime_accum() { return _vtime_accum; }
};
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -37,6 +37,7 @@
#include "runtime/atomic.hpp"
#include "runtime/flags/flagSetting.hpp"
#include "runtime/mutexLocker.hpp"
+#include "runtime/os.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadSMR.hpp"
@@ -62,6 +63,9 @@
}
}
+// Assumed to be zero by concurrent threads.
+static uint par_ids_start() { return 0; }
+
G1DirtyCardQueueSet::G1DirtyCardQueueSet(Monitor* cbl_mon,
BufferNode::Allocator* allocator) :
PtrQueueSet(allocator),
@@ -73,15 +77,16 @@
_process_completed_buffers(false),
_max_cards(MaxCardsUnlimited),
_max_cards_padding(0),
- _free_ids(0, num_par_ids()),
- _processed_buffers_mut(0),
- _processed_buffers_rs_thread(0)
+ _free_ids(par_ids_start(), num_par_ids()),
+ _mutator_refined_cards_counters(NEW_C_HEAP_ARRAY(size_t, num_par_ids(), mtGC))
{
+ ::memset(_mutator_refined_cards_counters, 0, num_par_ids() * sizeof(size_t));
_all_active = true;
}
G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
abandon_completed_buffers();
+ FREE_C_HEAP_ARRAY(size_t, _mutator_refined_cards_counters);
}
// Determines how many mutator threads can process the buffers in parallel.
@@ -89,6 +94,14 @@
return (uint)os::initial_active_processor_count();
}
+size_t G1DirtyCardQueueSet::total_mutator_refined_cards() const {
+ size_t sum = 0;
+ for (uint i = 0; i < num_par_ids(); ++i) {
+ sum += _mutator_refined_cards_counters[i];
+ }
+ return sum;
+}
+
void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
}
@@ -213,7 +226,9 @@
return result;
}
-bool G1DirtyCardQueueSet::refine_buffer(BufferNode* node, uint worker_id) {
+bool G1DirtyCardQueueSet::refine_buffer(BufferNode* node,
+ uint worker_id,
+ size_t* total_refined_cards) {
G1RemSet* rem_set = G1CollectedHeap::heap()->rem_set();
size_t size = buffer_size();
void** buffer = BufferNode::make_buffer_from_node(node);
@@ -223,6 +238,7 @@
CardTable::CardValue* cp = static_cast<CardTable::CardValue*>(buffer[i]);
rem_set->refine_card_concurrently(cp, worker_id);
}
+ *total_refined_cards += (i - node->index());
node->set_index(i);
return i == size;
}
@@ -260,25 +276,27 @@
bool G1DirtyCardQueueSet::mut_process_buffer(BufferNode* node) {
uint worker_id = _free_ids.claim_par_id(); // temporarily claim an id
- bool result = refine_buffer(node, worker_id);
+ uint counter_index = worker_id - par_ids_start();
+ size_t* counter = &_mutator_refined_cards_counters[counter_index];
+ bool result = refine_buffer(node, worker_id, counter);
_free_ids.release_par_id(worker_id); // release the id
if (result) {
assert_fully_consumed(node, buffer_size());
- Atomic::inc(&_processed_buffers_mut);
}
return result;
}
-bool G1DirtyCardQueueSet::refine_completed_buffer_concurrently(uint worker_id, size_t stop_at) {
+bool G1DirtyCardQueueSet::refine_completed_buffer_concurrently(uint worker_id,
+ size_t stop_at,
+ size_t* total_refined_cards) {
BufferNode* node = get_completed_buffer(stop_at);
if (node == NULL) {
return false;
- } else if (refine_buffer(node, worker_id)) {
+ } else if (refine_buffer(node, worker_id, total_refined_cards)) {
assert_fully_consumed(node, buffer_size());
// Done with fully processed buffer.
deallocate_buffer(node);
- Atomic::inc(&_processed_buffers_rs_thread);
return true;
} else {
// Return partially processed buffer to the queue.
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -78,14 +78,15 @@
void abandon_completed_buffers();
- // Refine the cards in "node" from it's index to buffer_size.
+ // Refine the cards in "node" from its index to buffer_size.
// Stops processing if SuspendibleThreadSet::should_yield() is true.
// Returns true if the entire buffer was processed, false if there
// is a pending yield request. The node's index is updated to exclude
// the processed elements, e.g. up to the element before processing
// stopped, or one past the last element if the entire buffer was
- // processed.
- bool refine_buffer(BufferNode* node, uint worker_id);
+ // processed. Increments *total_refined_cards by the number of cards
+ // processed and removed from the buffer.
+ bool refine_buffer(BufferNode* node, uint worker_id, size_t* total_refined_cards);
bool mut_process_buffer(BufferNode* node);
@@ -97,10 +98,9 @@
G1FreeIdSet _free_ids;
- // The number of completed buffers processed by mutator and rs thread,
- // respectively.
- jint _processed_buffers_mut;
- jint _processed_buffers_rs_thread;
+ // Array of cumulative dirty cards refined by mutator threads.
+ // Array has an entry per id in _free_ids.
+ size_t* _mutator_refined_cards_counters;
public:
G1DirtyCardQueueSet(Monitor* cbl_mon, BufferNode::Allocator* allocator);
@@ -158,7 +158,12 @@
// Stops processing a buffer if SuspendibleThreadSet::should_yield(),
// returning the incompletely processed buffer to the completed buffer
// list, for later processing of the remainder.
- bool refine_completed_buffer_concurrently(uint worker_id, size_t stop_at);
+ //
+ // Increments *total_refined_cards by the number of cards processed and
+ // removed from the buffer.
+ bool refine_completed_buffer_concurrently(uint worker_id,
+ size_t stop_at,
+ size_t* total_refined_cards);
// If a full collection is happening, reset partial logs, and release
// completed ones: the full collection will make them all irrelevant.
@@ -181,13 +186,8 @@
return _max_cards_padding;
}
- jint processed_buffers_mut() {
- return _processed_buffers_mut;
- }
- jint processed_buffers_rs_thread() {
- return _processed_buffers_rs_thread;
- }
-
+ // Total dirty cards refined by mutator threads.
+ size_t total_mutator_refined_cards() const;
};
inline G1DirtyCardQueueSet* G1DirtyCardQueue::dirty_card_qset() const {
--- a/src/hotspot/share/gc/g1/g1Policy.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -70,7 +70,11 @@
_free_regions_at_end_of_collection(0),
_max_rs_length(0),
_rs_length_prediction(0),
- _pending_cards(0),
+ _pending_cards_at_gc_start(0),
+ _pending_cards_at_prev_gc_end(0),
+ _total_mutator_refined_cards(0),
+ _total_concurrent_refined_cards(0),
+ _total_concurrent_refinement_time(),
_bytes_allocated_in_old_since_last_gc(0),
_initial_mark_to_mixed(),
_collection_set(NULL),
@@ -442,6 +446,7 @@
collector_state()->set_in_young_only_phase(false);
collector_state()->set_in_full_gc(true);
_collection_set->clear_candidates();
+ record_concurrent_refinement_data(true /* is_full_collection */);
}
void G1Policy::record_full_collection_end() {
@@ -472,12 +477,67 @@
_survivor_surv_rate_group->reset();
update_young_list_max_and_target_length();
update_rs_length_prediction();
+ _pending_cards_at_prev_gc_end = _g1h->pending_card_num();
_bytes_allocated_in_old_since_last_gc = 0;
record_pause(FullGC, _full_collection_start_sec, end_sec);
}
+void G1Policy::record_concurrent_refinement_data(bool is_full_collection) {
+ _pending_cards_at_gc_start = _g1h->pending_card_num();
+
+ // Record info about concurrent refinement thread processing.
+ G1ConcurrentRefine* cr = _g1h->concurrent_refine();
+ G1ConcurrentRefine::RefinementStats cr_stats = cr->total_refinement_stats();
+
+ Tickspan cr_time = cr_stats._time - _total_concurrent_refinement_time;
+ _total_concurrent_refinement_time = cr_stats._time;
+
+ size_t cr_cards = cr_stats._cards - _total_concurrent_refined_cards;
+ _total_concurrent_refined_cards = cr_stats._cards;
+
+ // Don't update rate if full collection. We could be in an implicit full
+ // collection after a non-full collection failure, in which case there
+ // wasn't any mutator/cr-thread activity since last recording. And if
+ // we're in an explicit full collection, the time since the last GC can
+ // be arbitrarily short, so not a very good sample. Similarly, don't
+ // update the rate if the current sample is empty or time is zero.
+ if (!is_full_collection && (cr_cards > 0) && (cr_time > Tickspan())) {
+ double rate = cr_cards / (cr_time.seconds() * MILLIUNITS);
+ _analytics->report_concurrent_refine_rate_ms(rate);
+ }
+
+ // Record info about mutator thread processing.
+ G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
+ size_t mut_total_cards = dcqs.total_mutator_refined_cards();
+ size_t mut_cards = mut_total_cards - _total_mutator_refined_cards;
+ _total_mutator_refined_cards = mut_total_cards;
+
+ // Record mutator's card logging rate.
+ // Don't update if full collection; see above.
+ if (!is_full_collection) {
+ size_t total_cards = _pending_cards_at_gc_start + cr_cards + mut_cards;
+ assert(_pending_cards_at_prev_gc_end <= total_cards,
+ "untracked cards: last pending: " SIZE_FORMAT
+ ", pending: " SIZE_FORMAT ", conc refine: " SIZE_FORMAT
+ ", mut refine:" SIZE_FORMAT,
+ _pending_cards_at_prev_gc_end, _pending_cards_at_gc_start,
+ cr_cards, mut_cards);
+ size_t logged_cards = total_cards - _pending_cards_at_prev_gc_end;
+ double logging_start_time = _analytics->prev_collection_pause_end_ms();
+ double logging_end_time = Ticks::now().seconds() * MILLIUNITS;
+ double logging_time = logging_end_time - logging_start_time;
+ // Unlike above for conc-refine rate, here we should not require a
+ // non-empty sample, since an application could go some time with only
+ // young-gen or filtered out writes. But we'll ignore unusually short
+ // sample periods, as they may just pollute the predictions.
+ if (logging_time > 1.0) { // Require > 1ms sample time.
+ _analytics->report_logged_cards_rate_ms(logged_cards / logging_time);
+ }
+ }
+}
+
void G1Policy::record_collection_pause_start(double start_time_sec) {
// We only need to do this here as the policy will only be applied
// to the GC we're about to start. so, no point is calculating this
@@ -490,7 +550,8 @@
assert_used_and_recalculate_used_equal(_g1h);
phase_times()->record_cur_collection_start_sec(start_time_sec);
- _pending_cards = _g1h->pending_card_num();
+
+ record_concurrent_refinement_data(false /* is_full_collection */);
_collection_set->reset_bytes_used_before();
_bytes_copied_during_gc = 0;
@@ -744,7 +805,7 @@
// after the mixed gc phase.
// During mixed gc we do not use them for young gen sizing.
if (this_pause_was_young_only) {
- _analytics->report_pending_cards((double) _pending_cards);
+ _analytics->report_pending_cards((double) _pending_cards_at_gc_start);
_analytics->report_rs_length((double) _max_rs_length);
}
}
@@ -798,6 +859,7 @@
scan_logged_cards_time_goal_ms -= scan_hcc_time_ms;
}
+ _pending_cards_at_prev_gc_end = _g1h->pending_card_num();
double const logged_cards_time = logged_cards_processing_time();
log_debug(gc, ergo, refine)("Concurrent refinement times: Logged Cards Scan time goal: %1.2fms Logged Cards Scan time: %1.2fms HCC time: %1.2fms",
--- a/src/hotspot/share/gc/g1/g1Policy.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -100,7 +100,11 @@
size_t _rs_length_prediction;
- size_t _pending_cards;
+ size_t _pending_cards_at_gc_start;
+ size_t _pending_cards_at_prev_gc_end;
+ size_t _total_mutator_refined_cards;
+ size_t _total_concurrent_refined_cards;
+ Tickspan _total_concurrent_refinement_time;
// The amount of allocated bytes in old gen during the last mutator and the following
// young GC phase.
@@ -244,7 +248,15 @@
uint base_free_regions, double target_pause_time_ms) const;
public:
- size_t pending_cards() const { return _pending_cards; }
+ size_t pending_cards_at_gc_start() const { return _pending_cards_at_gc_start; }
+
+ size_t total_concurrent_refined_cards() const {
+ return _total_concurrent_refined_cards;
+ }
+
+ size_t total_mutator_refined_cards() const {
+ return _total_mutator_refined_cards;
+ }
// Calculate the minimum number of old regions we'll add to the CSet
// during a mixed GC.
@@ -283,6 +295,9 @@
void record_pause(PauseKind kind, double start, double end);
// Indicate that we aborted marking before doing any mixed GCs.
void abort_time_to_mixed_tracking();
+
+ void record_concurrent_refinement_data(bool is_full_collection);
+
public:
G1Policy(STWGCTimer* gc_timer);
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -489,7 +489,6 @@
_scan_state(new G1RemSetScanState()),
_prev_period_summary(),
_g1h(g1h),
- _num_conc_refined_cards(0),
_ct(ct),
_g1p(_g1h->policy()),
_hot_card_cache(hot_card_cache) {
@@ -1377,7 +1376,6 @@
G1ConcurrentRefineOopClosure conc_refine_cl(_g1h, worker_id);
if (r->oops_on_memregion_seq_iterate_careful<false>(dirty_region, &conc_refine_cl) != NULL) {
- _num_conc_refined_cards++; // Unsynchronized update, only used for logging.
return;
}
--- a/src/hotspot/share/gc/g1/g1RemSet.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSet.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -61,7 +61,6 @@
G1RemSetSummary _prev_period_summary;
G1CollectedHeap* _g1h;
- size_t _num_conc_refined_cards; // Number of cards refined concurrently to the mutator.
G1CardTable* _ct;
G1Policy* _g1p;
@@ -125,8 +124,6 @@
// Print accumulated summary info from the last time called.
void print_periodic_summary_info(const char* header, uint period_count);
- size_t num_conc_refined_cards() const { return _num_conc_refined_cards; }
-
// Rebuilds the remembered set by scanning from bottom to TARS for all regions
// using the given work gang.
void rebuild_rem_set(G1ConcurrentMark* cm, WorkGang* workers, uint worker_id_offset);
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -27,6 +27,7 @@
#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1DirtyCardQueue.hpp"
+#include "gc/g1/g1Policy.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RemSetSummary.hpp"
#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
@@ -53,18 +54,17 @@
};
void G1RemSetSummary::update() {
- _num_conc_refined_cards = _rem_set->num_conc_refined_cards();
- G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
- _num_processed_buf_mutator = dcqs.processed_buffers_mut();
- _num_processed_buf_rs_threads = dcqs.processed_buffers_rs_thread();
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+ const G1Policy* policy = g1h->policy();
+ _total_mutator_refined_cards = policy->total_mutator_refined_cards();
+ _total_concurrent_refined_cards = policy->total_concurrent_refined_cards();
_num_coarsenings = HeapRegionRemSet::n_coarsenings();
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- G1ConcurrentRefine* cg1r = g1h->concurrent_refine();
if (_rs_threads_vtimes != NULL) {
GetRSThreadVTimeClosure p(this);
- cg1r->threads_do(&p);
+ g1h->concurrent_refine()->threads_do(&p);
}
set_sampling_thread_vtime(g1h->sampling_thread()->vtime_accum());
}
@@ -83,9 +83,8 @@
G1RemSetSummary::G1RemSetSummary() :
_rem_set(NULL),
- _num_conc_refined_cards(0),
- _num_processed_buf_mutator(0),
- _num_processed_buf_rs_threads(0),
+ _total_mutator_refined_cards(0),
+ _total_concurrent_refined_cards(0),
_num_coarsenings(0),
_num_vtimes(G1ConcurrentRefine::max_num_threads()),
_rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
@@ -96,9 +95,8 @@
G1RemSetSummary::G1RemSetSummary(G1RemSet* rem_set) :
_rem_set(rem_set),
- _num_conc_refined_cards(0),
- _num_processed_buf_mutator(0),
- _num_processed_buf_rs_threads(0),
+ _total_mutator_refined_cards(0),
+ _total_concurrent_refined_cards(0),
_num_coarsenings(0),
_num_vtimes(G1ConcurrentRefine::max_num_threads()),
_rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
@@ -114,12 +112,10 @@
assert(other != NULL, "just checking");
assert(_num_vtimes == other->_num_vtimes, "just checking");
- _num_conc_refined_cards = other->num_conc_refined_cards();
+ _total_mutator_refined_cards = other->total_mutator_refined_cards();
+ _total_concurrent_refined_cards = other->total_concurrent_refined_cards();
- _num_processed_buf_mutator = other->num_processed_buf_mutator();
- _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads();
-
- _num_coarsenings = other->_num_coarsenings;
+ _num_coarsenings = other->num_coarsenings();
memcpy(_rs_threads_vtimes, other->_rs_threads_vtimes, sizeof(double) * _num_vtimes);
@@ -130,10 +126,8 @@
assert(other != NULL, "just checking");
assert(_num_vtimes == other->_num_vtimes, "just checking");
- _num_conc_refined_cards = other->num_conc_refined_cards() - _num_conc_refined_cards;
-
- _num_processed_buf_mutator = other->num_processed_buf_mutator() - _num_processed_buf_mutator;
- _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads() - _num_processed_buf_rs_threads;
+ _total_mutator_refined_cards = other->total_mutator_refined_cards() - _total_mutator_refined_cards;
+ _total_concurrent_refined_cards = other->total_concurrent_refined_cards() - _total_concurrent_refined_cards;
_num_coarsenings = other->num_coarsenings() - _num_coarsenings;
@@ -356,16 +350,15 @@
void G1RemSetSummary::print_on(outputStream* out) {
out->print_cr(" Recent concurrent refinement statistics");
- out->print_cr(" Processed " SIZE_FORMAT " cards concurrently", num_conc_refined_cards());
- out->print_cr(" Of " SIZE_FORMAT " completed buffers:", num_processed_buf_total());
- out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by concurrent RS threads.",
- num_processed_buf_total(),
- percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
+ out->print_cr(" Of " SIZE_FORMAT " refined cards:", total_refined_cards());
+ out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by concurrent refinement threads.",
+ total_concurrent_refined_cards(),
+ percent_of(total_concurrent_refined_cards(), total_refined_cards()));
out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by mutator threads.",
- num_processed_buf_mutator(),
- percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
+ total_mutator_refined_cards(),
+ percent_of(total_mutator_refined_cards(), total_refined_cards()));
out->print_cr(" Did " SIZE_FORMAT " coarsenings.", num_coarsenings());
- out->print_cr(" Concurrent RS threads times (s)");
+ out->print_cr(" Concurrent refinement threads times (s)");
out->print(" ");
for (uint i = 0; i < _num_vtimes; i++) {
out->print(" %5.2f", rs_thread_vtime(i));
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -38,9 +38,8 @@
G1RemSet* _rem_set;
- size_t _num_conc_refined_cards;
- size_t _num_processed_buf_mutator;
- size_t _num_processed_buf_rs_threads;
+ size_t _total_mutator_refined_cards;
+ size_t _total_concurrent_refined_cards;
size_t _num_coarsenings;
@@ -76,20 +75,16 @@
return _sampling_thread_vtime;
}
- size_t num_conc_refined_cards() const {
- return _num_conc_refined_cards;
+ size_t total_mutator_refined_cards() const {
+ return _total_mutator_refined_cards;
}
- size_t num_processed_buf_mutator() const {
- return _num_processed_buf_mutator;
+ size_t total_concurrent_refined_cards() const {
+ return _total_concurrent_refined_cards;
}
- size_t num_processed_buf_rs_threads() const {
- return _num_processed_buf_rs_threads;
- }
-
- size_t num_processed_buf_total() const {
- return num_processed_buf_mutator() + num_processed_buf_rs_threads();
+ size_t total_refined_cards() const {
+ return total_mutator_refined_cards() + total_concurrent_refined_cards();
}
size_t num_coarsenings() const {
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -264,7 +264,7 @@
virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const;
// Support for GC barriers emitted during parsing
- virtual bool has_load_barriers() const { return false; }
+ virtual bool has_load_barrier_nodes() const { return false; }
virtual bool is_gc_barrier_node(Node* node) const { return false; }
virtual Node* step_over_gc_barrier(Node* c) const { return c; }
virtual Node* step_over_gc_barrier_ctrl(Node* c) const { return c; }
@@ -287,13 +287,9 @@
virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return false; }
virtual bool has_special_unique_user(const Node* node) const { return false; }
- virtual bool needs_anti_dependence_check(const Node* node) const { return true; }
-
- virtual void barrier_insertion_phase(Compile* C, PhaseIterGVN &igvn) const { }
enum CompilePhase {
BeforeOptimize,
- BeforeLateInsertion,
BeforeMacroExpand,
BeforeCodeGen
};
@@ -320,6 +316,10 @@
virtual Node* split_if_pre(PhaseIdealLoop* phase, Node* n) const { return NULL; }
virtual bool build_loop_late_post(PhaseIdealLoop* phase, Node* n) const { return false; }
virtual bool sink_node(PhaseIdealLoop* phase, Node* n, Node* x, Node* x_ctrl, Node* n_ctrl) const { return false; }
+
+ virtual void late_barrier_analysis() const { }
+ virtual int estimate_stub_size() const { return 0; }
+ virtual void emit_stubs(CodeBuffer& cb) const { }
};
#endif // SHARE_GC_SHARED_C2_BARRIERSETC2_HPP
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -103,7 +103,7 @@
static const TypeFunc* write_ref_field_pre_entry_Type();
static const TypeFunc* shenandoah_clone_barrier_Type();
static const TypeFunc* shenandoah_load_reference_barrier_Type();
- virtual bool has_load_barriers() const { return true; }
+ virtual bool has_load_barrier_nodes() const { return true; }
// This is the entry-point for the backend to perform accesses through the Access API.
virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const;
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -22,451 +22,157 @@
*/
#include "precompiled.hpp"
-#include "opto/castnode.hpp"
+#include "classfile/javaClasses.hpp"
+#include "gc/z/c2/zBarrierSetC2.hpp"
+#include "gc/z/zBarrierSet.hpp"
+#include "gc/z/zBarrierSetAssembler.hpp"
+#include "gc/z/zBarrierSetRuntime.hpp"
+#include "opto/block.hpp"
#include "opto/compile.hpp"
-#include "opto/escape.hpp"
#include "opto/graphKit.hpp"
-#include "opto/loopnode.hpp"
#include "opto/machnode.hpp"
-#include "opto/macro.hpp"
#include "opto/memnode.hpp"
-#include "opto/movenode.hpp"
#include "opto/node.hpp"
-#include "opto/phase.hpp"
-#include "opto/phaseX.hpp"
+#include "opto/regalloc.hpp"
#include "opto/rootnode.hpp"
-#include "opto/type.hpp"
-#include "utilities/copy.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
-#include "gc/z/zBarrierSet.hpp"
-#include "gc/z/c2/zBarrierSetC2.hpp"
-#include "gc/z/zThreadLocalData.hpp"
-#include "gc/z/zBarrierSetRuntime.hpp"
-ZBarrierSetC2State::ZBarrierSetC2State(Arena* comp_arena) :
- _load_barrier_nodes(new (comp_arena) GrowableArray<LoadBarrierNode*>(comp_arena, 8, 0, NULL)) {}
+class ZBarrierSetC2State : public ResourceObj {
+private:
+ GrowableArray<ZLoadBarrierStubC2*>* _stubs;
+ Node_Array _live;
-int ZBarrierSetC2State::load_barrier_count() const {
- return _load_barrier_nodes->length();
-}
+public:
+ ZBarrierSetC2State(Arena* arena) :
+ _stubs(new (arena) GrowableArray<ZLoadBarrierStubC2*>(arena, 8, 0, NULL)),
+ _live(arena) {}
-void ZBarrierSetC2State::add_load_barrier_node(LoadBarrierNode * n) {
- assert(!_load_barrier_nodes->contains(n), " duplicate entry in expand list");
- _load_barrier_nodes->append(n);
-}
+ GrowableArray<ZLoadBarrierStubC2*>* stubs() {
+ return _stubs;
+ }
-void ZBarrierSetC2State::remove_load_barrier_node(LoadBarrierNode * n) {
- // this function may be called twice for a node so check
- // that the node is in the array before attempting to remove it
- if (_load_barrier_nodes->contains(n)) {
- _load_barrier_nodes->remove(n);
- }
-}
+ RegMask* live(const Node* node) {
+ if (!node->is_Mach()) {
+ // Don't need liveness for non-MachNodes
+ return NULL;
+ }
-LoadBarrierNode* ZBarrierSetC2State::load_barrier_node(int idx) const {
- return _load_barrier_nodes->at(idx);
-}
+ const MachNode* const mach = node->as_Mach();
+ if (mach->barrier_data() != ZLoadBarrierStrong &&
+ mach->barrier_data() != ZLoadBarrierWeak) {
+ // Don't need liveness data for nodes without barriers
+ return NULL;
+ }
-void* ZBarrierSetC2::create_barrier_state(Arena* comp_arena) const {
- return new(comp_arena) ZBarrierSetC2State(comp_arena);
-}
+ RegMask* live = (RegMask*)_live[node->_idx];
+ if (live == NULL) {
+ live = new (Compile::current()->comp_arena()->Amalloc_D(sizeof(RegMask))) RegMask();
+ _live.map(node->_idx, (Node*)live);
+ }
-ZBarrierSetC2State* ZBarrierSetC2::state() const {
+ return live;
+ }
+};
+
+static ZBarrierSetC2State* barrier_set_state() {
return reinterpret_cast<ZBarrierSetC2State*>(Compile::current()->barrier_set_state());
}
-bool ZBarrierSetC2::is_gc_barrier_node(Node* node) const {
- // 1. This step follows potential oop projections of a load barrier before expansion
- if (node->is_Proj()) {
- node = node->in(0);
- }
-
- // 2. This step checks for unexpanded load barriers
- if (node->is_LoadBarrier()) {
- return true;
- }
-
- // 3. This step checks for the phi corresponding to an optimized load barrier expansion
- if (node->is_Phi()) {
- PhiNode* phi = node->as_Phi();
- Node* n = phi->in(1);
- if (n != NULL && n->is_LoadBarrierSlowReg()) {
- return true;
- }
- }
-
- return false;
-}
-
-void ZBarrierSetC2::register_potential_barrier_node(Node* node) const {
- if (node->is_LoadBarrier()) {
- state()->add_load_barrier_node(node->as_LoadBarrier());
- }
-}
-
-void ZBarrierSetC2::unregister_potential_barrier_node(Node* node) const {
- if (node->is_LoadBarrier()) {
- state()->remove_load_barrier_node(node->as_LoadBarrier());
- }
-}
-
-void ZBarrierSetC2::eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const {
- // Remove useless LoadBarrier nodes
- ZBarrierSetC2State* s = state();
- for (int i = s->load_barrier_count()-1; i >= 0; i--) {
- LoadBarrierNode* n = s->load_barrier_node(i);
- if (!useful.member(n)) {
- unregister_potential_barrier_node(n);
- }
- }
-}
-
-void ZBarrierSetC2::enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const {
- if (node->is_LoadBarrier() && !node->as_LoadBarrier()->has_true_uses()) {
- igvn->_worklist.push(node);
- }
-}
-
-const uint NoBarrier = 0;
-const uint RequireBarrier = 1;
-const uint WeakBarrier = 2;
-const uint ExpandedBarrier = 4;
-
-static bool load_require_barrier(LoadNode* load) { return (load->barrier_data() & RequireBarrier) == RequireBarrier; }
-static bool load_has_weak_barrier(LoadNode* load) { return (load->barrier_data() & WeakBarrier) == WeakBarrier; }
-static bool load_has_expanded_barrier(LoadNode* load) { return (load->barrier_data() & ExpandedBarrier) == ExpandedBarrier; }
-static void load_set_expanded_barrier(LoadNode* load) { return load->set_barrier_data(ExpandedBarrier); }
-
-static void load_set_barrier(LoadNode* load, bool weak) {
- if (weak) {
- load->set_barrier_data(RequireBarrier | WeakBarrier);
- } else {
- load->set_barrier_data(RequireBarrier);
- }
-}
-
-// == LoadBarrierNode ==
-
-LoadBarrierNode::LoadBarrierNode(Compile* C,
- Node* c,
- Node* mem,
- Node* val,
- Node* adr,
- bool weak) :
- MultiNode(Number_of_Inputs),
- _weak(weak) {
- init_req(Control, c);
- init_req(Memory, mem);
- init_req(Oop, val);
- init_req(Address, adr);
- init_req(Similar, C->top());
-
- init_class_id(Class_LoadBarrier);
- BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
- bs->register_potential_barrier_node(this);
-}
-
-uint LoadBarrierNode::size_of() const {
- return sizeof(*this);
-}
-
-bool LoadBarrierNode::cmp(const Node& n) const {
- ShouldNotReachHere();
- return false;
-}
-
-const Type *LoadBarrierNode::bottom_type() const {
- const Type** floadbarrier = (const Type **)(Compile::current()->type_arena()->Amalloc_4((Number_of_Outputs)*sizeof(Type*)));
- Node* in_oop = in(Oop);
- floadbarrier[Control] = Type::CONTROL;
- floadbarrier[Memory] = Type::MEMORY;
- floadbarrier[Oop] = in_oop == NULL ? Type::TOP : in_oop->bottom_type();
- return TypeTuple::make(Number_of_Outputs, floadbarrier);
-}
-
-const TypePtr* LoadBarrierNode::adr_type() const {
- ShouldNotReachHere();
- return NULL;
-}
-
-const Type *LoadBarrierNode::Value(PhaseGVN *phase) const {
- const Type** floadbarrier = (const Type **)(phase->C->type_arena()->Amalloc_4((Number_of_Outputs)*sizeof(Type*)));
- const Type* val_t = phase->type(in(Oop));
- floadbarrier[Control] = Type::CONTROL;
- floadbarrier[Memory] = Type::MEMORY;
- floadbarrier[Oop] = val_t;
- return TypeTuple::make(Number_of_Outputs, floadbarrier);
-}
-
-bool LoadBarrierNode::is_dominator(PhaseIdealLoop* phase, bool linear_only, Node *d, Node *n) {
- if (phase != NULL) {
- return phase->is_dominator(d, n);
- }
-
- for (int i = 0; i < 10 && n != NULL; i++) {
- n = IfNode::up_one_dom(n, linear_only);
- if (n == d) {
- return true;
- }
- }
-
- return false;
-}
-
-LoadBarrierNode* LoadBarrierNode::has_dominating_barrier(PhaseIdealLoop* phase, bool linear_only, bool look_for_similar) {
- if (is_weak()) {
- // Weak barriers can't be eliminated
- return NULL;
- }
-
- Node* val = in(LoadBarrierNode::Oop);
- if (in(Similar)->is_Proj() && in(Similar)->in(0)->is_LoadBarrier()) {
- LoadBarrierNode* lb = in(Similar)->in(0)->as_LoadBarrier();
- assert(lb->in(Address) == in(Address), "");
- // Load barrier on Similar edge dominates so if it now has the Oop field it can replace this barrier.
- if (lb->in(Oop) == in(Oop)) {
- return lb;
- }
- // Follow chain of load barrier through Similar edges
- while (!lb->in(Similar)->is_top()) {
- lb = lb->in(Similar)->in(0)->as_LoadBarrier();
- assert(lb->in(Address) == in(Address), "");
- }
- if (lb != in(Similar)->in(0)) {
- return lb;
- }
- }
- for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
- Node* u = val->fast_out(i);
- if (u != this && u->is_LoadBarrier() && u->in(Oop) == val && u->as_LoadBarrier()->has_true_uses()) {
- Node* this_ctrl = in(LoadBarrierNode::Control);
- Node* other_ctrl = u->in(LoadBarrierNode::Control);
- if (is_dominator(phase, linear_only, other_ctrl, this_ctrl)) {
- return u->as_LoadBarrier();
- }
- }
- }
-
- if (can_be_eliminated()) {
- return NULL;
- }
-
- if (!look_for_similar) {
- return NULL;
+ZLoadBarrierStubC2* ZLoadBarrierStubC2::create(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) {
+ ZLoadBarrierStubC2* const stub = new (Compile::current()->comp_arena()) ZLoadBarrierStubC2(node, ref_addr, ref, tmp, weak);
+ if (!Compile::current()->in_scratch_emit_size()) {
+ barrier_set_state()->stubs()->append(stub);
}
- Node* addr = in(LoadBarrierNode::Address);
- for (DUIterator_Fast imax, i = addr->fast_outs(imax); i < imax; i++) {
- Node* u = addr->fast_out(i);
- if (u != this && u->is_LoadBarrier() && u->as_LoadBarrier()->has_true_uses()) {
- Node* this_ctrl = in(LoadBarrierNode::Control);
- Node* other_ctrl = u->in(LoadBarrierNode::Control);
- if (is_dominator(phase, linear_only, other_ctrl, this_ctrl)) {
- ResourceMark rm;
- Unique_Node_List wq;
- wq.push(in(LoadBarrierNode::Control));
- bool ok = true;
- bool dom_found = false;
- for (uint next = 0; next < wq.size(); ++next) {
- Node *n = wq.at(next);
- if (n->is_top()) {
- return NULL;
- }
- assert(n->is_CFG(), "");
- if (n->is_SafePoint()) {
- ok = false;
- break;
- }
- if (n == u) {
- dom_found = true;
- continue;
- }
- if (n->is_Region()) {
- for (uint i = 1; i < n->req(); i++) {
- Node* m = n->in(i);
- if (m != NULL) {
- wq.push(m);
- }
- }
- } else {
- Node* m = n->in(0);
- if (m != NULL) {
- wq.push(m);
- }
- }
- }
- if (ok) {
- assert(dom_found, "");
- return u->as_LoadBarrier();
- }
- break;
- }
- }
- }
+ return stub;
+}
+
+ZLoadBarrierStubC2::ZLoadBarrierStubC2(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) :
+ _node(node),
+ _ref_addr(ref_addr),
+ _ref(ref),
+ _tmp(tmp),
+ _weak(weak),
+ _entry(),
+ _continuation() {
+ assert_different_registers(ref, ref_addr.base());
+ assert_different_registers(ref, ref_addr.index());
+}
- return NULL;
+Address ZLoadBarrierStubC2::ref_addr() const {
+ return _ref_addr;
+}
+
+Register ZLoadBarrierStubC2::ref() const {
+ return _ref;
+}
+
+Register ZLoadBarrierStubC2::tmp() const {
+ return _tmp;
+}
+
+address ZLoadBarrierStubC2::slow_path() const {
+ const DecoratorSet decorators = _weak ? ON_WEAK_OOP_REF : ON_STRONG_OOP_REF;
+ return ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators);
}
-void LoadBarrierNode::push_dominated_barriers(PhaseIterGVN* igvn) const {
- // Change to that barrier may affect a dominated barrier so re-push those
- assert(!is_weak(), "sanity");
- Node* val = in(LoadBarrierNode::Oop);
+RegMask& ZLoadBarrierStubC2::live() const {
+ return *barrier_set_state()->live(_node);
+}
+
+Label* ZLoadBarrierStubC2::entry() {
+ // The _entry will never be bound when in_scratch_emit_size() is true.
+ // However, we still need to return a label that is not bound now, but
+ // will eventually be bound. Any lable will do, as it will only act as
+ // a placeholder, so we return the _continuation label.
+ return Compile::current()->in_scratch_emit_size() ? &_continuation : &_entry;
+}
+
+Label* ZLoadBarrierStubC2::continuation() {
+ return &_continuation;
+}
- for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
- Node* u = val->fast_out(i);
- if (u != this && u->is_LoadBarrier() && u->in(Oop) == val) {
- Node* this_ctrl = in(Control);
- Node* other_ctrl = u->in(Control);
- if (is_dominator(NULL, false, this_ctrl, other_ctrl)) {
- igvn->_worklist.push(u);
- }
+void* ZBarrierSetC2::create_barrier_state(Arena* comp_arena) const {
+ return new (comp_arena) ZBarrierSetC2State(comp_arena);
+}
+
+void ZBarrierSetC2::late_barrier_analysis() const {
+ analyze_dominating_barriers();
+ compute_liveness_at_stubs();
+}
+
+void ZBarrierSetC2::emit_stubs(CodeBuffer& cb) const {
+ MacroAssembler masm(&cb);
+ GrowableArray<ZLoadBarrierStubC2*>* const stubs = barrier_set_state()->stubs();
+
+ for (int i = 0; i < stubs->length(); i++) {
+ // Make sure there is enough space in the code buffer
+ if (cb.insts()->maybe_expand_to_ensure_remaining(Compile::MAX_inst_size) && cb.blob() == NULL) {
+ ciEnv::current()->record_failure("CodeCache is full");
+ return;
}
- Node* addr = in(LoadBarrierNode::Address);
- for (DUIterator_Fast imax, i = addr->fast_outs(imax); i < imax; i++) {
- Node* u = addr->fast_out(i);
- if (u != this && u->is_LoadBarrier() && u->in(Similar)->is_top()) {
- Node* this_ctrl = in(Control);
- Node* other_ctrl = u->in(Control);
- if (is_dominator(NULL, false, this_ctrl, other_ctrl)) {
- igvn->_worklist.push(u);
- }
- }
- }
- }
-}
-
-Node *LoadBarrierNode::Identity(PhaseGVN *phase) {
- LoadBarrierNode* dominating_barrier = has_dominating_barrier(NULL, true, false);
- if (dominating_barrier != NULL) {
- assert(!is_weak(), "Weak barriers cant be eliminated");
- assert(dominating_barrier->in(Oop) == in(Oop), "");
- return dominating_barrier;
- }
-
- return this;
-}
-
-Node *LoadBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) {
- if (remove_dead_region(phase, can_reshape)) {
- return this;
+ ZBarrierSet::assembler()->generate_c2_load_barrier_stub(&masm, stubs->at(i));
}
- Node *val = in(Oop);
- Node *mem = in(Memory);
- Node *ctrl = in(Control);
-
- assert(val->Opcode() != Op_LoadN, "");
- assert(val->Opcode() != Op_DecodeN, "");
-
- if (mem->is_MergeMem()) {
- Node *new_mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw);
- set_req(Memory, new_mem);
- if (mem->outcnt() == 0 && can_reshape) {
- phase->is_IterGVN()->_worklist.push(mem);
- }
- return this;
- }
+ masm.flush();
+}
- LoadBarrierNode *dominating_barrier = NULL;
- if (!is_weak()) {
- dominating_barrier = has_dominating_barrier(NULL, !can_reshape, !phase->C->major_progress());
- if (dominating_barrier != NULL && dominating_barrier->in(Oop) != in(Oop)) {
- assert(in(Address) == dominating_barrier->in(Address), "");
- set_req(Similar, dominating_barrier->proj_out(Oop));
- return this;
- }
- }
-
- bool eliminate = can_reshape && (dominating_barrier != NULL || !has_true_uses());
- if (eliminate) {
- if (can_reshape) {
- PhaseIterGVN* igvn = phase->is_IterGVN();
- Node* out_ctrl = proj_out_or_null(Control);
- Node* out_res = proj_out_or_null(Oop);
+int ZBarrierSetC2::estimate_stub_size() const {
+ Compile* const C = Compile::current();
+ BufferBlob* const blob = C->scratch_buffer_blob();
+ GrowableArray<ZLoadBarrierStubC2*>* const stubs = barrier_set_state()->stubs();
+ int size = 0;
- if (out_ctrl != NULL) {
- igvn->replace_node(out_ctrl, ctrl);
- }
-
- // That transformation may cause the Similar edge on the load barrier to be invalid
- fix_similar_in_uses(igvn);
- if (out_res != NULL) {
- if (dominating_barrier != NULL) {
- assert(!is_weak(), "Sanity");
- igvn->replace_node(out_res, dominating_barrier->proj_out(Oop));
- } else {
- igvn->replace_node(out_res, val);
- }
- }
- }
- return new ConINode(TypeInt::ZERO);
+ for (int i = 0; i < stubs->length(); i++) {
+ CodeBuffer cb(blob->content_begin(), (address)C->scratch_locs_memory() - blob->content_begin());
+ MacroAssembler masm(&cb);
+ ZBarrierSet::assembler()->generate_c2_load_barrier_stub(&masm, stubs->at(i));
+ size += cb.insts_size();
}
- // If the Similar edge is no longer a load barrier, clear it
- Node* similar = in(Similar);
- if (!similar->is_top() && !(similar->is_Proj() && similar->in(0)->is_LoadBarrier())) {
- set_req(Similar, phase->C->top());
- return this;
- }
-
- if (can_reshape && !is_weak()) {
- // If this barrier is linked through the Similar edge by a
- // dominated barrier and both barriers have the same Oop field,
- // the dominated barrier can go away, so push it for reprocessing.
- // We also want to avoid a barrier to depend on another dominating
- // barrier through its Similar edge that itself depend on another
- // barrier through its Similar edge and rather have the first
- // depend on the third.
- PhaseIterGVN* igvn = phase->is_IterGVN();
- Node* out_res = proj_out(Oop);
- for (DUIterator_Fast imax, i = out_res->fast_outs(imax); i < imax; i++) {
- Node* u = out_res->fast_out(i);
- if (u->is_LoadBarrier() && u->in(Similar) == out_res &&
- (u->in(Oop) == val || !u->in(Similar)->is_top())) {
- assert(!u->as_LoadBarrier()->is_weak(), "Sanity");
- igvn->_worklist.push(u);
- }
- }
- push_dominated_barriers(igvn);
- }
-
- return NULL;
-}
-
-uint LoadBarrierNode::match_edge(uint idx) const {
- ShouldNotReachHere();
- return 0;
-}
-
-void LoadBarrierNode::fix_similar_in_uses(PhaseIterGVN* igvn) {
- Node* out_res = proj_out_or_null(Oop);
- if (out_res == NULL) {
- return;
- }
-
- for (DUIterator_Fast imax, i = out_res->fast_outs(imax); i < imax; i++) {
- Node* u = out_res->fast_out(i);
- if (u->is_LoadBarrier() && u->in(Similar) == out_res) {
- igvn->replace_input_of(u, Similar, igvn->C->top());
- --i;
- --imax;
- }
- }
-}
-
-bool LoadBarrierNode::has_true_uses() const {
- Node* out_res = proj_out_or_null(Oop);
- if (out_res != NULL) {
- for (DUIterator_Fast imax, i = out_res->fast_outs(imax); i < imax; i++) {
- Node *u = out_res->fast_out(i);
- if (!u->is_LoadBarrier() || u->in(Similar) != out_res) {
- return true;
- }
- }
- }
- return false;
+ return size;
}
static bool barrier_needed(C2Access& access) {
@@ -474,1223 +180,252 @@
}
Node* ZBarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) const {
- Node* p = BarrierSetC2::load_at_resolved(access, val_type);
- if (!barrier_needed(access)) {
- return p;
+ Node* result = BarrierSetC2::load_at_resolved(access, val_type);
+ if (barrier_needed(access) && access.raw_access()->is_Mem()) {
+ if ((access.decorators() & ON_WEAK_OOP_REF) != 0) {
+ access.raw_access()->as_Load()->set_barrier_data(ZLoadBarrierWeak);
+ } else {
+ access.raw_access()->as_Load()->set_barrier_data(ZLoadBarrierStrong);
+ }
}
- bool weak = (access.decorators() & ON_WEAK_OOP_REF) != 0;
- if (p->isa_Load()) {
- load_set_barrier(p->as_Load(), weak);
- }
- return p;
+ return result;
}
Node* ZBarrierSetC2::atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
Node* new_val, const Type* val_type) const {
Node* result = BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, new_val, val_type);
- LoadStoreNode* lsn = result->as_LoadStore();
if (barrier_needed(access)) {
- lsn->set_has_barrier();
+ access.raw_access()->as_LoadStore()->set_barrier_data(ZLoadBarrierStrong);
}
- return lsn;
+ return result;
}
Node* ZBarrierSetC2::atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
Node* new_val, const Type* value_type) const {
Node* result = BarrierSetC2::atomic_cmpxchg_bool_at_resolved(access, expected_val, new_val, value_type);
- LoadStoreNode* lsn = result->as_LoadStore();
if (barrier_needed(access)) {
- lsn->set_has_barrier();
+ access.raw_access()->as_LoadStore()->set_barrier_data(ZLoadBarrierStrong);
}
- return lsn;
+ return result;
}
Node* ZBarrierSetC2::atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* val_type) const {
Node* result = BarrierSetC2::atomic_xchg_at_resolved(access, new_val, val_type);
- LoadStoreNode* lsn = result->as_LoadStore();
if (barrier_needed(access)) {
- lsn->set_has_barrier();
+ access.raw_access()->as_LoadStore()->set_barrier_data(ZLoadBarrierStrong);
}
- return lsn;
+ return result;
}
-// == Macro Expansion ==
-
-// Optimized, low spill, loadbarrier variant using stub specialized on register used
-void ZBarrierSetC2::expand_loadbarrier_node(PhaseMacroExpand* phase, LoadBarrierNode* barrier) const {
- PhaseIterGVN &igvn = phase->igvn();
- float unlikely = PROB_UNLIKELY(0.999);
-
- Node* in_ctrl = barrier->in(LoadBarrierNode::Control);
- Node* in_mem = barrier->in(LoadBarrierNode::Memory);
- Node* in_val = barrier->in(LoadBarrierNode::Oop);
- Node* in_adr = barrier->in(LoadBarrierNode::Address);
-
- Node* out_ctrl = barrier->proj_out(LoadBarrierNode::Control);
- Node* out_res = barrier->proj_out(LoadBarrierNode::Oop);
-
- assert(barrier->in(LoadBarrierNode::Oop) != NULL, "oop to loadbarrier node cannot be null");
-
- Node* jthread = igvn.transform(new ThreadLocalNode());
- Node* adr = phase->basic_plus_adr(jthread, in_bytes(ZThreadLocalData::address_bad_mask_offset()));
- Node* bad_mask = igvn.transform(LoadNode::make(igvn, in_ctrl, in_mem, adr,
- TypeRawPtr::BOTTOM, TypeX_X, TypeX_X->basic_type(),
- MemNode::unordered));
- Node* cast = igvn.transform(new CastP2XNode(in_ctrl, in_val));
- Node* obj_masked = igvn.transform(new AndXNode(cast, bad_mask));
- Node* cmp = igvn.transform(new CmpXNode(obj_masked, igvn.zerocon(TypeX_X->basic_type())));
- Node *bol = igvn.transform(new BoolNode(cmp, BoolTest::ne))->as_Bool();
- IfNode* iff = igvn.transform(new IfNode(in_ctrl, bol, unlikely, COUNT_UNKNOWN))->as_If();
- Node* then = igvn.transform(new IfTrueNode(iff));
- Node* elsen = igvn.transform(new IfFalseNode(iff));
-
- Node* new_loadp = igvn.transform(new LoadBarrierSlowRegNode(then, in_adr, in_val,
- (const TypePtr*) in_val->bottom_type(), barrier->is_weak()));
-
- // Create the final region/phi pair to converge cntl/data paths to downstream code
- Node* result_region = igvn.transform(new RegionNode(3));
- result_region->set_req(1, then);
- result_region->set_req(2, elsen);
-
- Node* result_phi = igvn.transform(new PhiNode(result_region, TypeInstPtr::BOTTOM));
- result_phi->set_req(1, new_loadp);
- result_phi->set_req(2, barrier->in(LoadBarrierNode::Oop));
-
- igvn.replace_node(out_ctrl, result_region);
- igvn.replace_node(out_res, result_phi);
-
- assert(barrier->outcnt() == 0,"LoadBarrier macro node has non-null outputs after expansion!");
-
- igvn.remove_dead_node(barrier);
- igvn.remove_dead_node(out_ctrl);
- igvn.remove_dead_node(out_res);
-
- assert(is_gc_barrier_node(result_phi), "sanity");
- assert(step_over_gc_barrier(result_phi) == in_val, "sanity");
-
- phase->C->print_method(PHASE_BARRIER_EXPANSION, 4, barrier->_idx);
+bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type,
+ bool is_clone, ArrayCopyPhase phase) const {
+ return type == T_OBJECT || type == T_ARRAY;
}
-bool ZBarrierSetC2::expand_barriers(Compile* C, PhaseIterGVN& igvn) const {
- ZBarrierSetC2State* s = state();
- if (s->load_barrier_count() > 0) {
- PhaseMacroExpand macro(igvn);
+// == Dominating barrier elision ==
- int skipped = 0;
- while (s->load_barrier_count() > skipped) {
- int load_barrier_count = s->load_barrier_count();
- LoadBarrierNode * n = s->load_barrier_node(load_barrier_count-1-skipped);
- 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
- s->remove_load_barrier_node(n);
- continue;
- }
- if (!n->can_be_eliminated()) {
- skipped++;
- continue;
- }
- expand_loadbarrier_node(¯o, n);
- assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list");
- if (C->failing()) {
- return true;
- }
- }
- while (s->load_barrier_count() > 0) {
- int load_barrier_count = s->load_barrier_count();
- LoadBarrierNode* n = s->load_barrier_node(load_barrier_count - 1);
- assert(!(igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())), "should have been processed already");
- assert(!n->can_be_eliminated(), "should have been processed already");
- expand_loadbarrier_node(¯o, n);
- assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list");
- if (C->failing()) {
- return true;
- }
- }
- igvn.set_delay_transform(false);
- igvn.optimize();
- if (C->failing()) {
+static bool block_has_safepoint(const Block* block, uint from, uint to) {
+ for (uint i = from; i < to; i++) {
+ if (block->get_node(i)->is_MachSafePoint()) {
+ // Safepoint found
return true;
}
}
+ // Safepoint not found
return false;
}
-Node* ZBarrierSetC2::step_over_gc_barrier(Node* c) const {
- Node* node = c;
+static bool block_has_safepoint(const Block* block) {
+ return block_has_safepoint(block, 0, block->number_of_nodes());
+}
- // 1. This step follows potential oop projections of a load barrier before expansion
- if (node->is_Proj()) {
- node = node->in(0);
+static uint block_index(const Block* block, const Node* node) {
+ for (uint j = 0; j < block->number_of_nodes(); ++j) {
+ if (block->get_node(j) == node) {
+ return j;
+ }
}
+ ShouldNotReachHere();
+ return 0;
+}
+
+void ZBarrierSetC2::analyze_dominating_barriers() const {
+ ResourceMark rm;
+ Compile* const C = Compile::current();
+ PhaseCFG* const cfg = C->cfg();
+ Block_List worklist;
+ Node_List mem_ops;
+ Node_List barrier_loads;
- // 2. This step checks for unexpanded load barriers
- if (node->is_LoadBarrier()) {
- return node->in(LoadBarrierNode::Oop);
- }
+ // Step 1 - Find accesses, and track them in lists
+ for (uint i = 0; i < cfg->number_of_blocks(); ++i) {
+ const Block* const block = cfg->get_block(i);
+ for (uint j = 0; j < block->number_of_nodes(); ++j) {
+ const Node* const node = block->get_node(j);
+ if (!node->is_Mach()) {
+ continue;
+ }
- // 3. This step checks for the phi corresponding to an optimized load barrier expansion
- if (node->is_Phi()) {
- PhiNode* phi = node->as_Phi();
- Node* n = phi->in(1);
- if (n != NULL && n->is_LoadBarrierSlowReg()) {
- assert(c == node, "projections from step 1 should only be seen before macro expansion");
- return phi->in(2);
+ MachNode* const mach = node->as_Mach();
+ switch (mach->ideal_Opcode()) {
+ case Op_LoadP:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndSwapP:
+ case Op_GetAndSetP:
+ if (mach->barrier_data() == ZLoadBarrierStrong) {
+ barrier_loads.push(mach);
+ }
+ case Op_StoreP:
+ mem_ops.push(mach);
+ break;
+
+ default:
+ break;
+ }
}
}
- return c;
-}
-
-Node* ZBarrierSetC2::step_over_gc_barrier_ctrl(Node* c) const {
- Node* node = c;
-
- // 1. This step follows potential ctrl projections of a load barrier before expansion
- if (node->is_Proj()) {
- node = node->in(0);
- }
-
- // 2. This step checks for unexpanded load barriers
- if (node->is_LoadBarrier()) {
- return node->in(LoadBarrierNode::Control);
- }
-
- return c;
-}
-
-bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
- return is_reference_type(type);
-}
-
-bool ZBarrierSetC2::final_graph_reshaping(Compile* compile, Node* n, uint opcode) const {
- switch (opcode) {
- case Op_LoadBarrier:
- assert(0, "There should be no load barriers left");
- case Op_ZGetAndSetP:
- case Op_ZCompareAndExchangeP:
- case Op_ZCompareAndSwapP:
- case Op_ZWeakCompareAndSwapP:
-#ifdef ASSERT
- if (VerifyOptoOopOffsets) {
- MemNode *mem = n->as_Mem();
- // Check to see if address types have grounded out somehow.
- const TypeInstPtr *tp = mem->in(MemNode::Address)->bottom_type()->isa_instptr();
- ciInstanceKlass *k = tp->klass()->as_instance_klass();
- bool oop_offset_is_sane = k->contains_field_offset(tp->offset());
- assert(!tp || oop_offset_is_sane, "");
- }
-#endif
- return true;
- default:
- return false;
- }
-}
+ // Step 2 - Find dominating accesses for each load
+ for (uint i = 0; i < barrier_loads.size(); i++) {
+ MachNode* const load = barrier_loads.at(i)->as_Mach();
+ const TypePtr* load_adr_type = NULL;
+ intptr_t load_offset = 0;
+ const Node* const load_obj = load->get_base_and_disp(load_offset, load_adr_type);
+ Block* const load_block = cfg->get_block_for_node(load);
+ const uint load_index = block_index(load_block, load);
-bool ZBarrierSetC2::matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const {
- switch(opcode) {
- case Op_CallLeaf:
- if (n->as_Call()->entry_point() == ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr() ||
- n->as_Call()->entry_point() == ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded_addr()) {
- mem_op = true;
- mem_addr_idx = TypeFunc::Parms + 1;
- return true;
- }
- return false;
- default:
- return false;
- }
-}
-
-bool ZBarrierSetC2::matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const {
- switch(opcode) {
- case Op_ZCompareAndExchangeP:
- case Op_ZCompareAndSwapP:
- case Op_ZWeakCompareAndSwapP: {
- Node *mem = n->in(MemNode::Address);
- Node *keepalive = n->in(5);
- Node *pair1 = new BinaryNode(mem, keepalive);
-
- Node *newval = n->in(MemNode::ValueIn);
- Node *oldval = n->in(LoadStoreConditionalNode::ExpectedIn);
- Node *pair2 = new BinaryNode(oldval, newval);
+ for (uint j = 0; j < mem_ops.size(); j++) {
+ MachNode* mem = mem_ops.at(j)->as_Mach();
+ const TypePtr* mem_adr_type = NULL;
+ intptr_t mem_offset = 0;
+ const Node* mem_obj = mem_obj = mem->get_base_and_disp(mem_offset, mem_adr_type);
+ Block* mem_block = cfg->get_block_for_node(mem);
+ uint mem_index = block_index(mem_block, mem);
- n->set_req(MemNode::Address, pair1);
- n->set_req(MemNode::ValueIn, pair2);
- n->del_req(5);
- n->del_req(LoadStoreConditionalNode::ExpectedIn);
- return true;
- }
- case Op_ZGetAndSetP: {
- Node *keepalive = n->in(4);
- Node *newval = n->in(MemNode::ValueIn);
- Node *pair = new BinaryNode(newval, keepalive);
- n->set_req(MemNode::ValueIn, pair);
- n->del_req(4);
- return true;
- }
+ if (load_obj == NodeSentinel || mem_obj == NodeSentinel ||
+ load_obj == NULL || mem_obj == NULL ||
+ load_offset < 0 || mem_offset < 0) {
+ continue;
+ }
- default:
- return false;
- }
-}
-
-// == Verification ==
-
-#ifdef ASSERT
-
-static void verify_slippery_safepoints_internal(Node* ctrl) {
- // Given a CFG node, make sure it does not contain both safepoints and loads
- // that have expanded barriers.
- bool found_safepoint = false;
- bool found_load = false;
+ if (mem_obj != load_obj || mem_offset != load_offset) {
+ // Not the same addresses, not a candidate
+ continue;
+ }
- for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) {
- Node* node = ctrl->fast_out(i);
- if (node->in(0) != ctrl) {
- // Skip outgoing precedence edges from ctrl.
- continue;
- }
- if (node->is_SafePoint()) {
- found_safepoint = true;
- }
- if (node->is_Load() && load_require_barrier(node->as_Load()) &&
- load_has_expanded_barrier(node->as_Load())) {
- found_load = true;
- }
- }
- assert(!found_safepoint || !found_load, "found load and safepoint in same block");
-}
-
-static void verify_slippery_safepoints(Compile* C) {
- ResourceArea *area = Thread::current()->resource_area();
- Unique_Node_List visited(area);
- Unique_Node_List checked(area);
-
- // Recursively walk the graph.
- visited.push(C->root());
- while (visited.size() > 0) {
- Node* node = visited.pop();
-
- Node* ctrl = node;
- if (!node->is_CFG()) {
- ctrl = node->in(0);
- }
-
- if (ctrl != NULL && !checked.member(ctrl)) {
- // For each block found in the graph, verify that it does not
- // contain both a safepoint and a load requiring barriers.
- verify_slippery_safepoints_internal(ctrl);
-
- checked.push(ctrl);
- }
-
- checked.push(node);
-
- for (DUIterator_Fast imax, i = node->fast_outs(imax); i < imax; i++) {
- Node* use = node->fast_out(i);
- if (checked.member(use)) continue;
- if (visited.member(use)) continue;
- visited.push(use);
- }
- }
-}
+ if (load_block == mem_block) {
+ // Earlier accesses in the same block
+ if (mem_index < load_index && !block_has_safepoint(mem_block, mem_index + 1, load_index)) {
+ load->set_barrier_data(ZLoadBarrierElided);
+ }
+ } else if (mem_block->dominates(load_block)) {
+ // Dominating block? Look around for safepoints
+ ResourceMark rm;
+ Block_List stack;
+ VectorSet visited(Thread::current()->resource_area());
+ stack.push(load_block);
+ bool safepoint_found = block_has_safepoint(load_block);
+ while (!safepoint_found && stack.size() > 0) {
+ Block* block = stack.pop();
+ if (visited.test_set(block->_pre_order)) {
+ continue;
+ }
+ if (block_has_safepoint(block)) {
+ safepoint_found = true;
+ break;
+ }
+ if (block == mem_block) {
+ continue;
+ }
-void ZBarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase phase) const {
- switch(phase) {
- case BarrierSetC2::BeforeOptimize:
- case BarrierSetC2::BeforeLateInsertion:
- assert(state()->load_barrier_count() == 0, "No barriers inserted yet");
- break;
- case BarrierSetC2::BeforeMacroExpand:
- // Barrier placement should be set by now.
- verify_gc_barriers(false /*post_parse*/);
- break;
- case BarrierSetC2::BeforeCodeGen:
- // Barriers has been fully expanded.
- assert(state()->load_barrier_count() == 0, "No more macro barriers");
- verify_slippery_safepoints(compile);
- break;
- default:
- assert(0, "Phase without verification");
- }
-}
-
-// post_parse implies that there might be load barriers without uses after parsing
-// That only applies when adding barriers at parse time.
-void ZBarrierSetC2::verify_gc_barriers(bool post_parse) const {
- ZBarrierSetC2State* s = state();
- Compile* C = Compile::current();
- ResourceMark rm;
- VectorSet visited(Thread::current()->resource_area());
-
- for (int i = 0; i < s->load_barrier_count(); i++) {
- LoadBarrierNode* n = s->load_barrier_node(i);
-
- // The dominating barrier on the same address if it exists and
- // this barrier must not be applied on the value from the same
- // load otherwise the value is not reloaded before it's used the
- // second time.
- assert(n->in(LoadBarrierNode::Similar)->is_top() ||
- (n->in(LoadBarrierNode::Similar)->in(0)->is_LoadBarrier() &&
- n->in(LoadBarrierNode::Similar)->in(0)->in(LoadBarrierNode::Address) == n->in(LoadBarrierNode::Address) &&
- n->in(LoadBarrierNode::Similar)->in(0)->in(LoadBarrierNode::Oop) != n->in(LoadBarrierNode::Oop)),
- "broken similar edge");
-
- assert(n->as_LoadBarrier()->has_true_uses(),
- "found unneeded load barrier");
-
- // Several load barrier nodes chained through their Similar edge
- // break the code that remove the barriers in final graph reshape.
- assert(n->in(LoadBarrierNode::Similar)->is_top() ||
- (n->in(LoadBarrierNode::Similar)->in(0)->is_LoadBarrier() &&
- n->in(LoadBarrierNode::Similar)->in(0)->in(LoadBarrierNode::Similar)->is_top()),
- "chain of Similar load barriers");
-
- if (!n->in(LoadBarrierNode::Similar)->is_top()) {
- ResourceMark rm;
- Unique_Node_List wq;
- Node* other = n->in(LoadBarrierNode::Similar)->in(0);
- wq.push(n);
- for (uint next = 0; next < wq.size(); ++next) {
- Node *nn = wq.at(next);
- assert(nn->is_CFG(), "");
- assert(!nn->is_SafePoint(), "");
-
- if (nn == other) {
- continue;
+ // Push predecessor blocks
+ for (uint p = 1; p < block->num_preds(); ++p) {
+ Block* pred = cfg->get_block_for_node(block->pred(p));
+ stack.push(pred);
+ }
}
- if (nn->is_Region()) {
- for (uint i = 1; i < nn->req(); i++) {
- Node* m = nn->in(i);
- if (m != NULL) {
- wq.push(m);
- }
- }
- } else {
- Node* m = nn->in(0);
- if (m != NULL) {
- wq.push(m);
- }
+ if (!safepoint_found) {
+ load->set_barrier_data(ZLoadBarrierElided);
}
}
}
}
}
-#endif // end verification code
-
-// If a call is the control, we actually want its control projection
-static Node* normalize_ctrl(Node* node) {
- if (node->is_Call()) {
- node = node->as_Call()->proj_out(TypeFunc::Control);
- }
- return node;
-}
-
-static Node* get_ctrl_normalized(PhaseIdealLoop *phase, Node* node) {
- return normalize_ctrl(phase->get_ctrl(node));
-}
-
-static void call_catch_cleanup_one(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl);
-
-// This code is cloning all uses of a load that is between a call and the catch blocks,
-// to each use.
-
-static bool fixup_uses_in_catch(PhaseIdealLoop *phase, Node *start_ctrl, Node *node) {
-
- if (!phase->has_ctrl(node)) {
- // This node is floating - doesn't need to be cloned.
- assert(node != start_ctrl, "check");
- return false;
- }
-
- Node* ctrl = get_ctrl_normalized(phase, node);
- if (ctrl != start_ctrl) {
- // We are in a successor block - the node is ok.
- return false; // Unwind
- }
-
- // Process successor nodes
- int outcnt = node->outcnt();
- for (int i = 0; i < outcnt; i++) {
- Node* n = node->raw_out(0);
- assert(!n->is_LoadBarrier(), "Sanity");
- // Calling recursively, visiting leafs first
- fixup_uses_in_catch(phase, start_ctrl, n);
- }
-
- // Now all successors are outside
- // - Clone this node to both successors
- assert(!node->is_Store(), "Stores not expected here");
-
- // In some very rare cases a load that doesn't need a barrier will end up here
- // Treat it as a LoadP and the insertion of phis will be done correctly.
- if (node->is_Load()) {
- call_catch_cleanup_one(phase, node->as_Load(), phase->get_ctrl(node));
- } else {
- for (DUIterator_Fast jmax, i = node->fast_outs(jmax); i < jmax; i++) {
- Node* use = node->fast_out(i);
- Node* clone = node->clone();
- assert(clone->outcnt() == 0, "");
+// == Reduced spilling optimization ==
- assert(use->find_edge(node) != -1, "check");
- phase->igvn().rehash_node_delayed(use);
- use->replace_edge(node, clone);
-
- Node* new_ctrl;
- if (use->is_block_start()) {
- new_ctrl = use;
- } else if (use->is_CFG()) {
- new_ctrl = use->in(0);
- assert (new_ctrl != NULL, "");
- } else {
- new_ctrl = get_ctrl_normalized(phase, use);
- }
-
- phase->set_ctrl(clone, new_ctrl);
-
- if (phase->C->directive()->ZTraceLoadBarriersOption) tty->print_cr(" Clone op %i as %i to control %i", node->_idx, clone->_idx, new_ctrl->_idx);
- phase->igvn().register_new_node_with_optimizer(clone);
- --i, --jmax;
- }
- assert(node->outcnt() == 0, "must be empty now");
-
- // Node node is dead.
- phase->igvn().remove_dead_node(node);
- }
- return true; // unwind - return if a use was processed
-}
+void ZBarrierSetC2::compute_liveness_at_stubs() const {
+ ResourceMark rm;
+ Compile* const C = Compile::current();
+ Arena* const A = Thread::current()->resource_area();
+ PhaseCFG* const cfg = C->cfg();
+ PhaseRegAlloc* const regalloc = C->regalloc();
+ RegMask* const live = NEW_ARENA_ARRAY(A, RegMask, cfg->number_of_blocks() * sizeof(RegMask));
+ ZBarrierSetAssembler* const bs = ZBarrierSet::assembler();
+ Block_List worklist;
-// Clone a load to a specific catch_proj
-static Node* clone_load_to_catchproj(PhaseIdealLoop* phase, Node* load, Node* catch_proj) {
- Node* cloned_load = load->clone();
- cloned_load->set_req(0, catch_proj); // set explicit control
- phase->set_ctrl(cloned_load, catch_proj); // update
- if (phase->C->directive()->ZTraceLoadBarriersOption) tty->print_cr(" Clone LOAD %i as %i to control %i", load->_idx, cloned_load->_idx, catch_proj->_idx);
- phase->igvn().register_new_node_with_optimizer(cloned_load);
- return cloned_load;
-}
-
-static Node* get_dominating_region(PhaseIdealLoop* phase, Node* node, Node* stop) {
- Node* region = node;
- while (!region->isa_Region()) {
- Node *up = phase->idom(region);
- assert(up != region, "Must not loop");
- assert(up != stop, "Must not find original control");
- region = up;
- }
- return region;
-}
-
-// Clone this load to each catch block
-static void call_catch_cleanup_one(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl) {
- bool trace = phase->C->directive()->ZTraceLoadBarriersOption;
- phase->igvn().set_delay_transform(true);
-
- // Verify pre conditions
- assert(ctrl->isa_Proj() && ctrl->in(0)->isa_Call(), "Must be a call proj");
- assert(ctrl->raw_out(0)->isa_Catch(), "Must be a catch");
-
- if (ctrl->raw_out(0)->isa_Catch()->outcnt() == 1) {
- if (trace) tty->print_cr("Cleaning up catch: Skipping load %i, call with single catch", load->_idx);
- return;
+ for (uint i = 0; i < cfg->number_of_blocks(); ++i) {
+ new ((void*)(live + i)) RegMask();
+ worklist.push(cfg->get_block(i));
}
- // Process the loads successor nodes - if any is between
- // the call and the catch blocks, they need to be cloned to.
- // This is done recursively
- for (uint i = 0; i < load->outcnt();) {
- Node *n = load->raw_out(i);
- assert(!n->is_LoadBarrier(), "Sanity");
- if (!fixup_uses_in_catch(phase, ctrl, n)) {
- // if no successor was cloned, progress to next out.
- i++;
- }
- }
-
- // Now all the loads uses has been cloned down
- // Only thing left is to clone the loads, but they must end up
- // first in the catch blocks.
-
- // We clone the loads oo the catch blocks only when needed.
- // An array is used to map the catch blocks to each lazily cloned load.
- // In that way no extra unnecessary loads are cloned.
-
- // Any use dominated by original block must have an phi and a region added
-
- Node* catch_node = ctrl->raw_out(0);
- int number_of_catch_projs = catch_node->outcnt();
- Node** proj_to_load_mapping = NEW_RESOURCE_ARRAY(Node*, number_of_catch_projs);
- Copy::zero_to_bytes(proj_to_load_mapping, sizeof(Node*) * number_of_catch_projs);
-
- // The phi_map is used to keep track of where phis have already been inserted
- int phi_map_len = phase->C->unique();
- Node** phi_map = NEW_RESOURCE_ARRAY(Node*, phi_map_len);
- Copy::zero_to_bytes(phi_map, sizeof(Node*) * phi_map_len);
+ while (worklist.size() > 0) {
+ const Block* const block = worklist.pop();
+ RegMask& old_live = live[block->_pre_order];
+ RegMask new_live;
- for (unsigned int i = 0; i < load->outcnt(); i++) {
- Node* load_use_control = NULL;
- Node* load_use = load->raw_out(i);
-
- if (phase->has_ctrl(load_use)) {
- load_use_control = get_ctrl_normalized(phase, load_use);
- assert(load_use_control != ctrl, "sanity");
- } else {
- load_use_control = load_use->in(0);
- }
- assert(load_use_control != NULL, "sanity");
- if (trace) tty->print_cr(" Handling use: %i, with control: %i", load_use->_idx, load_use_control->_idx);
-
- // Some times the loads use is a phi. For them we need to determine from which catch block
- // the use is defined.
- bool load_use_is_phi = false;
- unsigned int load_use_phi_index = 0;
- Node* phi_ctrl = NULL;
- if (load_use->is_Phi()) {
- // Find phi input that matches load
- for (unsigned int u = 1; u < load_use->req(); u++) {
- if (load_use->in(u) == load) {
- load_use_is_phi = true;
- load_use_phi_index = u;
- assert(load_use->in(0)->is_Region(), "Region or broken");
- phi_ctrl = load_use->in(0)->in(u);
- assert(phi_ctrl->is_CFG(), "check");
- assert(phi_ctrl != load, "check");
- break;
- }
- }
- assert(load_use_is_phi, "must find");
- assert(load_use_phi_index > 0, "sanity");
+ // Initialize to union of successors
+ for (uint i = 0; i < block->_num_succs; i++) {
+ const uint succ_id = block->_succs[i]->_pre_order;
+ new_live.OR(live[succ_id]);
}
- // For each load use, see which catch projs dominates, create load clone lazily and reconnect
- bool found_dominating_catchproj = false;
- for (int c = 0; c < number_of_catch_projs; c++) {
- Node* catchproj = catch_node->raw_out(c);
- assert(catchproj != NULL && catchproj->isa_CatchProj(), "Sanity");
-
- if (!phase->is_dominator(catchproj, load_use_control)) {
- if (load_use_is_phi && phase->is_dominator(catchproj, phi_ctrl)) {
- // The loads use is local to the catchproj.
- // fall out and replace load with catch-local load clone.
- } else {
- continue;
- }
- }
- assert(!found_dominating_catchproj, "Max one should match");
-
- // Clone loads to catch projs
- Node* load_clone = proj_to_load_mapping[c];
- if (load_clone == NULL) {
- load_clone = clone_load_to_catchproj(phase, load, catchproj);
- proj_to_load_mapping[c] = load_clone;
- }
- phase->igvn().rehash_node_delayed(load_use);
+ // Walk block backwards, computing liveness
+ for (int i = block->number_of_nodes() - 1; i >= 0; --i) {
+ const Node* const node = block->get_node(i);
- if (load_use_is_phi) {
- // phis are special - the load is defined from a specific control flow
- load_use->set_req(load_use_phi_index, load_clone);
- } else {
- // Multipe edges can be replaced at once - on calls for example
- load_use->replace_edge(load, load_clone);
+ // Remove def bits
+ const OptoReg::Name first = bs->refine_register(node, regalloc->get_reg_first(node));
+ const OptoReg::Name second = bs->refine_register(node, regalloc->get_reg_second(node));
+ if (first != OptoReg::Bad) {
+ new_live.Remove(first);
}
- --i; // more than one edge can have been removed, but the next is in later iterations
-
- // We could break the for-loop after finding a dominating match.
- // But keep iterating to catch any bad idom early.
- found_dominating_catchproj = true;
- }
+ if (second != OptoReg::Bad) {
+ new_live.Remove(second);
+ }
- // We found no single catchproj that dominated the use - The use is at a point after
- // where control flow from multiple catch projs have merged. We will have to create
- // phi nodes before the use and tie the output from the cloned loads together. It
- // can be a single phi or a number of chained phis, depending on control flow
- if (!found_dominating_catchproj) {
-
- // Use phi-control if use is a phi
- if (load_use_is_phi) {
- load_use_control = phi_ctrl;
- }
- assert(phase->is_dominator(ctrl, load_use_control), "Common use but no dominator");
-
- // Clone a load on all paths
- for (int c = 0; c < number_of_catch_projs; c++) {
- Node* catchproj = catch_node->raw_out(c);
- Node* load_clone = proj_to_load_mapping[c];
- if (load_clone == NULL) {
- load_clone = clone_load_to_catchproj(phase, load, catchproj);
- proj_to_load_mapping[c] = load_clone;
+ // Add use bits
+ for (uint j = 1; j < node->req(); ++j) {
+ const Node* const use = node->in(j);
+ const OptoReg::Name first = bs->refine_register(use, regalloc->get_reg_first(use));
+ const OptoReg::Name second = bs->refine_register(use, regalloc->get_reg_second(use));
+ if (first != OptoReg::Bad) {
+ new_live.Insert(first);
+ }
+ if (second != OptoReg::Bad) {
+ new_live.Insert(second);
}
}
- // Move up dominator tree from use until dom front is reached
- Node* next_region = get_dominating_region(phase, load_use_control, ctrl);
- while (phase->idom(next_region) != catch_node) {
- next_region = phase->idom(next_region);
- if (trace) tty->print_cr("Moving up idom to region ctrl %i", next_region->_idx);
- }
- assert(phase->is_dominator(catch_node, next_region), "Sanity");
-
- // Create or reuse phi node that collect all cloned loads and feed it to the use.
- Node* test_phi = phi_map[next_region->_idx];
- if ((test_phi != NULL) && test_phi->is_Phi()) {
- // Reuse an already created phi
- if (trace) tty->print_cr(" Using cached Phi %i on load_use %i", test_phi->_idx, load_use->_idx);
- phase->igvn().rehash_node_delayed(load_use);
- load_use->replace_edge(load, test_phi);
- // Now this use is done
- } else {
- // Otherwise we need to create one or more phis
- PhiNode* next_phi = new PhiNode(next_region, load->type());
- phi_map[next_region->_idx] = next_phi; // cache new phi
- phase->igvn().rehash_node_delayed(load_use);
- load_use->replace_edge(load, next_phi);
-
- int dominators_of_region = 0;
- do {
- // New phi, connect to region and add all loads as in.
- Node* region = next_region;
- assert(region->isa_Region() && region->req() > 2, "Catch dead region nodes");
- PhiNode* new_phi = next_phi;
-
- if (trace) tty->print_cr("Created Phi %i on load %i with control %i", new_phi->_idx, load->_idx, region->_idx);
-
- // Need to add all cloned loads to the phi, taking care that the right path is matched
- dominators_of_region = 0; // reset for new region
- for (unsigned int reg_i = 1; reg_i < region->req(); reg_i++) {
- Node* region_pred = region->in(reg_i);
- assert(region_pred->is_CFG(), "check");
- bool pred_has_dominator = false;
- for (int c = 0; c < number_of_catch_projs; c++) {
- Node* catchproj = catch_node->raw_out(c);
- if (phase->is_dominator(catchproj, region_pred)) {
- new_phi->set_req(reg_i, proj_to_load_mapping[c]);
- if (trace) tty->print_cr(" - Phi in(%i) set to load %i", reg_i, proj_to_load_mapping[c]->_idx);
- pred_has_dominator = true;
- dominators_of_region++;
- break;
- }
- }
-
- // Sometimes we need to chain several phis.
- if (!pred_has_dominator) {
- assert(dominators_of_region <= 1, "More than one region can't require extra phi");
- if (trace) tty->print_cr(" - Region %i pred %i not dominated by catch proj", region->_idx, region_pred->_idx);
- // Continue search on on this region_pred
- // - walk up to next region
- // - create a new phi and connect to first new_phi
- next_region = get_dominating_region(phase, region_pred, ctrl);
-
- // Lookup if there already is a phi, create a new otherwise
- Node* test_phi = phi_map[next_region->_idx];
- if ((test_phi != NULL) && test_phi->is_Phi()) {
- next_phi = test_phi->isa_Phi();
- dominators_of_region++; // record that a match was found and that we are done
- if (trace) tty->print_cr(" Using cached phi Phi %i on control %i", next_phi->_idx, next_region->_idx);
- } else {
- next_phi = new PhiNode(next_region, load->type());
- phi_map[next_region->_idx] = next_phi;
- }
- new_phi->set_req(reg_i, next_phi);
- }
- }
-
- new_phi->set_req(0, region);
- phase->igvn().register_new_node_with_optimizer(new_phi);
- phase->set_ctrl(new_phi, region);
-
- assert(dominators_of_region != 0, "Must have found one this iteration");
- } while (dominators_of_region == 1);
- }
- --i;
- }
- } // end of loop over uses
-
- assert(load->outcnt() == 0, "All uses should be handled");
- phase->igvn().remove_dead_node(load);
- phase->C->print_method(PHASE_CALL_CATCH_CLEANUP, 4, load->_idx);
-
- // Now we should be home
- phase->igvn().set_delay_transform(false);
-}
-
-// Sort out the loads that are between a call ant its catch blocks
-static void process_catch_cleanup_candidate(PhaseIdealLoop* phase, LoadNode* load, bool verify) {
- bool trace = phase->C->directive()->ZTraceLoadBarriersOption;
-
- Node* ctrl = get_ctrl_normalized(phase, load);
- if (!ctrl->is_Proj() || (ctrl->in(0) == NULL) || !ctrl->in(0)->isa_Call()) {
- return;
- }
-
- Node* catch_node = ctrl->isa_Proj()->raw_out(0);
- if (catch_node->is_Catch()) {
- if (catch_node->outcnt() > 1) {
- assert(!verify, "All loads should already have been moved");
- call_catch_cleanup_one(phase, load, ctrl);
- } else {
- if (trace) tty->print_cr("Call catch cleanup with only one catch: load %i ", load->_idx);
- }
- }
-}
-
-void ZBarrierSetC2::barrier_insertion_phase(Compile* C, PhaseIterGVN& igvn) const {
- PhaseIdealLoop::optimize(igvn, LoopOptsZBarrierInsertion);
- if (C->failing()) return;
-}
-
-bool ZBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const {
-
- if (mode == LoopOptsZBarrierInsertion) {
- // First make sure all loads between call and catch are moved to the catch block
- clean_catch_blocks(phase);
- DEBUG_ONLY(clean_catch_blocks(phase, true /* verify */);)
-
- // Then expand barriers on all loads
- insert_load_barriers(phase);
-
- // Handle all Unsafe that need barriers.
- insert_barriers_on_unsafe(phase);
-
- phase->C->clear_major_progress();
- return true;
- } else {
- return false;
- }
-}
-
-static bool can_simplify_cas(LoadStoreNode* node) {
- if (node->isa_LoadStoreConditional()) {
- Node *expected_in = node->as_LoadStoreConditional()->in(LoadStoreConditionalNode::ExpectedIn);
- return (expected_in->get_ptr_type() == TypePtr::NULL_PTR);
- } else {
- return false;
- }
-}
-
-static void insert_barrier_before_unsafe(PhaseIdealLoop* phase, LoadStoreNode* old_node) {
-
- Compile *C = phase->C;
- PhaseIterGVN &igvn = phase->igvn();
- LoadStoreNode* zclone = NULL;
-
- Node *in_ctrl = old_node->in(MemNode::Control);
- Node *in_mem = old_node->in(MemNode::Memory);
- Node *in_adr = old_node->in(MemNode::Address);
- Node *in_val = old_node->in(MemNode::ValueIn);
- const TypePtr *adr_type = old_node->adr_type();
- const TypePtr* load_type = TypeOopPtr::BOTTOM; // The type for the load we are adding
-
- switch (old_node->Opcode()) {
- case Op_CompareAndExchangeP: {
- zclone = new ZCompareAndExchangePNode(in_ctrl, in_mem, in_adr, in_val, old_node->in(LoadStoreConditionalNode::ExpectedIn),
- adr_type, old_node->get_ptr_type(), ((CompareAndExchangeNode*)old_node)->order());
- load_type = old_node->bottom_type()->is_ptr();
- break;
- }
- case Op_WeakCompareAndSwapP: {
- if (can_simplify_cas(old_node)) {
- break;
- }
- zclone = new ZWeakCompareAndSwapPNode(in_ctrl, in_mem, in_adr, in_val, old_node->in(LoadStoreConditionalNode::ExpectedIn),
- ((CompareAndSwapNode*)old_node)->order());
- adr_type = TypePtr::BOTTOM;
- break;
- }
- case Op_CompareAndSwapP: {
- if (can_simplify_cas(old_node)) {
- break;
- }
- zclone = new ZCompareAndSwapPNode(in_ctrl, in_mem, in_adr, in_val, old_node->in(LoadStoreConditionalNode::ExpectedIn),
- ((CompareAndSwapNode*)old_node)->order());
- adr_type = TypePtr::BOTTOM;
- break;
- }
- case Op_GetAndSetP: {
- zclone = new ZGetAndSetPNode(in_ctrl, in_mem, in_adr, in_val, old_node->adr_type(), old_node->get_ptr_type());
- load_type = old_node->bottom_type()->is_ptr();
- break;
- }
- }
- if (zclone != NULL) {
- igvn.register_new_node_with_optimizer(zclone, old_node);
-
- // Make load
- LoadPNode *load = new LoadPNode(NULL, in_mem, in_adr, adr_type, load_type, MemNode::unordered,
- LoadNode::DependsOnlyOnTest);
- load_set_expanded_barrier(load);
- igvn.register_new_node_with_optimizer(load);
- igvn.replace_node(old_node, zclone);
-
- Node *barrier = new LoadBarrierNode(C, NULL, in_mem, load, in_adr, false /* weak */);
- Node *barrier_val = new ProjNode(barrier, LoadBarrierNode::Oop);
- Node *barrier_ctrl = new ProjNode(barrier, LoadBarrierNode::Control);
-
- igvn.register_new_node_with_optimizer(barrier);
- igvn.register_new_node_with_optimizer(barrier_val);
- igvn.register_new_node_with_optimizer(barrier_ctrl);
-
- // loop over all of in_ctrl usages and move to barrier_ctrl
- for (DUIterator_Last imin, i = in_ctrl->last_outs(imin); i >= imin; --i) {
- Node *use = in_ctrl->last_out(i);
- uint l;
- for (l = 0; use->in(l) != in_ctrl; l++) {}
- igvn.replace_input_of(use, l, barrier_ctrl);
- }
-
- load->set_req(MemNode::Control, in_ctrl);
- barrier->set_req(LoadBarrierNode::Control, in_ctrl);
- zclone->add_req(barrier_val); // add req as keep alive.
-
- C->print_method(PHASE_ADD_UNSAFE_BARRIER, 4, zclone->_idx);
- }
-}
-
-void ZBarrierSetC2::insert_barriers_on_unsafe(PhaseIdealLoop* phase) const {
- Compile *C = phase->C;
- PhaseIterGVN &igvn = phase->igvn();
- uint new_ids = C->unique();
- VectorSet visited(Thread::current()->resource_area());
- GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
- nodeStack.push(C->root());
- visited.test_set(C->root()->_idx);
-
- // Traverse all nodes, visit all unsafe ops that require a barrier
- while (nodeStack.length() > 0) {
- Node *n = nodeStack.pop();
-
- bool is_old_node = (n->_idx < new_ids); // don't process nodes that were created during cleanup
- if (is_old_node) {
- if (n->is_LoadStore()) {
- LoadStoreNode* lsn = n->as_LoadStore();
- if (lsn->has_barrier()) {
- BasicType bt = lsn->in(MemNode::Address)->bottom_type()->basic_type();
- assert (is_reference_type(bt), "Sanity test");
- insert_barrier_before_unsafe(phase, lsn);
- }
- }
- }
- for (uint i = 0; i < n->len(); i++) {
- if (n->in(i)) {
- if (!visited.test_set(n->in(i)->_idx)) {
- nodeStack.push(n->in(i));
- }
- }
- }
- }
-
- igvn.optimize();
- C->print_method(PHASE_ADD_UNSAFE_BARRIER, 2);
-}
-
-// The purpose of ZBarrierSetC2::clean_catch_blocks is to prepare the IR for
-// splicing in load barrier nodes.
-//
-// The problem is that we might have instructions between a call and its catch nodes.
-// (This is usually handled in PhaseCFG:call_catch_cleanup, which clones mach nodes in
-// already scheduled blocks.) We can't have loads that require barriers there,
-// because we need to splice in new control flow, and that would violate the IR.
-//
-// clean_catch_blocks find all Loads that require a barrier and clone them and any
-// dependent instructions to each use. The loads must be in the beginning of the catch block
-// before any store.
-//
-// Sometimes the loads use will be at a place dominated by all catch blocks, then we need
-// a load in each catch block, and a Phi at the dominated use.
-
-void ZBarrierSetC2::clean_catch_blocks(PhaseIdealLoop* phase, bool verify) const {
-
- Compile *C = phase->C;
- uint new_ids = C->unique();
- PhaseIterGVN &igvn = phase->igvn();
- VectorSet visited(Thread::current()->resource_area());
- GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
- nodeStack.push(C->root());
- visited.test_set(C->root()->_idx);
-
- // Traverse all nodes, visit all loads that require a barrier
- while(nodeStack.length() > 0) {
- Node *n = nodeStack.pop();
-
- for (uint i = 0; i < n->len(); i++) {
- if (n->in(i)) {
- if (!visited.test_set(n->in(i)->_idx)) {
- nodeStack.push(n->in(i));
- }
+ // If this node tracks liveness, update it
+ RegMask* const regs = barrier_set_state()->live(node);
+ if (regs != NULL) {
+ regs->OR(new_live);
}
}
- bool is_old_node = (n->_idx < new_ids); // don't process nodes that were created during cleanup
- if (n->is_Load() && is_old_node) {
- LoadNode* load = n->isa_Load();
- // only care about loads that will have a barrier
- if (load_require_barrier(load)) {
- process_catch_cleanup_candidate(phase, load, verify);
- }
- }
- }
-
- C->print_method(PHASE_CALL_CATCH_CLEANUP, 2);
-}
-
-class DomDepthCompareClosure : public CompareClosure<LoadNode*> {
- PhaseIdealLoop* _phase;
-
-public:
- DomDepthCompareClosure(PhaseIdealLoop* phase) : _phase(phase) { }
-
- int do_compare(LoadNode* const &n1, LoadNode* const &n2) {
- int d1 = _phase->dom_depth(_phase->get_ctrl(n1));
- int d2 = _phase->dom_depth(_phase->get_ctrl(n2));
- if (d1 == d2) {
- // Compare index if the depth is the same, ensures all entries are unique.
- return n1->_idx - n2->_idx;
- } else {
- return d2 - d1;
- }
- }
-};
-
-// Traverse graph and add all loadPs to list, sorted by dom depth
-void gather_loadnodes_sorted(PhaseIdealLoop* phase, GrowableArray<LoadNode*>* loadList) {
-
- VectorSet visited(Thread::current()->resource_area());
- GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
- DomDepthCompareClosure ddcc(phase);
-
- nodeStack.push(phase->C->root());
- while(nodeStack.length() > 0) {
- Node *n = nodeStack.pop();
- if (visited.test(n->_idx)) {
- continue;
- }
-
- if (n->isa_Load()) {
- LoadNode *load = n->as_Load();
- if (load_require_barrier(load)) {
- assert(phase->get_ctrl(load) != NULL, "sanity");
- assert(phase->dom_depth(phase->get_ctrl(load)) != 0, "sanity");
- loadList->insert_sorted(&ddcc, load);
- }
- }
-
- visited.set(n->_idx);
- for (uint i = 0; i < n->req(); i++) {
- if (n->in(i)) {
- if (!visited.test(n->in(i)->_idx)) {
- nodeStack.push(n->in(i));
- }
+ // Now at block top, see if we have any changes
+ new_live.SUBTRACT(old_live);
+ if (new_live.is_NotEmpty()) {
+ // Liveness has refined, update and propagate to prior blocks
+ old_live.OR(new_live);
+ for (uint i = 1; i < block->num_preds(); ++i) {
+ Block* const pred = cfg->get_block_for_node(block->pred(i));
+ worklist.push(pred);
}
}
}
}
-
-// Add LoadBarriers to all LoadPs
-void ZBarrierSetC2::insert_load_barriers(PhaseIdealLoop* phase) const {
-
- bool trace = phase->C->directive()->ZTraceLoadBarriersOption;
- GrowableArray<LoadNode *> loadList(Thread::current()->resource_area(), 0, 0, NULL);
- gather_loadnodes_sorted(phase, &loadList);
-
- PhaseIterGVN &igvn = phase->igvn();
- int count = 0;
-
- for (GrowableArrayIterator<LoadNode *> loadIter = loadList.begin(); loadIter != loadList.end(); ++loadIter) {
- LoadNode *load = *loadIter;
-
- if (load_has_expanded_barrier(load)) {
- continue;
- }
-
- do {
- // Insert a barrier on a loadP
- // if another load is found that needs to be expanded first, retry on that one
- LoadNode* result = insert_one_loadbarrier(phase, load, phase->get_ctrl(load));
- while (result != NULL) {
- result = insert_one_loadbarrier(phase, result, phase->get_ctrl(result));
- }
- } while (!load_has_expanded_barrier(load));
- }
-
- phase->C->print_method(PHASE_INSERT_BARRIER, 2);
-}
-
-void push_antidependent_stores(PhaseIdealLoop* phase, Node_Stack& nodestack, LoadNode* start_load) {
- // push all stores on the same mem, that can_alias
- // Any load found must be handled first
- PhaseIterGVN &igvn = phase->igvn();
- int load_alias_idx = igvn.C->get_alias_index(start_load->adr_type());
-
- Node *mem = start_load->in(1);
- for (DUIterator_Fast imax, u = mem->fast_outs(imax); u < imax; u++) {
- Node *mem_use = mem->fast_out(u);
-
- if (mem_use == start_load) continue;
- if (!mem_use->is_Store()) continue;
- if (!phase->has_ctrl(mem_use)) continue;
- if (phase->get_ctrl(mem_use) != phase->get_ctrl(start_load)) continue;
-
- // add any aliasing store in this block
- StoreNode *store = mem_use->isa_Store();
- const TypePtr *adr_type = store->adr_type();
- if (igvn.C->can_alias(adr_type, load_alias_idx)) {
- nodestack.push(store, 0);
- }
- }
-}
-
-LoadNode* ZBarrierSetC2::insert_one_loadbarrier(PhaseIdealLoop* phase, LoadNode* start_load, Node* ctrl) const {
- bool trace = phase->C->directive()->ZTraceLoadBarriersOption;
- PhaseIterGVN &igvn = phase->igvn();
-
- // Check for other loadPs at the same loop depth that is reachable by a DFS
- // - if found - return it. It needs to be inserted first
- // - otherwise proceed and insert barrier
-
- VectorSet visited(Thread::current()->resource_area());
- Node_Stack nodestack(100);
-
- nodestack.push(start_load, 0);
- push_antidependent_stores(phase, nodestack, start_load);
-
- while(!nodestack.is_empty()) {
- Node* n = nodestack.node(); // peek
- nodestack.pop();
- if (visited.test(n->_idx)) {
- continue;
- }
-
- if (n->is_Load() && n != start_load && load_require_barrier(n->as_Load()) && !load_has_expanded_barrier(n->as_Load())) {
- // Found another load that needs a barrier in the same block. Must expand later loads first.
- if (trace) tty->print_cr(" * Found LoadP %i on DFS", n->_idx);
- return n->as_Load(); // return node that should be expanded first
- }
-
- if (!phase->has_ctrl(n)) continue;
- if (phase->get_ctrl(n) != phase->get_ctrl(start_load)) continue;
- if (n->is_Phi()) continue;
-
- visited.set(n->_idx);
- // push all children
- for (DUIterator_Fast imax, ii = n->fast_outs(imax); ii < imax; ii++) {
- Node* c = n->fast_out(ii);
- if (c != NULL) {
- nodestack.push(c, 0);
- }
- }
- }
-
- insert_one_loadbarrier_inner(phase, start_load, ctrl, visited);
- return NULL;
-}
-
-void ZBarrierSetC2::insert_one_loadbarrier_inner(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl, VectorSet visited2) const {
- PhaseIterGVN &igvn = phase->igvn();
- Compile* C = igvn.C;
- bool trace = C->directive()->ZTraceLoadBarriersOption;
-
- // create barrier
- Node* barrier = new LoadBarrierNode(C, NULL, load->in(LoadNode::Memory), NULL, load->in(LoadNode::Address), load_has_weak_barrier(load));
- Node* barrier_val = new ProjNode(barrier, LoadBarrierNode::Oop);
- Node* barrier_ctrl = new ProjNode(barrier, LoadBarrierNode::Control);
- ctrl = normalize_ctrl(ctrl);
-
- if (trace) tty->print_cr("Insert load %i with barrier: %i and ctrl : %i", load->_idx, barrier->_idx, ctrl->_idx);
-
- // Splice control
- // - insert barrier control diamond between loads ctrl and ctrl successor on path to block end.
- // - If control successor is a catch, step over to next.
- Node* ctrl_succ = NULL;
- for (DUIterator_Fast imax, j = ctrl->fast_outs(imax); j < imax; j++) {
- Node* tmp = ctrl->fast_out(j);
-
- // - CFG nodes is the ones we are going to splice (1 only!)
- // - Phi nodes will continue to hang from the region node!
- // - self loops should be skipped
- if (tmp->is_Phi() || tmp == ctrl) {
- continue;
- }
-
- if (tmp->is_CFG()) {
- assert(ctrl_succ == NULL, "There can be only one");
- ctrl_succ = tmp;
- continue;
- }
- }
-
- // Now splice control
- assert(ctrl_succ != load, "sanity");
- assert(ctrl_succ != NULL, "Broken IR");
- bool found = false;
- for(uint k = 0; k < ctrl_succ->req(); k++) {
- if (ctrl_succ->in(k) == ctrl) {
- assert(!found, "sanity");
- if (trace) tty->print_cr(" Move CFG ctrl_succ %i to barrier_ctrl", ctrl_succ->_idx);
- igvn.replace_input_of(ctrl_succ, k, barrier_ctrl);
- found = true;
- k--;
- }
- }
-
- // For all successors of ctrl - move all visited to become successors of barrier_ctrl instead
- for (DUIterator_Fast imax, r = ctrl->fast_outs(imax); r < imax; r++) {
- Node* tmp = ctrl->fast_out(r);
- if (tmp->is_SafePoint() || (visited2.test(tmp->_idx) && (tmp != load))) {
- if (trace) tty->print_cr(" Move ctrl_succ %i to barrier_ctrl", tmp->_idx);
- igvn.replace_input_of(tmp, 0, barrier_ctrl);
- --r; --imax;
- }
- }
-
- // Move the loads user to the barrier
- for (DUIterator_Fast imax, i = load->fast_outs(imax); i < imax; i++) {
- Node* u = load->fast_out(i);
- if (u->isa_LoadBarrier()) {
- continue;
- }
-
- // find correct input - replace with iterator?
- for(uint j = 0; j < u->req(); j++) {
- if (u->in(j) == load) {
- igvn.replace_input_of(u, j, barrier_val);
- --i; --imax; // Adjust the iterator of the *outer* loop
- break; // some nodes (calls) might have several uses from the same node
- }
- }
- }
-
- // Connect barrier to load and control
- barrier->set_req(LoadBarrierNode::Oop, load);
- barrier->set_req(LoadBarrierNode::Control, ctrl);
-
- igvn.replace_input_of(load, MemNode::Control, ctrl);
- load->pin();
-
- igvn.rehash_node_delayed(load);
- igvn.register_new_node_with_optimizer(barrier);
- igvn.register_new_node_with_optimizer(barrier_val);
- igvn.register_new_node_with_optimizer(barrier_ctrl);
- load_set_expanded_barrier(load);
-
- C->print_method(PHASE_INSERT_BARRIER, 3, load->_idx);
-}
-
-// The bad_mask in the ThreadLocalData shouldn't have an anti-dep-check.
-// The bad_mask address if of type TypeRawPtr, but that will alias
-// InitializeNodes until the type system is expanded.
-bool ZBarrierSetC2::needs_anti_dependence_check(const Node* node) const {
- MachNode* mnode = node->as_Mach();
- if (mnode != NULL) {
- intptr_t offset = 0;
- const TypePtr *adr_type2 = NULL;
- const Node* base = mnode->get_base_and_disp(offset, adr_type2);
- if ((base != NULL) &&
- (base->is_Mach() && base->as_Mach()->ideal_Opcode() == Op_ThreadLocal) &&
- (offset == in_bytes(ZThreadLocalData::address_bad_mask_offset()))) {
- return false;
- }
- }
- return true;
-}
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -29,134 +29,38 @@
#include "opto/node.hpp"
#include "utilities/growableArray.hpp"
-class ZCompareAndSwapPNode : public CompareAndSwapPNode {
-public:
- ZCompareAndSwapPNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapPNode(c, mem, adr, val, ex, mem_ord) { }
- virtual int Opcode() const;
-};
-
-class ZWeakCompareAndSwapPNode : public WeakCompareAndSwapPNode {
-public:
- ZWeakCompareAndSwapPNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : WeakCompareAndSwapPNode(c, mem, adr, val, ex, mem_ord) { }
- virtual int Opcode() const;
-};
+const uint8_t ZLoadBarrierStrong = 1;
+const uint8_t ZLoadBarrierWeak = 2;
+const uint8_t ZLoadBarrierElided = 3;
-class ZCompareAndExchangePNode : public CompareAndExchangePNode {
-public:
- ZCompareAndExchangePNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangePNode(c, mem, adr, val, ex, at, t, mem_ord) { }
- virtual int Opcode() const;
-};
+class ZLoadBarrierStubC2 : public ResourceObj {
+private:
+ const MachNode* _node;
+ const Address _ref_addr;
+ const Register _ref;
+ const Register _tmp;
+ const bool _weak;
+ Label _entry;
+ Label _continuation;
-class ZGetAndSetPNode : public GetAndSetPNode {
-public:
- ZGetAndSetPNode(Node* c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* t) : GetAndSetPNode(c, mem, adr, val, at, t) { }
- virtual int Opcode() const;
-};
-
-class LoadBarrierNode : public MultiNode {
-private:
- bool _weak; // On strong or weak oop reference
- static bool is_dominator(PhaseIdealLoop* phase, bool linear_only, Node *d, Node *n);
- void push_dominated_barriers(PhaseIterGVN* igvn) const;
+ ZLoadBarrierStubC2(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak);
public:
- enum {
- Control,
- Memory,
- Oop,
- Address,
- Number_of_Outputs = Address,
- Similar,
- Number_of_Inputs
- };
-
- LoadBarrierNode(Compile* C,
- Node* c,
- Node* mem,
- Node* val,
- Node* adr,
- bool weak);
-
- virtual int Opcode() const;
- virtual uint size_of() const;
- virtual bool cmp(const Node& n) const;
- virtual const Type *bottom_type() const;
- virtual const TypePtr* adr_type() const;
- virtual const Type *Value(PhaseGVN *phase) const;
- virtual Node *Identity(PhaseGVN *phase);
- virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
- virtual uint match_edge(uint idx) const;
-
- LoadBarrierNode* has_dominating_barrier(PhaseIdealLoop* phase,
- bool linear_only,
- bool look_for_similar);
-
- void fix_similar_in_uses(PhaseIterGVN* igvn);
-
- bool has_true_uses() const;
-
- bool can_be_eliminated() const {
- return !in(Similar)->is_top();
- }
-
- bool is_weak() const {
- return _weak;
- }
-};
+ static ZLoadBarrierStubC2* create(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak);
-class LoadBarrierSlowRegNode : public TypeNode {
-private:
- bool _is_weak;
-public:
- LoadBarrierSlowRegNode(Node *c,
- Node *adr,
- Node *src,
- const TypePtr* t,
- bool weak) :
- TypeNode(t, 3), _is_weak(weak) {
- init_req(1, adr);
- init_req(2, src);
- init_class_id(Class_LoadBarrierSlowReg);
- }
-
- virtual uint size_of() const {
- return sizeof(*this);
- }
-
- virtual const char * name() {
- return "LoadBarrierSlowRegNode";
- }
-
- virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) {
- return NULL;
- }
-
- virtual int Opcode() const;
-
- bool is_weak() { return _is_weak; }
-};
-
-class ZBarrierSetC2State : public ResourceObj {
-private:
- // List of load barrier nodes which need to be expanded before matching
- GrowableArray<LoadBarrierNode*>* _load_barrier_nodes;
-
-public:
- ZBarrierSetC2State(Arena* comp_arena);
- int load_barrier_count() const;
- void add_load_barrier_node(LoadBarrierNode* n);
- void remove_load_barrier_node(LoadBarrierNode* n);
- LoadBarrierNode* load_barrier_node(int idx) const;
+ Address ref_addr() const;
+ Register ref() const;
+ Register tmp() const;
+ address slow_path() const;
+ RegMask& live() const;
+ Label* entry();
+ Label* continuation();
};
class ZBarrierSetC2 : public BarrierSetC2 {
private:
- ZBarrierSetC2State* state() const;
- void expand_loadbarrier_node(PhaseMacroExpand* phase, LoadBarrierNode* barrier) const;
-
-#ifdef ASSERT
- void verify_gc_barriers(bool post_parse) const;
-#endif
+ void compute_liveness_at_stubs() const;
+ void analyze_dominating_barriers() const;
protected:
virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const;
@@ -174,43 +78,14 @@
public:
virtual void* create_barrier_state(Arena* comp_arena) const;
-
- virtual bool has_load_barriers() const { return true; }
- virtual bool is_gc_barrier_node(Node* node) const;
- virtual Node* step_over_gc_barrier(Node* c) const;
- virtual Node* step_over_gc_barrier_ctrl(Node* c) const;
-
- virtual void register_potential_barrier_node(Node* node) const;
- virtual void unregister_potential_barrier_node(Node* node) const;
- virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { }
- virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const;
- virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const;
-
- virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const;
+ virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc,
+ BasicType type,
+ bool is_clone,
+ ArrayCopyPhase phase) const;
- virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const;
- virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode) const;
- virtual bool matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const;
- virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const;
- virtual bool needs_anti_dependence_check(const Node* node) const;
-
-#ifdef ASSERT
- virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const;
-#endif
-
- // Load barrier insertion and expansion external
- virtual void barrier_insertion_phase(Compile* C, PhaseIterGVN &igvn) const;
- virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const;
- virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return (mode == LoopOptsZBarrierInsertion); }
- virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return mode == LoopOptsZBarrierInsertion; }
-
-private:
- // Load barrier insertion and expansion internal
- void insert_barriers_on_unsafe(PhaseIdealLoop* phase) const;
- void clean_catch_blocks(PhaseIdealLoop* phase, bool verify = false) const;
- void insert_load_barriers(PhaseIdealLoop* phase) const;
- LoadNode* insert_one_loadbarrier(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl) const;
- void insert_one_loadbarrier_inner(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl, VectorSet visited) const;
+ virtual void late_barrier_analysis() const;
+ virtual int estimate_stub_size() const;
+ virtual void emit_stubs(CodeBuffer& cb) const;
};
#endif // SHARE_GC_Z_C2_ZBARRIERSETC2_HPP
--- a/src/hotspot/share/gc/z/zBarrierSetAssembler.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/gc/z/zBarrierSetAssembler.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,7 @@
#ifndef SHARE_GC_Z_ZBARRIERSETASSEMBLER_HPP
#define SHARE_GC_Z_ZBARRIERSETASSEMBLER_HPP
-#include "asm/macroAssembler.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
-#include "oops/accessDecorators.hpp"
-#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
class ZBarrierSetAssemblerBase : public BarrierSetAssembler {
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -390,6 +390,10 @@
Service_lock->unlock();
}
+ if (UseNotificationThread && Notification_lock->owned_by_self()) {
+ Notification_lock->unlock();
+ }
+
if (CodeCache_lock->owned_by_self()) {
CodeCache_lock->unlock();
}
--- a/src/hotspot/share/oops/klassVtable.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/oops/klassVtable.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -128,11 +128,6 @@
*vtable_length_ret = vtable_length;
}
-int klassVtable::index_of(Method* m, int len) const {
- assert(m->has_vtable_index(), "do not ask this of non-vtable methods");
- return m->vtable_index();
-}
-
// Copy super class's vtable to the first part (prefix) of this class's vtable,
// and return the number of entries copied. Expects that 'super' is the Java
// super class (arrays can have "array" super classes that must be skipped).
@@ -169,7 +164,6 @@
// Note: Arrays can have intermediate array supers. Use java_super to skip them.
InstanceKlass* super = _klass->java_super();
- int nofNewEntries = 0;
bool is_shared = _klass->is_shared();
@@ -1029,15 +1023,6 @@
}
#endif // INCLUDE_JVMTI
-// CDS/RedefineClasses support - clear vtables so they can be reinitialized
-void klassVtable::clear_vtable() {
- for (int i = 0; i < _length; i++) table()[i].clear();
-}
-
-bool klassVtable::is_initialized() {
- return _length == 0 || table()[0].method() != NULL;
-}
-
//-----------------------------------------------------------------------------------------
// Itable code
@@ -1468,31 +1453,6 @@
#endif
}
-
-// inverse to itable_index
-Method* klassItable::method_for_itable_index(InstanceKlass* intf, int itable_index) {
- assert(intf->is_interface(), "sanity check");
- assert(intf->verify_itable_index(itable_index), "");
- Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
-
- if (itable_index < 0 || itable_index >= method_count_for_interface(intf))
- return NULL; // help caller defend against bad indices
-
- int index = itable_index;
- Method* m = methods->at(index);
- int index2 = -1;
- while (!m->has_itable_index() ||
- (index2 = m->itable_index()) != itable_index) {
- assert(index2 < itable_index, "monotonic");
- if (++index == methods->length())
- return NULL;
- m = methods->at(index);
- }
- assert(m->itable_index() == itable_index, "correct inverse");
-
- return m;
-}
-
void klassVtable::verify(outputStream* st, bool forced) {
// make sure table is initialized
if (!Universe::is_fully_initialized()) return;
--- a/src/hotspot/share/oops/klassVtable.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/oops/klassVtable.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -48,13 +48,6 @@
int _verify_count; // to make verify faster
#endif
- // Ordering important, so greater_than (>) can be used as an merge operator.
- enum AccessType {
- acc_private = 0,
- acc_package_private = 1,
- acc_publicprotected = 2
- };
-
public:
klassVtable(Klass* klass, void* base, int length) : _klass(klass) {
_tableOffset = (address)base - (address)klass; _length = length;
@@ -66,22 +59,12 @@
int length() const { return _length; }
inline Method* method_at(int i) const;
inline Method* unchecked_method_at(int i) const;
- inline Method** adr_method_at(int i) const;
// searching; all methods return -1 if not found
- int index_of(Method* m) const { return index_of(m, _length); }
int index_of_miranda(Symbol* name, Symbol* signature);
void initialize_vtable(bool checkconstraints, TRAPS); // initialize vtable of a new klass
- // CDS/RedefineClasses support - clear vtables so they can be reinitialized
- // at dump time. Clearing gives us an easy way to tell if the vtable has
- // already been reinitialized at dump time (see dump.cpp). Vtables can
- // be initialized at run time by RedefineClasses so dumping the right order
- // is necessary.
- void clear_vtable();
- bool is_initialized();
-
// computes vtable length (in words) and the number of miranda methods
static void compute_vtable_size_and_num_mirandas(int* vtable_length,
int* num_new_mirandas,
@@ -125,7 +108,6 @@
private:
void copy_vtable_to(vtableEntry* start);
int initialize_from_super(Klass* super);
- int index_of(Method* m, int len) const; // same as index_of, but search only up to len
void put_method_at(Method* m, int index);
static bool needs_new_vtable_entry(const methodHandle& m,
const Klass* super,
@@ -223,12 +205,6 @@
return table()[i].method();
}
-inline Method** klassVtable::adr_method_at(int i) const {
- // Allow one past the last entry to be referenced; useful for loop bounds.
- assert(i >= 0 && i <= _length, "index out of bounds");
- return (Method**)(address(table() + i) + vtableEntry::method_offset_in_bytes());
-}
-
// --------------------------------------------------------------------------------
class klassItable;
class itableMethodEntry;
@@ -333,9 +309,6 @@
static int compute_itable_size(Array<InstanceKlass*>* transitive_interfaces);
static void setup_itable_offset_table(InstanceKlass* klass);
- // Resolving of method to index
- static Method* method_for_itable_index(InstanceKlass* klass, int itable_index);
-
// Debugging/Statistics
static void print_statistics() PRODUCT_RETURN;
private:
--- a/src/hotspot/share/opto/c2compiler.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/c2compiler.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -102,7 +102,8 @@
assert(is_initialized(), "Compiler thread must be initialized");
bool subsume_loads = SubsumeLoads;
- bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
+ bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables()
+ && !env->jvmti_can_get_owned_monitor_info();
bool eliminate_boxing = EliminateAutoBox;
while (!env->failing()) {
--- a/src/hotspot/share/opto/classes.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/classes.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -48,9 +48,6 @@
#include "opto/subnode.hpp"
#include "opto/vectornode.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_ZGC
-#include "gc/z/c2/zBarrierSetC2.hpp"
-#endif
#if INCLUDE_SHENANDOAHGC
#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
#endif
--- a/src/hotspot/share/opto/classes.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/classes.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -193,17 +193,6 @@
macro(LoadN)
macro(LoadRange)
macro(LoadS)
-#if INCLUDE_ZGC
-#define zgcmacro(x) macro(x)
-#else
-#define zgcmacro(x) optionalmacro(x)
-#endif
-zgcmacro(LoadBarrier)
-zgcmacro(LoadBarrierSlowReg)
-zgcmacro(ZCompareAndSwapP)
-zgcmacro(ZWeakCompareAndSwapP)
-zgcmacro(ZCompareAndExchangeP)
-zgcmacro(ZGetAndSetP)
macro(Lock)
macro(Loop)
macro(LoopLimit)
--- a/src/hotspot/share/opto/compile.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/compile.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -76,9 +76,6 @@
#include "utilities/align.hpp"
#include "utilities/copy.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_ZGC
-#include "gc/z/c2/zBarrierSetC2.hpp"
-#endif
// -------------------- Compile::mach_constant_base_node -----------------------
@@ -990,6 +987,7 @@
_has_method_handle_invokes(false),
_clinit_barrier_on_entry(false),
_comp_arena(mtCompiler),
+ _barrier_set_state(BarrierSet::barrier_set()->barrier_set_c2()->create_barrier_state(comp_arena())),
_env(ci_env),
_directive(directive),
_log(ci_env->log()),
@@ -2412,13 +2410,6 @@
print_method(PHASE_MACRO_EXPANSION, 2);
}
-#ifdef ASSERT
- bs->verify_gc_barriers(this, BarrierSetC2::BeforeLateInsertion);
-#endif
-
- bs->barrier_insertion_phase(C, igvn);
- if (failing()) return;
-
{
TracePhase tp("barrierExpand", &timers[_t_barrierExpand]);
if (bs->expand_barriers(this, igvn)) {
--- a/src/hotspot/share/opto/compile.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/compile.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -55,7 +55,6 @@
class IdealGraphPrinter;
class InlineTree;
class Int_Array;
-class LoadBarrierNode;
class Matcher;
class MachConstantNode;
class MachConstantBaseNode;
@@ -96,7 +95,6 @@
LoopOptsNone,
LoopOptsShenandoahExpand,
LoopOptsShenandoahPostExpand,
- LoopOptsZBarrierInsertion,
LoopOptsSkipSplitIf,
LoopOptsVerify
};
@@ -1186,11 +1184,7 @@
bool in_scratch_emit_size() const { return _in_scratch_emit_size; }
enum ScratchBufferBlob {
-#if defined(PPC64)
MAX_inst_size = 2048,
-#else
- MAX_inst_size = 1024,
-#endif
MAX_locs_size = 128, // number of relocInfo elements
MAX_const_size = 128,
MAX_stubs_size = 128
@@ -1265,14 +1259,30 @@
// Process an OopMap Element while emitting nodes
void Process_OopMap_Node(MachNode *mach, int code_offset);
+ class BufferSizingData {
+ public:
+ int _stub;
+ int _code;
+ int _const;
+ int _reloc;
+
+ BufferSizingData() :
+ _stub(0),
+ _code(0),
+ _const(0),
+ _reloc(0)
+ { };
+ };
+
// Initialize code buffer
- CodeBuffer* init_buffer(uint* blk_starts);
+ void estimate_buffer_size(int& const_req);
+ CodeBuffer* init_buffer(BufferSizingData& buf_sizes);
// Write out basic block data to code buffer
void fill_buffer(CodeBuffer* cb, uint* blk_starts);
// Determine which variable sized branches can be shortened
- void shorten_branches(uint* blk_starts, int& code_size, int& reloc_size, int& stub_size);
+ void shorten_branches(uint* blk_starts, BufferSizingData& buf_sizes);
// Compute the size of first NumberOfLoopInstrToAlign instructions
// at the head of a loop.
--- a/src/hotspot/share/opto/loopnode.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/loopnode.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -993,18 +993,6 @@
}
}
- if (UseZGC && !inner_out->in(0)->is_CountedLoopEnd()) {
- // In some very special cases there can be a load that has no other uses than the
- // counted loop safepoint. Then its loadbarrier will be placed between the inner
- // loop exit and the safepoint. This is very rare
-
- Node* ifnode = inner_out->in(1)->in(0);
- // Region->IfTrue->If == Region->Iffalse->If
- if (ifnode == inner_out->in(2)->in(0)) {
- inner_out = ifnode->in(0);
- }
- }
-
CountedLoopEndNode* cle = inner_out->in(0)->as_CountedLoopEnd();
assert(cle == inner->loopexit_or_null(), "mismatch");
bool has_skeleton = outer_le->in(1)->bottom_type()->singleton() && outer_le->in(1)->bottom_type()->is_int()->get_con() == 0;
--- a/src/hotspot/share/opto/loopopts.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/loopopts.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -41,9 +41,6 @@
#include "opto/rootnode.hpp"
#include "opto/subnode.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_ZGC
-#include "gc/z/c2/zBarrierSetC2.hpp"
-#endif
//=============================================================================
//------------------------------split_thru_phi---------------------------------
--- a/src/hotspot/share/opto/machnode.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/machnode.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -197,7 +197,7 @@
// ADLC inherit from this class.
class MachNode : public Node {
public:
- MachNode() : Node((uint)0), _num_opnds(0), _opnds(NULL) {
+ MachNode() : Node((uint)0), _barrier(0), _num_opnds(0), _opnds(NULL) {
init_class_id(Class_Mach);
}
// Required boilerplate
@@ -211,6 +211,9 @@
// no constant base node input.
virtual uint mach_constant_base_node_input() const { return (uint)-1; }
+ uint8_t barrier_data() const { return _barrier; }
+ void set_barrier_data(uint data) { _barrier = data; }
+
// Copy inputs and operands to new node of instruction.
// Called from cisc_version() and short_branch_version().
// !!!! The method's body is defined in ad_<arch>.cpp file.
@@ -255,6 +258,9 @@
// output have choices - but they must use the same choice.
virtual uint two_adr( ) const { return 0; }
+ // The GC might require some barrier metadata for machine code emission.
+ uint8_t _barrier;
+
// Array of complex operand pointers. Each corresponds to zero or
// more leafs. Must be set by MachNode constructor to point to an
// internal array of MachOpers. The MachOper array is sized by
--- a/src/hotspot/share/opto/matcher.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/matcher.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1751,6 +1751,13 @@
_shared_nodes.map(leaf->_idx, ex);
}
+ // Have mach nodes inherit GC barrier data
+ if (leaf->is_LoadStore()) {
+ mach->set_barrier_data(leaf->as_LoadStore()->barrier_data());
+ } else if (leaf->is_Mem()) {
+ mach->set_barrier_data(leaf->as_Mem()->barrier_data());
+ }
+
return ex;
}
--- a/src/hotspot/share/opto/memnode.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/memnode.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -49,9 +49,6 @@
#include "utilities/copy.hpp"
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
-#if INCLUDE_ZGC
-#include "gc/z/c2/zBarrierSetC2.hpp"
-#endif
// Portions of code courtesy of Clifford Click
@@ -2851,7 +2848,7 @@
: Node(required),
_type(rt),
_adr_type(at),
- _has_barrier(false)
+ _barrier(0)
{
init_req(MemNode::Control, c );
init_req(MemNode::Memory , mem);
--- a/src/hotspot/share/opto/memnode.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/memnode.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -43,6 +43,8 @@
bool _unaligned_access; // Unaligned access from unsafe
bool _mismatched_access; // Mismatched access from unsafe: byte read in integer array for instance
bool _unsafe_access; // Access of unsafe origin.
+ uint8_t _barrier; // Bit field with barrier information
+
protected:
#ifdef ASSERT
const TypePtr* _adr_type; // What kind of memory is being addressed?
@@ -62,18 +64,30 @@
unset // The memory ordering is not set (used for testing)
} MemOrd;
protected:
- MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at )
- : Node(c0,c1,c2 ), _unaligned_access(false), _mismatched_access(false), _unsafe_access(false) {
+ MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at ) :
+ Node(c0,c1,c2),
+ _unaligned_access(false),
+ _mismatched_access(false),
+ _unsafe_access(false),
+ _barrier(0) {
init_class_id(Class_Mem);
debug_only(_adr_type=at; adr_type();)
}
- MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3 )
- : Node(c0,c1,c2,c3), _unaligned_access(false), _mismatched_access(false), _unsafe_access(false) {
+ MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3 ) :
+ Node(c0,c1,c2,c3),
+ _unaligned_access(false),
+ _mismatched_access(false),
+ _unsafe_access(false),
+ _barrier(0) {
init_class_id(Class_Mem);
debug_only(_adr_type=at; adr_type();)
}
- MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3, Node *c4)
- : Node(c0,c1,c2,c3,c4), _unaligned_access(false), _mismatched_access(false), _unsafe_access(false) {
+ MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3, Node *c4) :
+ Node(c0,c1,c2,c3,c4),
+ _unaligned_access(false),
+ _mismatched_access(false),
+ _unsafe_access(false),
+ _barrier(0) {
init_class_id(Class_Mem);
debug_only(_adr_type=at; adr_type();)
}
@@ -125,6 +139,9 @@
#endif
}
+ uint8_t barrier_data() { return _barrier; }
+ void set_barrier_data(uint8_t barrier_data) { _barrier = barrier_data; }
+
// Search through memory states which precede this node (load or store).
// Look for an exact match for the address, with no intervening
// aliased stores.
@@ -181,8 +198,6 @@
// this field.
const MemOrd _mo;
- uint _barrier; // Bit field with barrier information
-
AllocateNode* is_new_object_mark_load(PhaseGVN *phase) const;
protected:
@@ -196,7 +211,7 @@
public:
LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency)
- : MemNode(c,mem,adr,at), _control_dependency(control_dependency), _mo(mo), _barrier(0), _type(rt) {
+ : MemNode(c,mem,adr,at), _control_dependency(control_dependency), _mo(mo), _type(rt) {
init_class_id(Class_Load);
}
inline bool is_unordered() const { return !is_acquire(); }
@@ -265,10 +280,6 @@
Node* convert_to_unsigned_load(PhaseGVN& gvn);
Node* convert_to_signed_load(PhaseGVN& gvn);
- void copy_barrier_info(const Node* src) { _barrier = src->as_Load()->_barrier; }
- uint barrier_data() { return _barrier; }
- void set_barrier_data(uint barrier_data) { _barrier |= barrier_data; }
-
void pin() { _control_dependency = Pinned; }
bool has_unknown_control_dependency() const { return _control_dependency == UnknownControl; }
@@ -820,7 +831,7 @@
private:
const Type* const _type; // What kind of value is loaded?
const TypePtr* _adr_type; // What kind of memory is being addressed?
- bool _has_barrier;
+ uint8_t _barrier; // Bit field with barrier information
virtual uint size_of() const; // Size is bigger
public:
LoadStoreNode( Node *c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* rt, uint required );
@@ -833,8 +844,9 @@
bool result_not_used() const;
MemBarNode* trailing_membar() const;
- void set_has_barrier() { _has_barrier = true; };
- bool has_barrier() const { return _has_barrier; };
+
+ uint8_t barrier_data() { return _barrier; }
+ void set_barrier_data(uint8_t barrier_data) { _barrier = barrier_data; }
};
class LoadStoreConditionalNode : public LoadStoreNode {
@@ -886,6 +898,7 @@
MemNode::MemOrd order() const {
return _mem_ord;
}
+ virtual uint size_of() const { return sizeof(*this); }
};
class CompareAndExchangeNode : public LoadStoreNode {
@@ -903,6 +916,7 @@
MemNode::MemOrd order() const {
return _mem_ord;
}
+ virtual uint size_of() const { return sizeof(*this); }
};
//------------------------------CompareAndSwapBNode---------------------------
--- a/src/hotspot/share/opto/node.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/node.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -546,9 +546,6 @@
if (n->is_SafePoint()) {
n->as_SafePoint()->clone_replaced_nodes();
}
- if (n->is_Load()) {
- n->as_Load()->copy_barrier_info(this);
- }
return n; // Return the clone
}
@@ -1473,10 +1470,6 @@
if (req() < 2 || (_flags & Flag_needs_anti_dependence_check) == 0) {
return false;
}
- BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
- if (!bs->needs_anti_dependence_check(this)) {
- return false;
- }
return in(1)->bottom_type()->has_memory();
}
--- a/src/hotspot/share/opto/node.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/node.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -83,8 +83,6 @@
class JumpNode;
class JumpProjNode;
class LoadNode;
-class LoadBarrierNode;
-class LoadBarrierSlowRegNode;
class LoadStoreNode;
class LoadStoreConditionalNode;
class LockNode;
@@ -642,7 +640,6 @@
DEFINE_CLASS_ID(MemBar, Multi, 3)
DEFINE_CLASS_ID(Initialize, MemBar, 0)
DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1)
- DEFINE_CLASS_ID(LoadBarrier, Multi, 4)
DEFINE_CLASS_ID(Mach, Node, 1)
DEFINE_CLASS_ID(MachReturn, Mach, 0)
@@ -679,7 +676,6 @@
DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6)
DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0)
DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1)
- DEFINE_CLASS_ID(LoadBarrierSlowReg, Type, 7)
DEFINE_CLASS_ID(Proj, Node, 3)
DEFINE_CLASS_ID(CatchProj, Proj, 0)
@@ -836,8 +832,6 @@
DEFINE_CLASS_QUERY(Load)
DEFINE_CLASS_QUERY(LoadStore)
DEFINE_CLASS_QUERY(LoadStoreConditional)
- DEFINE_CLASS_QUERY(LoadBarrier)
- DEFINE_CLASS_QUERY(LoadBarrierSlowReg)
DEFINE_CLASS_QUERY(Lock)
DEFINE_CLASS_QUERY(Loop)
DEFINE_CLASS_QUERY(Mach)
--- a/src/hotspot/share/opto/output.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/output.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -31,6 +31,8 @@
#include "compiler/compileBroker.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/oopMap.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/c2/barrierSetC2.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/ad.hpp"
#include "opto/callnode.hpp"
@@ -114,35 +116,33 @@
}
}
+ // Keeper of sizing aspects
+ BufferSizingData buf_sizes = BufferSizingData();
+
+ // Initialize code buffer
+ estimate_buffer_size(buf_sizes._const);
+ if (failing()) return;
+
+ // Pre-compute the length of blocks and replace
+ // long branches with short if machine supports it.
+ // Must be done before ScheduleAndBundle due to SPARC delay slots
uint* blk_starts = NEW_RESOURCE_ARRAY(uint, _cfg->number_of_blocks() + 1);
blk_starts[0] = 0;
-
- // Initialize code buffer and process short branches.
- CodeBuffer* cb = init_buffer(blk_starts);
-
- if (cb == NULL || failing()) {
- return;
- }
+ shorten_branches(blk_starts, buf_sizes);
ScheduleAndBundle();
-
-#ifndef PRODUCT
- if (trace_opto_output()) {
- tty->print("\n---- After ScheduleAndBundle ----\n");
- for (uint i = 0; i < _cfg->number_of_blocks(); i++) {
- tty->print("\nBB#%03d:\n", i);
- Block* block = _cfg->get_block(i);
- for (uint j = 0; j < block->number_of_nodes(); j++) {
- Node* n = block->get_node(j);
- OptoReg::Name reg = _regalloc->get_reg_first(n);
- tty->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : "");
- n->dump();
- }
- }
+ if (failing()) {
+ return;
}
-#endif
-
- if (failing()) {
+
+ // Late barrier analysis must be done after schedule and bundle
+ // Otherwise liveness based spilling will fail
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ bs->late_barrier_analysis();
+
+ // Complete sizing of codebuffer
+ CodeBuffer* cb = init_buffer(buf_sizes);
+ if (cb == NULL || failing()) {
return;
}
@@ -223,7 +223,7 @@
// The architecture description provides short branch variants for some long
// branch instructions. Replace eligible long branches with short branches.
-void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size, int& stub_size) {
+void Compile::shorten_branches(uint* blk_starts, BufferSizingData& buf_sizes) {
// Compute size of each block, method size, and relocation information size
uint nblocks = _cfg->number_of_blocks();
@@ -241,11 +241,11 @@
bool has_short_branch_candidate = false;
// Initialize the sizes to 0
- code_size = 0; // Size in bytes of generated code
- stub_size = 0; // Size in bytes of all stub entries
+ int code_size = 0; // Size in bytes of generated code
+ int stub_size = 0; // Size in bytes of all stub entries
// Size in bytes of all relocation entries, including those in local stubs.
// Start with 2-bytes of reloc info for the unvalidated entry point
- reloc_size = 1; // Number of relocation entries
+ int reloc_size = 1; // Number of relocation entries
// Make three passes. The first computes pessimistic blk_starts,
// relative jmp_offset and reloc_size information. The second performs
@@ -479,6 +479,10 @@
// a relocation index.
// The CodeBuffer will expand the locs array if this estimate is too low.
reloc_size *= 10 / sizeof(relocInfo);
+
+ buf_sizes._reloc = reloc_size;
+ buf_sizes._code = code_size;
+ buf_sizes._stub = stub_size;
}
//------------------------------FillLocArray-----------------------------------
@@ -490,8 +494,8 @@
// This should never have accepted Bad before
assert(OptoReg::is_valid(regnum), "location must be valid");
return (OptoReg::is_reg(regnum))
- ? new LocationValue(Location::new_reg_loc(l_type, OptoReg::as_VMReg(regnum)) )
- : new LocationValue(Location::new_stk_loc(l_type, ra->reg2offset(regnum)));
+ ? new LocationValue(Location::new_reg_loc(l_type, OptoReg::as_VMReg(regnum)) )
+ : new LocationValue(Location::new_stk_loc(l_type, ra->reg2offset(regnum)));
}
@@ -610,12 +614,12 @@
}
#endif //_LP64
else if( (t->base() == Type::FloatBot || t->base() == Type::FloatCon) &&
- OptoReg::is_reg(regnum) ) {
+ OptoReg::is_reg(regnum) ) {
array->append(new_loc_value( _regalloc, regnum, Matcher::float_in_double()
- ? Location::float_in_dbl : Location::normal ));
+ ? Location::float_in_dbl : Location::normal ));
} else if( t->base() == Type::Int && OptoReg::is_reg(regnum) ) {
array->append(new_loc_value( _regalloc, regnum, Matcher::int_in_long
- ? Location::int_in_long : Location::normal ));
+ ? Location::int_in_long : Location::normal ));
} else if( t->base() == Type::NarrowOop ) {
array->append(new_loc_value( _regalloc, regnum, Location::narrowoop ));
} else {
@@ -626,48 +630,48 @@
// No register. It must be constant data.
switch (t->base()) {
- case Type::Half: // Second half of a double
- ShouldNotReachHere(); // Caller should skip 2nd halves
- break;
- case Type::AnyPtr:
- array->append(new ConstantOopWriteValue(NULL));
- break;
- case Type::AryPtr:
- case Type::InstPtr: // fall through
- array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->constant_encoding()));
- break;
- case Type::NarrowOop:
- if (t == TypeNarrowOop::NULL_PTR) {
+ case Type::Half: // Second half of a double
+ ShouldNotReachHere(); // Caller should skip 2nd halves
+ break;
+ case Type::AnyPtr:
array->append(new ConstantOopWriteValue(NULL));
- } else {
- array->append(new ConstantOopWriteValue(t->make_ptr()->isa_oopptr()->const_oop()->constant_encoding()));
+ break;
+ case Type::AryPtr:
+ case Type::InstPtr: // fall through
+ array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->constant_encoding()));
+ break;
+ case Type::NarrowOop:
+ if (t == TypeNarrowOop::NULL_PTR) {
+ array->append(new ConstantOopWriteValue(NULL));
+ } else {
+ array->append(new ConstantOopWriteValue(t->make_ptr()->isa_oopptr()->const_oop()->constant_encoding()));
+ }
+ break;
+ case Type::Int:
+ array->append(new ConstantIntValue(t->is_int()->get_con()));
+ break;
+ case Type::RawPtr:
+ // A return address (T_ADDRESS).
+ assert((intptr_t)t->is_ptr()->get_con() < (intptr_t)0x10000, "must be a valid BCI");
+#ifdef _LP64
+ // Must be restored to the full-width 64-bit stack slot.
+ array->append(new ConstantLongValue(t->is_ptr()->get_con()));
+#else
+ array->append(new ConstantIntValue(t->is_ptr()->get_con()));
+#endif
+ break;
+ case Type::FloatCon: {
+ float f = t->is_float_constant()->getf();
+ array->append(new ConstantIntValue(jint_cast(f)));
+ break;
}
- break;
- case Type::Int:
- array->append(new ConstantIntValue(t->is_int()->get_con()));
- break;
- case Type::RawPtr:
- // A return address (T_ADDRESS).
- assert((intptr_t)t->is_ptr()->get_con() < (intptr_t)0x10000, "must be a valid BCI");
+ case Type::DoubleCon: {
+ jdouble d = t->is_double_constant()->getd();
#ifdef _LP64
- // Must be restored to the full-width 64-bit stack slot.
- array->append(new ConstantLongValue(t->is_ptr()->get_con()));
+ array->append(new ConstantIntValue((jint)0));
+ array->append(new ConstantDoubleValue(d));
#else
- array->append(new ConstantIntValue(t->is_ptr()->get_con()));
-#endif
- break;
- case Type::FloatCon: {
- float f = t->is_float_constant()->getf();
- array->append(new ConstantIntValue(jint_cast(f)));
- break;
- }
- case Type::DoubleCon: {
- jdouble d = t->is_double_constant()->getd();
-#ifdef _LP64
- array->append(new ConstantIntValue((jint)0));
- array->append(new ConstantDoubleValue(d));
-#else
- // Repack the double as two jints.
+ // Repack the double as two jints.
// The convention the interpreter uses is that the second local
// holds the first raw word of the native double representation.
// This is actually reasonable, since locals and stack arrays
@@ -679,15 +683,15 @@
array->append(new ConstantIntValue(acc.words[1]));
array->append(new ConstantIntValue(acc.words[0]));
#endif
- break;
- }
- case Type::Long: {
- jlong d = t->is_long()->get_con();
+ break;
+ }
+ case Type::Long: {
+ jlong d = t->is_long()->get_con();
#ifdef _LP64
- array->append(new ConstantIntValue((jint)0));
- array->append(new ConstantLongValue(d));
+ array->append(new ConstantIntValue((jint)0));
+ array->append(new ConstantLongValue(d));
#else
- // Repack the long as two jints.
+ // Repack the long as two jints.
// The convention the interpreter uses is that the second local
// holds the first raw word of the native double representation.
// This is actually reasonable, since locals and stack arrays
@@ -699,14 +703,14 @@
array->append(new ConstantIntValue(acc.words[1]));
array->append(new ConstantIntValue(acc.words[0]));
#endif
- break;
- }
- case Type::Top: // Add an illegal value here
- array->append(new LocationValue(Location()));
- break;
- default:
- ShouldNotReachHere();
- break;
+ break;
+ }
+ case Type::Top: // Add an illegal value here
+ array->append(new LocationValue(Location()));
+ break;
+ default:
+ ShouldNotReachHere();
+ break;
}
}
@@ -871,58 +875,58 @@
// A simplified version of Process_OopMap_Node, to handle non-safepoints.
class NonSafepointEmitter {
- Compile* C;
- JVMState* _pending_jvms;
- int _pending_offset;
-
- void emit_non_safepoint();
+ Compile* C;
+ JVMState* _pending_jvms;
+ int _pending_offset;
+
+ void emit_non_safepoint();
public:
- NonSafepointEmitter(Compile* compile) {
- this->C = compile;
- _pending_jvms = NULL;
- _pending_offset = 0;
- }
-
- void observe_instruction(Node* n, int pc_offset) {
- if (!C->debug_info()->recording_non_safepoints()) return;
-
- Node_Notes* nn = C->node_notes_at(n->_idx);
- if (nn == NULL || nn->jvms() == NULL) return;
- if (_pending_jvms != NULL &&
- _pending_jvms->same_calls_as(nn->jvms())) {
- // Repeated JVMS? Stretch it up here.
- _pending_offset = pc_offset;
- } else {
+ NonSafepointEmitter(Compile* compile) {
+ this->C = compile;
+ _pending_jvms = NULL;
+ _pending_offset = 0;
+ }
+
+ void observe_instruction(Node* n, int pc_offset) {
+ if (!C->debug_info()->recording_non_safepoints()) return;
+
+ Node_Notes* nn = C->node_notes_at(n->_idx);
+ if (nn == NULL || nn->jvms() == NULL) return;
if (_pending_jvms != NULL &&
+ _pending_jvms->same_calls_as(nn->jvms())) {
+ // Repeated JVMS? Stretch it up here.
+ _pending_offset = pc_offset;
+ } else {
+ if (_pending_jvms != NULL &&
+ _pending_offset < pc_offset) {
+ emit_non_safepoint();
+ }
+ _pending_jvms = NULL;
+ if (pc_offset > C->debug_info()->last_pc_offset()) {
+ // This is the only way _pending_jvms can become non-NULL:
+ _pending_jvms = nn->jvms();
+ _pending_offset = pc_offset;
+ }
+ }
+ }
+
+ // Stay out of the way of real safepoints:
+ void observe_safepoint(JVMState* jvms, int pc_offset) {
+ if (_pending_jvms != NULL &&
+ !_pending_jvms->same_calls_as(jvms) &&
_pending_offset < pc_offset) {
emit_non_safepoint();
}
_pending_jvms = NULL;
- if (pc_offset > C->debug_info()->last_pc_offset()) {
- // This is the only way _pending_jvms can become non-NULL:
- _pending_jvms = nn->jvms();
- _pending_offset = pc_offset;
- }
}
- }
-
- // Stay out of the way of real safepoints:
- void observe_safepoint(JVMState* jvms, int pc_offset) {
- if (_pending_jvms != NULL &&
- !_pending_jvms->same_calls_as(jvms) &&
- _pending_offset < pc_offset) {
- emit_non_safepoint();
+
+ void flush_at_end() {
+ if (_pending_jvms != NULL) {
+ emit_non_safepoint();
+ }
+ _pending_jvms = NULL;
}
- _pending_jvms = NULL;
- }
-
- void flush_at_end() {
- if (_pending_jvms != NULL) {
- emit_non_safepoint();
- }
- _pending_jvms = NULL;
- }
};
void NonSafepointEmitter::emit_non_safepoint() {
@@ -952,15 +956,11 @@
}
//------------------------------init_buffer------------------------------------
-CodeBuffer* Compile::init_buffer(uint* blk_starts) {
+void Compile::estimate_buffer_size(int& const_req) {
// Set the initially allocated size
- int code_req = initial_code_capacity;
- int locs_req = initial_locs_capacity;
- int stub_req = initial_stub_capacity;
- int const_req = initial_const_capacity;
-
- int pad_req = NativeCall::instruction_size;
+ const_req = initial_const_capacity;
+
// The extra spacing after the code is necessary on some platforms.
// Sometimes we need to patch in a jump after the last instruction,
// if the nmethod has been deoptimized. (See 4932387, 4894843.)
@@ -972,7 +972,7 @@
// Compute prolog code size
_method_size = 0;
- _frame_slots = OptoReg::reg2stack(_matcher->_old_SP)+_regalloc->_framesize;
+ _frame_slots = OptoReg::reg2stack(_matcher->_old_SP) + _regalloc->_framesize;
#if defined(IA64) && !defined(AIX)
if (save_argument_registers()) {
// 4815101: this is a stub with implicit and unknown precision fp args.
@@ -1021,11 +1021,18 @@
// Initialize the space for the BufferBlob used to find and verify
// instruction size in MachNode::emit_size()
init_scratch_buffer_blob(const_req);
- if (failing()) return NULL; // Out of memory
-
- // Pre-compute the length of blocks and replace
- // long branches with short if machine supports it.
- shorten_branches(blk_starts, code_req, locs_req, stub_req);
+}
+
+CodeBuffer* Compile::init_buffer(BufferSizingData& buf_sizes) {
+
+ int stub_req = buf_sizes._stub;
+ int code_req = buf_sizes._code;
+ int const_req = buf_sizes._const;
+
+ int pad_req = NativeCall::instruction_size;
+
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ stub_req += bs->estimate_stub_size();
// nmethod and CodeBuffer count stubs & constants as part of method's code.
// class HandlerImpl is platform-specific and defined in the *.ad files.
@@ -1038,18 +1045,18 @@
code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10; // force expansion
int total_req =
- const_req +
- code_req +
- pad_req +
- stub_req +
- exception_handler_req +
- deopt_handler_req; // deopt handler
+ const_req +
+ code_req +
+ pad_req +
+ stub_req +
+ exception_handler_req +
+ deopt_handler_req; // deopt handler
if (has_method_handle_invokes())
total_req += deopt_handler_req; // deopt MH handler
CodeBuffer* cb = code_buffer();
- cb->initialize(total_req, locs_req);
+ cb->initialize(total_req, buf_sizes._reloc);
// Have we run out of code space?
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
@@ -1268,12 +1275,12 @@
Process_OopMap_Node(mach, current_offset);
} // End if safepoint
- // If this is a null check, then add the start of the previous instruction to the list
+ // If this is a null check, then add the start of the previous instruction to the list
else if( mach->is_MachNullCheck() ) {
inct_starts[inct_cnt++] = previous_offset;
}
- // If this is a branch, then fill in the label with the target BB's label
+ // If this is a branch, then fill in the label with the target BB's label
else if (mach->is_MachBranch()) {
// This requires the TRUE branch target be in succs[0]
uint block_num = block->non_connector_successor(0)->_pre_order;
@@ -1284,8 +1291,8 @@
bool delay_slot_is_used = valid_bundle_info(n) &&
node_bundling(n)->use_unconditional_delay();
if (!delay_slot_is_used && mach->may_be_short_branch()) {
- assert(delay_slot == NULL, "not expecting delay slot node");
- int br_size = n->size(_regalloc);
+ assert(delay_slot == NULL, "not expecting delay slot node");
+ int br_size = n->size(_regalloc);
int offset = blk_starts[block_num] - current_offset;
if (block_num >= i) {
// Current and following block's offset are not
@@ -1343,7 +1350,7 @@
}
}
#ifdef ASSERT
- // Check that oop-store precedes the card-mark
+ // Check that oop-store precedes the card-mark
else if (mach->ideal_Opcode() == Op_StoreCM) {
uint storeCM_idx = j;
int count = 0;
@@ -1514,6 +1521,10 @@
}
#endif
+ BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+ bs->emit_stubs(*cb);
+ if (failing()) return;
+
#ifndef PRODUCT
// Information on the size of the method, without the extraneous code
Scheduling::increment_method_size(cb->insts_size());
@@ -1688,20 +1699,20 @@
// Initializer for class Scheduling
Scheduling::Scheduling(Arena *arena, Compile &compile)
- : _arena(arena),
- _cfg(compile.cfg()),
- _regalloc(compile.regalloc()),
- _scheduled(arena),
- _available(arena),
- _reg_node(arena),
- _pinch_free_list(arena),
- _next_node(NULL),
- _bundle_instr_count(0),
- _bundle_cycle_number(0),
- _bundle_use(0, 0, resource_count, &_bundle_use_elements[0])
+ : _arena(arena),
+ _cfg(compile.cfg()),
+ _regalloc(compile.regalloc()),
+ _scheduled(arena),
+ _available(arena),
+ _reg_node(arena),
+ _pinch_free_list(arena),
+ _next_node(NULL),
+ _bundle_instr_count(0),
+ _bundle_cycle_number(0),
+ _bundle_use(0, 0, resource_count, &_bundle_use_elements[0])
#ifndef PRODUCT
- , _branches(0)
- , _unconditional_delays(0)
+ , _branches(0)
+ , _unconditional_delays(0)
#endif
{
// Create a MachNopNode
@@ -1782,8 +1793,8 @@
_bundle_use.reset();
memcpy(_bundle_use_elements,
- Pipeline_Use::elaborated_elements,
- sizeof(Pipeline_Use::elaborated_elements));
+ Pipeline_Use::elaborated_elements,
+ sizeof(Pipeline_Use::elaborated_elements));
}
// Perform instruction scheduling and bundling over the sequence of
@@ -1810,6 +1821,22 @@
// Walk backwards over each basic block, computing the needed alignment
// Walk over all the basic blocks
scheduling.DoScheduling();
+
+#ifndef PRODUCT
+ if (trace_opto_output()) {
+ tty->print("\n---- After ScheduleAndBundle ----\n");
+ for (uint i = 0; i < _cfg->number_of_blocks(); i++) {
+ tty->print("\nBB#%03d:\n", i);
+ Block* block = _cfg->get_block(i);
+ for (uint j = 0; j < block->number_of_nodes(); j++) {
+ Node* n = block->get_node(j);
+ OptoReg::Name reg = _regalloc->get_reg_first(n);
+ tty->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : "");
+ n->dump();
+ }
+ }
+ }
+#endif
}
// Compute the latency of all the instructions. This is fairly simple,
@@ -1878,7 +1905,7 @@
#ifndef PRODUCT
if (_cfg->C->trace_opto_output())
tty->print("# NodeFitsInBundle [%4d]: FALSE; latency %4d > %d\n",
- n->_idx, _current_latency[n_idx], _bundle_cycle_number);
+ n->_idx, _current_latency[n_idx], _bundle_cycle_number);
#endif
return (false);
}
@@ -1895,7 +1922,7 @@
#ifndef PRODUCT
if (_cfg->C->trace_opto_output())
tty->print("# NodeFitsInBundle [%4d]: FALSE; too many instructions: %d > %d\n",
- n->_idx, _bundle_instr_count + instruction_count, Pipeline::_max_instrs_per_cycle);
+ n->_idx, _bundle_instr_count + instruction_count, Pipeline::_max_instrs_per_cycle);
#endif
return (false);
}
@@ -2103,12 +2130,12 @@
// Don't allow safepoints in the branch shadow, that will
// cause a number of difficulties
if ( avail_pipeline->instructionCount() == 1 &&
- !avail_pipeline->hasMultipleBundles() &&
- !avail_pipeline->hasBranchDelay() &&
- Pipeline::instr_has_unit_size() &&
- d->size(_regalloc) == Pipeline::instr_unit_size() &&
- NodeFitsInBundle(d) &&
- !node_bundling(d)->used_in_delay()) {
+ !avail_pipeline->hasMultipleBundles() &&
+ !avail_pipeline->hasBranchDelay() &&
+ Pipeline::instr_has_unit_size() &&
+ d->size(_regalloc) == Pipeline::instr_unit_size() &&
+ NodeFitsInBundle(d) &&
+ !node_bundling(d)->used_in_delay()) {
if (d->is_Mach() && !d->is_MachSafePoint()) {
// A node that fits in the delay slot was found, so we need to
@@ -2153,13 +2180,13 @@
// step of the bundles
if (!NodeFitsInBundle(n)) {
#ifndef PRODUCT
- if (_cfg->C->trace_opto_output())
- tty->print("# *** STEP(branch won't fit) ***\n");
+ if (_cfg->C->trace_opto_output())
+ tty->print("# *** STEP(branch won't fit) ***\n");
#endif
- // Update the state information
- _bundle_instr_count = 0;
- _bundle_cycle_number += 1;
- _bundle_use.step(1);
+ // Update the state information
+ _bundle_instr_count = 0;
+ _bundle_cycle_number += 1;
+ _bundle_use.step(1);
}
}
@@ -2205,8 +2232,8 @@
#ifndef PRODUCT
if (_cfg->C->trace_opto_output())
tty->print("# *** STEP(%d >= %d instructions) ***\n",
- instruction_count + _bundle_instr_count,
- Pipeline::_max_instrs_per_cycle);
+ instruction_count + _bundle_instr_count,
+ Pipeline::_max_instrs_per_cycle);
#endif
step(1);
}
@@ -2412,7 +2439,7 @@
}
assert(!last->is_Mach() || last->as_Mach()->ideal_Opcode() != Op_Con, "");
if( last->is_Catch() ||
- (last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
+ (last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
// There might be a prior call. Skip it.
while (_bb_start < _bb_end && bb->get_node(--_bb_end)->is_MachProj());
} else if( last->is_MachNullCheck() ) {
@@ -2482,7 +2509,7 @@
}
#endif
#ifdef ASSERT
- verify_good_schedule(bb,"after block local scheduling");
+ verify_good_schedule(bb,"after block local scheduling");
#endif
}
@@ -2830,31 +2857,31 @@
//
void Scheduling::garbage_collect_pinch_nodes() {
#ifndef PRODUCT
- if (_cfg->C->trace_opto_output()) tty->print("Reclaimed pinch nodes:");
+ if (_cfg->C->trace_opto_output()) tty->print("Reclaimed pinch nodes:");
#endif
- int trace_cnt = 0;
- for (uint k = 0; k < _reg_node.Size(); k++) {
- Node* pinch = _reg_node[k];
- if ((pinch != NULL) && pinch->Opcode() == Op_Node &&
- // no predecence input edges
- (pinch->req() == pinch->len() || pinch->in(pinch->req()) == NULL) ) {
- cleanup_pinch(pinch);
- _pinch_free_list.push(pinch);
- _reg_node.map(k, NULL);
+ int trace_cnt = 0;
+ for (uint k = 0; k < _reg_node.Size(); k++) {
+ Node* pinch = _reg_node[k];
+ if ((pinch != NULL) && pinch->Opcode() == Op_Node &&
+ // no predecence input edges
+ (pinch->req() == pinch->len() || pinch->in(pinch->req()) == NULL) ) {
+ cleanup_pinch(pinch);
+ _pinch_free_list.push(pinch);
+ _reg_node.map(k, NULL);
#ifndef PRODUCT
- if (_cfg->C->trace_opto_output()) {
- trace_cnt++;
- if (trace_cnt > 40) {
- tty->print("\n");
- trace_cnt = 0;
- }
- tty->print(" %d", pinch->_idx);
+ if (_cfg->C->trace_opto_output()) {
+ trace_cnt++;
+ if (trace_cnt > 40) {
+ tty->print("\n");
+ trace_cnt = 0;
}
+ tty->print(" %d", pinch->_idx);
+ }
#endif
- }
}
+ }
#ifndef PRODUCT
- if (_cfg->C->trace_opto_output()) tty->print("\n");
+ if (_cfg->C->trace_opto_output()) tty->print("\n");
#endif
}
@@ -2891,19 +2918,19 @@
void Scheduling::print_statistics() {
// Print the size added by nops for bundling
tty->print("Nops added %d bytes to total of %d bytes",
- _total_nop_size, _total_method_size);
+ _total_nop_size, _total_method_size);
if (_total_method_size > 0)
tty->print(", for %.2f%%",
- ((double)_total_nop_size) / ((double) _total_method_size) * 100.0);
+ ((double)_total_nop_size) / ((double) _total_method_size) * 100.0);
tty->print("\n");
// Print the number of branch shadows filled
if (Pipeline::_branch_has_delay_slot) {
tty->print("Of %d branches, %d had unconditional delay slots filled",
- _total_branches, _total_unconditional_delays);
+ _total_branches, _total_unconditional_delays);
if (_total_branches > 0)
tty->print(", for %.2f%%",
- ((double)_total_unconditional_delays) / ((double)_total_branches) * 100.0);
+ ((double)_total_unconditional_delays) / ((double)_total_branches) * 100.0);
tty->print("\n");
}
@@ -2917,6 +2944,6 @@
if (total_bundles > 0)
tty->print("Average ILP (excluding nops) is %.2f\n",
- ((double)total_instructions) / ((double)total_bundles));
+ ((double)total_instructions) / ((double)total_bundles));
}
#endif
--- a/src/hotspot/share/opto/output.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/output.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -40,7 +40,6 @@
class PhaseChaitin;
class Pipeline_Use_Element;
class Pipeline_Use;
-
#ifndef PRODUCT
#define DEBUG_ARG(x) , x
#else
@@ -49,10 +48,7 @@
// Define the initial sizes for allocation of the resizable code buffer
enum {
- initial_code_capacity = 16 * 1024,
- initial_stub_capacity = 4 * 1024,
- initial_const_capacity = 4 * 1024,
- initial_locs_capacity = 3 * 1024
+ initial_const_capacity = 4 * 1024
};
//------------------------------Scheduling----------------------------------
--- a/src/hotspot/share/opto/phaseX.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/opto/phaseX.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1648,14 +1648,14 @@
// of the mirror load depends on the type of 'n'. See LoadNode::Value().
// LoadBarrier?(LoadP(LoadP(AddP(foo:Klass, #java_mirror))))
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
- bool has_load_barriers = bs->has_load_barriers();
+ bool has_load_barrier_nodes = bs->has_load_barrier_nodes();
if (use_op == Op_LoadP && use->bottom_type()->isa_rawptr()) {
for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = use->fast_out(i2);
const Type* ut = u->bottom_type();
if (u->Opcode() == Op_LoadP && ut->isa_instptr()) {
- if (has_load_barriers) {
+ if (has_load_barrier_nodes) {
// Search for load barriers behind the load
for (DUIterator_Fast i3max, i3 = u->fast_outs(i3max); i3 < i3max; i3++) {
Node* b = u->fast_out(i3);
@@ -1808,14 +1808,14 @@
// Loading the java mirror from a Klass requires two loads and the type
// of the mirror load depends on the type of 'n'. See LoadNode::Value().
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
- bool has_load_barriers = bs->has_load_barriers();
+ bool has_load_barrier_nodes = bs->has_load_barrier_nodes();
if (m_op == Op_LoadP && m->bottom_type()->isa_rawptr()) {
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = m->fast_out(i2);
const Type* ut = u->bottom_type();
if (u->Opcode() == Op_LoadP && ut->isa_instptr() && ut != type(u)) {
- if (has_load_barriers) {
+ if (has_load_barrier_nodes) {
// Search for load barriers behind the load
for (DUIterator_Fast i3max, i3 = u->fast_outs(i3max); i3 < i3max; i3++) {
Node* b = u->fast_out(i3);
--- a/src/hotspot/share/prims/jvmtiExport.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiExport.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1202,6 +1202,7 @@
bool JvmtiExport::_can_post_method_exit = false;
bool JvmtiExport::_can_pop_frame = false;
bool JvmtiExport::_can_force_early_return = false;
+bool JvmtiExport::_can_get_owned_monitor_info = false;
bool JvmtiExport::_early_vmstart_recorded = false;
--- a/src/hotspot/share/prims/jvmtiExport.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiExport.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -91,6 +91,7 @@
JVMTI_SUPPORT_FLAG(can_force_early_return)
JVMTI_SUPPORT_FLAG(early_vmstart_recorded)
+ JVMTI_SUPPORT_FLAG(can_get_owned_monitor_info) // includes can_get_owned_monitor_stack_depth_info
friend class JvmtiEventControllerPrivate; // should only modify these flags
JVMTI_SUPPORT_FLAG(should_post_single_step)
--- a/src/hotspot/share/prims/jvmtiManageCapabilities.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiManageCapabilities.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -367,6 +367,8 @@
JvmtiExport::set_can_pop_frame(avail.can_pop_frame);
JvmtiExport::set_can_force_early_return(avail.can_force_early_return);
JvmtiExport::set_should_clean_up_heap_objects(avail.can_generate_breakpoint_events);
+ JvmtiExport::set_can_get_owned_monitor_info(avail.can_get_owned_monitor_info ||
+ avail.can_get_owned_monitor_stack_depth_info);
}
#ifndef PRODUCT
--- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -32,20 +32,20 @@
JvmtiRawMonitor::QNode::QNode(Thread* thread) : _next(NULL), _prev(NULL),
_event(thread->_ParkEvent),
- _notified(0), TState(TS_RUN) {
+ _notified(0), _t_state(TS_RUN) {
}
-GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors =
+GrowableArray<JvmtiRawMonitor*>* JvmtiPendingMonitors::_monitors =
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1, true);
void JvmtiPendingMonitors::transition_raw_monitors() {
assert((Threads::number_of_threads()==1),
- "Java thread has not been created yet or more than one java thread \
-is running. Raw monitor transition will not work");
- JavaThread *current_java_thread = JavaThread::current();
+ "Java thread has not been created yet or more than one java thread "
+ "is running. Raw monitor transition will not work");
+ JavaThread* current_java_thread = JavaThread::current();
assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
- for(int i=0; i< count(); i++) {
- JvmtiRawMonitor *rmonitor = monitors()->at(i);
+ for (int i = 0; i < count(); i++) {
+ JvmtiRawMonitor* rmonitor = monitors()->at(i);
rmonitor->raw_enter(current_java_thread);
}
// pending monitors are converted to real monitor so delete them all.
@@ -56,10 +56,10 @@
// class JvmtiRawMonitor
//
-JvmtiRawMonitor::JvmtiRawMonitor(const char *name) : _owner(NULL),
+JvmtiRawMonitor::JvmtiRawMonitor(const char* name) : _owner(NULL),
_recursions(0),
- _EntryList(NULL),
- _WaitSet(NULL),
+ _entry_list(NULL),
+ _wait_set(NULL),
_waiters(0),
_magic(JVMTI_RM_MAGIC),
_name(NULL) {
@@ -119,155 +119,165 @@
//
// -------------------------------------------------------------------------
-void JvmtiRawMonitor::SimpleEnter (Thread * Self) {
+void JvmtiRawMonitor::simple_enter(Thread* self) {
for (;;) {
- if (Atomic::replace_if_null(Self, &_owner)) {
- return ;
+ if (Atomic::replace_if_null(self, &_owner)) {
+ return;
}
- QNode Node (Self) ;
- Self->_ParkEvent->reset() ; // strictly optional
- Node.TState = QNode::TS_ENTER ;
+ QNode node(self);
+ self->_ParkEvent->reset(); // strictly optional
+ node._t_state = QNode::TS_ENTER;
- RawMonitor_lock->lock_without_safepoint_check() ;
- Node._next = _EntryList ;
- _EntryList = &Node ;
- OrderAccess::fence() ;
- if (_owner == NULL && Atomic::replace_if_null(Self, &_owner)) {
- _EntryList = Node._next ;
- RawMonitor_lock->unlock() ;
- return ;
+ RawMonitor_lock->lock_without_safepoint_check();
+ node._next = _entry_list;
+ _entry_list = &node;
+ OrderAccess::fence();
+ if (_owner == NULL && Atomic::replace_if_null(self, &_owner)) {
+ _entry_list = node._next;
+ RawMonitor_lock->unlock();
+ return;
}
- RawMonitor_lock->unlock() ;
- while (Node.TState == QNode::TS_ENTER) {
- Self->_ParkEvent->park() ;
+ RawMonitor_lock->unlock();
+ while (node._t_state == QNode::TS_ENTER) {
+ self->_ParkEvent->park();
}
}
}
-void JvmtiRawMonitor::SimpleExit (Thread * Self) {
- guarantee (_owner == Self, "invariant") ;
- OrderAccess::release_store(&_owner, (Thread*)NULL) ;
- OrderAccess::fence() ;
- if (_EntryList == NULL) return ;
- QNode * w ;
+void JvmtiRawMonitor::simple_exit(Thread* self) {
+ guarantee(_owner == self, "invariant");
+ OrderAccess::release_store(&_owner, (Thread*)NULL);
+ OrderAccess::fence();
+ if (_entry_list == NULL) {
+ return;
+ }
- RawMonitor_lock->lock_without_safepoint_check() ;
- w = _EntryList ;
+ RawMonitor_lock->lock_without_safepoint_check();
+ QNode* w = _entry_list;
if (w != NULL) {
- _EntryList = w->_next ;
+ _entry_list = w->_next;
}
- RawMonitor_lock->unlock() ;
+ RawMonitor_lock->unlock();
if (w != NULL) {
- guarantee (w ->TState == QNode::TS_ENTER, "invariant") ;
- // Once we set TState to TS_RUN the waiting thread can complete
- // SimpleEnter and 'w' is pointing into random stack space. So we have
- // to ensure we extract the ParkEvent (which is in type-stable memory)
- // before we set the state, and then don't access 'w'.
- ParkEvent * ev = w->_event ;
- OrderAccess::loadstore();
- w->TState = QNode::TS_RUN ;
- OrderAccess::fence() ;
- ev->unpark() ;
+ guarantee(w ->_t_state == QNode::TS_ENTER, "invariant");
+ // Once we set _t_state to TS_RUN the waiting thread can complete
+ // simple_enter and 'w' is pointing into random stack space. So we have
+ // to ensure we extract the ParkEvent (which is in type-stable memory)
+ // before we set the state, and then don't access 'w'.
+ ParkEvent* ev = w->_event;
+ OrderAccess::loadstore();
+ w->_t_state = QNode::TS_RUN;
+ OrderAccess::fence();
+ ev->unpark();
}
- return ;
+ return;
}
-int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {
- guarantee (_owner == Self , "invariant") ;
- guarantee (_recursions == 0, "invariant") ;
+int JvmtiRawMonitor::simple_wait(Thread* self, jlong millis) {
+ guarantee(_owner == self , "invariant");
+ guarantee(_recursions == 0, "invariant");
- QNode Node (Self) ;
- Node._notified = 0 ;
- Node.TState = QNode::TS_WAIT ;
+ QNode node(self);
+ node._notified = 0;
+ node._t_state = QNode::TS_WAIT;
- RawMonitor_lock->lock_without_safepoint_check() ;
- Node._next = _WaitSet ;
- _WaitSet = &Node ;
- RawMonitor_lock->unlock() ;
+ RawMonitor_lock->lock_without_safepoint_check();
+ node._next = _wait_set;
+ _wait_set = &node;
+ RawMonitor_lock->unlock();
- SimpleExit (Self) ;
- guarantee (_owner != Self, "invariant") ;
+ simple_exit(self);
+ guarantee(_owner != self, "invariant");
- int ret = OS_OK ;
+ int ret = OS_OK;
if (millis <= 0) {
- Self->_ParkEvent->park();
+ self->_ParkEvent->park();
} else {
- ret = Self->_ParkEvent->park(millis);
+ ret = self->_ParkEvent->park(millis);
}
// If thread still resides on the waitset then unlink it.
// Double-checked locking -- the usage is safe in this context
- // as TState is volatile and the lock-unlock operators are
+ // as _t_state is volatile and the lock-unlock operators are
// serializing (barrier-equivalent).
- if (Node.TState == QNode::TS_WAIT) {
- RawMonitor_lock->lock_without_safepoint_check() ;
- if (Node.TState == QNode::TS_WAIT) {
+ if (node._t_state == QNode::TS_WAIT) {
+ RawMonitor_lock->lock_without_safepoint_check();
+ if (node._t_state == QNode::TS_WAIT) {
// Simple O(n) unlink, but performance isn't critical here.
- QNode * p ;
- QNode * q = NULL ;
- for (p = _WaitSet ; p != &Node; p = p->_next) {
- q = p ;
+ QNode* p;
+ QNode* q = NULL;
+ for (p = _wait_set; p != &node; p = p->_next) {
+ q = p;
}
- guarantee (p == &Node, "invariant") ;
+ guarantee(p == &node, "invariant");
if (q == NULL) {
- guarantee (p == _WaitSet, "invariant") ;
- _WaitSet = p->_next ;
+ guarantee (p == _wait_set, "invariant");
+ _wait_set = p->_next;
} else {
- guarantee (p == q->_next, "invariant") ;
- q->_next = p->_next ;
+ guarantee(p == q->_next, "invariant");
+ q->_next = p->_next;
}
- Node.TState = QNode::TS_RUN ;
+ node._t_state = QNode::TS_RUN;
}
- RawMonitor_lock->unlock() ;
+ RawMonitor_lock->unlock();
}
- guarantee (Node.TState == QNode::TS_RUN, "invariant") ;
- SimpleEnter (Self) ;
+ guarantee(node._t_state == QNode::TS_RUN, "invariant");
+ simple_enter(self);
- guarantee (_owner == Self, "invariant") ;
- guarantee (_recursions == 0, "invariant") ;
- return ret ;
+ guarantee(_owner == self, "invariant");
+ guarantee(_recursions == 0, "invariant");
+ return ret;
}
-void JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
- guarantee (_owner == Self, "invariant") ;
- if (_WaitSet == NULL) return ;
+void JvmtiRawMonitor::simple_notify(Thread* self, bool all) {
+ guarantee(_owner == self, "invariant");
+ if (_wait_set == NULL) {
+ return;
+ }
// We have two options:
- // A. Transfer the threads from the WaitSet to the EntryList
- // B. Remove the thread from the WaitSet and unpark() it.
+ // A. Transfer the threads from the _wait_set to the _entry_list
+ // B. Remove the thread from the _wait_set and unpark() it.
//
// We use (B), which is crude and results in lots of futile
// context switching. In particular (B) induces lots of contention.
- ParkEvent * ev = NULL ; // consider using a small auto array ...
- RawMonitor_lock->lock_without_safepoint_check() ;
+ ParkEvent* ev = NULL; // consider using a small auto array ...
+ RawMonitor_lock->lock_without_safepoint_check();
for (;;) {
- QNode * w = _WaitSet ;
- if (w == NULL) break ;
- _WaitSet = w->_next ;
- if (ev != NULL) { ev->unpark(); ev = NULL; }
- ev = w->_event ;
- OrderAccess::loadstore() ;
- w->TState = QNode::TS_RUN ;
- OrderAccess::storeload();
- if (!All) break ;
+ QNode* w = _wait_set;
+ if (w == NULL) break;
+ _wait_set = w->_next;
+ if (ev != NULL) {
+ ev->unpark();
+ ev = NULL;
+ }
+ ev = w->_event;
+ OrderAccess::loadstore();
+ w->_t_state = QNode::TS_RUN;
+ OrderAccess::storeload();
+ if (!all) {
+ break;
+ }
}
- RawMonitor_lock->unlock() ;
- if (ev != NULL) ev->unpark();
- return ;
+ RawMonitor_lock->unlock();
+ if (ev != NULL) {
+ ev->unpark();
+ }
+ return;
}
// Any JavaThread will enter here with state _thread_blocked
-void JvmtiRawMonitor::raw_enter(Thread * Self) {
- void * Contended ;
- JavaThread * jt = NULL;
+void JvmtiRawMonitor::raw_enter(Thread* self) {
+ void* contended;
+ JavaThread* jt = NULL;
// don't enter raw monitor if thread is being externally suspended, it will
// surprise the suspender if a "suspended" thread can still enter monitor
- if (Self->is_Java_thread()) {
- jt = (JavaThread*) Self;
+ if (self->is_Java_thread()) {
+ jt = (JavaThread*)self;
jt->SR_lock()->lock_without_safepoint_check();
while (jt->is_external_suspend()) {
jt->SR_lock()->unlock();
@@ -275,37 +285,39 @@
jt->SR_lock()->lock_without_safepoint_check();
}
// guarded by SR_lock to avoid racing with new external suspend requests.
- Contended = Atomic::cmpxchg(jt, &_owner, (Thread*)NULL);
+ contended = Atomic::cmpxchg(jt, &_owner, (Thread*)NULL);
jt->SR_lock()->unlock();
} else {
- Contended = Atomic::cmpxchg(Self, &_owner, (Thread*)NULL);
+ contended = Atomic::cmpxchg(self, &_owner, (Thread*)NULL);
}
- if (Contended == Self) {
- _recursions ++ ;
- return ;
+ if (contended == self) {
+ _recursions++;
+ return;
}
- if (Contended == NULL) {
- guarantee (_owner == Self, "invariant") ;
- guarantee (_recursions == 0, "invariant") ;
- return ;
+ if (contended == NULL) {
+ guarantee(_owner == self, "invariant");
+ guarantee(_recursions == 0, "invariant");
+ return;
}
- Self->set_current_pending_raw_monitor(this);
+ self->set_current_pending_raw_monitor(this);
- if (!Self->is_Java_thread()) {
- SimpleEnter (Self) ;
+ if (!self->is_Java_thread()) {
+ simple_enter(self);
} else {
- guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
+ guarantee(jt->thread_state() == _thread_blocked, "invariant");
for (;;) {
jt->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self()
- SimpleEnter (jt) ;
+ simple_enter(jt);
// were we externally suspended while we were waiting?
- if (!jt->handle_special_suspend_equivalent_condition()) break ;
+ if (!jt->handle_special_suspend_equivalent_condition()) {
+ break;
+ }
// This thread was externally suspended
// We have reentered the contended monitor, but while we were
@@ -314,26 +326,26 @@
// thread that suspended us.
//
// Drop the lock
- SimpleExit (jt) ;
+ simple_exit(jt);
jt->java_suspend_self();
}
}
- Self->set_current_pending_raw_monitor(NULL);
+ self->set_current_pending_raw_monitor(NULL);
- guarantee (_owner == Self, "invariant") ;
- guarantee (_recursions == 0, "invariant") ;
+ guarantee(_owner == self, "invariant");
+ guarantee(_recursions == 0, "invariant");
}
-int JvmtiRawMonitor::raw_exit(Thread * Self) {
- if (Self != _owner) {
+int JvmtiRawMonitor::raw_exit(Thread* self) {
+ if (self != _owner) {
return M_ILLEGAL_MONITOR_STATE;
}
if (_recursions > 0) {
- --_recursions ;
+ _recursions--;
} else {
- SimpleExit (Self) ;
+ simple_exit(self);
}
return M_OK;
@@ -341,70 +353,72 @@
// All JavaThreads will enter here with state _thread_blocked
-int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, Thread * Self) {
- if (Self != _owner) {
+int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, Thread* self) {
+ if (self != _owner) {
return M_ILLEGAL_MONITOR_STATE;
}
- // To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
+ // To avoid spurious wakeups we reset the parkevent. This is strictly optional.
// The caller must be able to tolerate spurious returns from raw_wait().
- Self->_ParkEvent->reset() ;
- OrderAccess::fence() ;
+ self->_ParkEvent->reset();
+ OrderAccess::fence();
- JavaThread * jt = NULL;
+ JavaThread* jt = NULL;
// check interrupt event
if (interruptible) {
- assert(Self->is_Java_thread(), "Only JavaThreads can be interruptible");
- jt = (JavaThread*) Self;
+ assert(self->is_Java_thread(), "Only JavaThreads can be interruptible");
+ jt = (JavaThread*)self;
if (jt->is_interrupted(true)) {
return M_INTERRUPTED;
}
} else {
- assert(!Self->is_Java_thread(), "JavaThreads must be interuptible");
+ assert(!self->is_Java_thread(), "JavaThreads must be interuptible");
}
- intptr_t save = _recursions ;
- _recursions = 0 ;
- _waiters ++ ;
- if (Self->is_Java_thread()) {
- guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
+ intptr_t save = _recursions;
+ _recursions = 0;
+ _waiters++;
+ if (self->is_Java_thread()) {
+ guarantee(jt->thread_state() == _thread_blocked, "invariant");
jt->set_suspend_equivalent();
}
- int rv = SimpleWait (Self, millis) ;
- _recursions = save ;
- _waiters -- ;
+ int rv = simple_wait(self, millis);
+ _recursions = save;
+ _waiters--;
- guarantee (Self == _owner, "invariant") ;
- if (Self->is_Java_thread()) {
- for (;;) {
- if (!jt->handle_special_suspend_equivalent_condition()) break ;
- SimpleExit (jt) ;
- jt->java_suspend_self();
- SimpleEnter (jt) ;
- jt->set_suspend_equivalent() ;
- }
- guarantee (jt == _owner, "invariant") ;
+ guarantee(self == _owner, "invariant");
+ if (self->is_Java_thread()) {
+ for (;;) {
+ if (!jt->handle_special_suspend_equivalent_condition()) {
+ break;
+ }
+ simple_exit(jt);
+ jt->java_suspend_self();
+ simple_enter(jt);
+ jt->set_suspend_equivalent();
+ }
+ guarantee(jt == _owner, "invariant");
}
if (interruptible && jt->is_interrupted(true)) {
return M_INTERRUPTED;
}
- return M_OK ;
-}
-
-int JvmtiRawMonitor::raw_notify(Thread * Self) {
- if (Self != _owner) {
- return M_ILLEGAL_MONITOR_STATE;
- }
- SimpleNotify (Self, false) ;
return M_OK;
}
-int JvmtiRawMonitor::raw_notifyAll(Thread * Self) {
- if (Self != _owner) {
+int JvmtiRawMonitor::raw_notify(Thread* self) {
+ if (self != _owner) {
return M_ILLEGAL_MONITOR_STATE;
}
- SimpleNotify (Self, true) ;
+ simple_notify(self, false);
return M_OK;
}
+
+int JvmtiRawMonitor::raw_notifyAll(Thread* self) {
+ if (self != _owner) {
+ return M_ILLEGAL_MONITOR_STATE;
+ }
+ simple_notify(self, true);
+ return M_OK;
+}
--- a/src/hotspot/share/prims/jvmtiRawMonitor.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -46,31 +46,31 @@
enum TStates { TS_READY, TS_RUN, TS_WAIT, TS_ENTER };
QNode* volatile _next;
QNode* volatile _prev;
- ParkEvent * _event;
- volatile int _notified;
- volatile TStates TState;
+ ParkEvent* _event;
+ volatile int _notified;
+ volatile TStates _t_state;
QNode(Thread* thread);
};
- Thread* volatile _owner; // pointer to owning thread
- volatile int _recursions; // recursion count, 0 for first entry
- QNode* volatile _EntryList; // Threads blocked on entry or reentry.
- // The list is actually composed of nodes,
- // acting as proxies for Threads.
- QNode* volatile _WaitSet; // Threads wait()ing on the monitor
- volatile jint _waiters; // number of waiting threads
- int _magic;
- char * _name;
+ Thread* volatile _owner; // pointer to owning thread
+ volatile int _recursions; // recursion count, 0 for first entry
+ QNode* volatile _entry_list; // Threads blocked on entry or reentry.
+ // The list is actually composed of nodes,
+ // acting as proxies for Threads.
+ QNode* volatile _wait_set; // Threads wait()ing on the monitor
+ volatile jint _waiters; // number of waiting threads
+ int _magic;
+ char* _name;
// JVMTI_RM_MAGIC is set in contructor and unset in destructor.
enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') };
- void SimpleEnter (Thread * Self) ;
- void SimpleExit (Thread * Self) ;
- int SimpleWait (Thread * Self, jlong millis) ;
- void SimpleNotify(Thread * Self, bool All) ;
+ void simple_enter(Thread* self);
+ void simple_exit(Thread* self);
+ int simple_wait(Thread* self, jlong millis);
+ void simple_notify(Thread* self, bool all);
-public:
+ public:
// return codes
enum {
@@ -84,20 +84,20 @@
return CHeapObj::operator new(size, std::nothrow);
}
- JvmtiRawMonitor(const char *name);
+ JvmtiRawMonitor(const char* name);
~JvmtiRawMonitor();
- Thread * owner() const { return _owner; }
- void set_owner(Thread * owner) { _owner = owner; }
- int recursions() const { return _recursions; }
- void raw_enter(Thread * Self);
- int raw_exit(Thread * Self);
- int raw_wait(jlong millis, bool interruptable, Thread * Self);
- int raw_notify(Thread * Self);
- int raw_notifyAll(Thread * Self);
- int magic() const { return _magic; }
- const char *get_name() const { return _name; }
- bool is_valid();
+ Thread* owner() const { return _owner; }
+ void set_owner(Thread* owner) { _owner = owner; }
+ int recursions() const { return _recursions; }
+ void raw_enter(Thread* self);
+ int raw_exit(Thread* self);
+ int raw_wait(jlong millis, bool interruptible, Thread* self);
+ int raw_notify(Thread* self);
+ int raw_notifyAll(Thread* self);
+ int magic() const { return _magic; }
+ const char* get_name() const { return _name; }
+ bool is_valid();
};
// Onload pending raw monitors
@@ -106,8 +106,8 @@
// VM is fully initialized.
class JvmtiPendingMonitors : public AllStatic {
-private:
- static GrowableArray<JvmtiRawMonitor*> *_monitors; // Cache raw monitor enter
+ private:
+ static GrowableArray<JvmtiRawMonitor*>* _monitors; // Cache raw monitor enter
inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
@@ -115,8 +115,8 @@
delete monitors();
}
-public:
- static void enter(JvmtiRawMonitor *monitor) {
+ public:
+ static void enter(JvmtiRawMonitor* monitor) {
monitors()->append(monitor);
}
@@ -124,14 +124,14 @@
return monitors()->length();
}
- static void destroy(JvmtiRawMonitor *monitor) {
+ static void destroy(JvmtiRawMonitor* monitor) {
while (monitors()->contains(monitor)) {
monitors()->remove(monitor);
}
}
// Return false if monitor is not found in the list.
- static bool exit(JvmtiRawMonitor *monitor) {
+ static bool exit(JvmtiRawMonitor* monitor) {
if (monitors()->contains(monitor)) {
monitors()->remove(monitor);
return true;
--- a/src/hotspot/share/runtime/globals.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/runtime/globals.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -1047,6 +1047,9 @@
diagnostic(bool, EnableThreadSMRStatistics, trueInDebug, \
"Enable Thread SMR Statistics") \
\
+ product(bool, UseNotificationThread, true, \
+ "Use Notification Thread") \
+ \
product(bool, Inline, true, \
"Enable inlining") \
\
--- a/src/hotspot/share/runtime/mutexLocker.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -115,6 +115,7 @@
Mutex* Management_lock = NULL;
Monitor* Service_lock = NULL;
+Monitor* Notification_lock = NULL;
Monitor* PeriodicTask_lock = NULL;
Monitor* RedefineClasses_lock = NULL;
Mutex* Verify_lock = NULL;
@@ -236,6 +237,13 @@
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
+
+ if (UseNotificationThread) {
+ def(Notification_lock , PaddedMonitor, special, true, _safepoint_check_never); // used for notification thread operations
+ } else {
+ Notification_lock = Service_lock;
+ }
+
def(JmethodIdCreation_lock , PaddedMutex , leaf, true, _safepoint_check_always); // used for creating jmethodIDs.
def(SystemDictionary_lock , PaddedMonitor, leaf, true, _safepoint_check_always);
--- a/src/hotspot/share/runtime/mutexLocker.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -111,6 +111,7 @@
extern Mutex* Management_lock; // a lock used to serialize JVM management
extern Monitor* Service_lock; // a lock used for service thread operation
+extern Monitor* Notification_lock; // a lock used for notification thread operation
extern Monitor* PeriodicTask_lock; // protects the periodic task structure
extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition
extern Mutex* Verify_lock; // synchronize initialization of verify library
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/notificationThread.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,128 @@
+/*
+ * 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 "memory/universe.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/notificationThread.hpp"
+#include "services/diagnosticArgument.hpp"
+#include "services/diagnosticFramework.hpp"
+#include "services/gcNotifier.hpp"
+#include "services/lowMemoryDetector.hpp"
+
+NotificationThread* NotificationThread::_instance = NULL;
+
+void NotificationThread::initialize() {
+ EXCEPTION_MARK;
+
+ const char* name = "Notification Thread";
+ Handle string = java_lang_String::create_from_str(name, CHECK);
+
+ // Initialize thread_oop to put it into the system threadGroup
+ Handle thread_group (THREAD, Universe::system_thread_group());
+ Handle thread_oop = JavaCalls::construct_new_instance(
+ SystemDictionary::Thread_klass(),
+ vmSymbols::threadgroup_string_void_signature(),
+ thread_group,
+ string,
+ CHECK);
+
+ Klass* group = SystemDictionary::ThreadGroup_klass();
+ JavaValue result(T_VOID);
+ JavaCalls::call_special(&result,
+ thread_group,
+ group,
+ vmSymbols::add_method_name(),
+ vmSymbols::thread_void_signature(),
+ thread_oop,
+ THREAD);
+ {
+ MutexLocker mu(Threads_lock);
+ NotificationThread* thread = new NotificationThread(¬ification_thread_entry);
+
+ // At this point it may be possible that no osthread was created for the
+ // JavaThread due to lack of memory. We would have to throw an exception
+ // in that case. However, since this must work and we do not allow
+ // exceptions anyway, check and abort if this fails.
+ if (thread == NULL || thread->osthread() == NULL) {
+ vm_exit_during_initialization("java.lang.OutOfMemoryError",
+ os::native_thread_creation_failed_msg());
+ }
+
+ java_lang_Thread::set_thread(thread_oop(), thread);
+ java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
+ java_lang_Thread::set_daemon(thread_oop());
+ thread->set_threadObj(thread_oop());
+ _instance = thread;
+
+ Threads::add(thread);
+ Thread::start(thread);
+ }
+}
+
+
+
+void NotificationThread::notification_thread_entry(JavaThread* jt, TRAPS) {
+ while (true) {
+ bool sensors_changed = false;
+ bool has_dcmd_notification_event = false;
+ bool has_gc_notification_event = false;
+ {
+ // Need state transition ThreadBlockInVM so that this thread
+ // will be handled by safepoint correctly when this thread is
+ // notified at a safepoint.
+
+ ThreadBlockInVM tbivm(jt);
+
+ MonitorLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
+ // Process all available work on each (outer) iteration, rather than
+ // only the first recognized bit of work, to avoid frequently true early
+ // tests from potentially starving later work. Hence the use of
+ // arithmetic-or to combine results; we don't want short-circuiting.
+ while (((sensors_changed = LowMemoryDetector::has_pending_requests()) |
+ (has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification()) |
+ (has_gc_notification_event = GCNotifier::has_event()))
+ == 0) {
+ // Wait as a suspend equalent until notified that there is some work to do.
+ ml.wait(0, true);
+ }
+
+ }
+
+ if (sensors_changed) {
+ LowMemoryDetector::process_sensor_changes(jt);
+ }
+
+ if(has_gc_notification_event) {
+ GCNotifier::sendNotification(CHECK);
+ }
+
+ if(has_dcmd_notification_event) {
+ DCmdFactory::send_notification(CHECK);
+ }
+
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/notificationThread.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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_RUNTIME_NOTIFICATIONTHREAD_HPP
+#define SHARE_RUNTIME_NOTIFICATIONTHREAD_HPP
+
+#include "runtime/thread.hpp"
+
+// A JavaThread for low memory detection support, GC and
+// diagnostic framework notifications. This thread is not hidden
+// from the external view to allow the debugger to stop at the
+// breakpoints inside registred MXBean notification listeners.
+
+class NotificationThread : public JavaThread {
+ friend class VMStructs;
+ private:
+
+ static NotificationThread* _instance;
+
+ static void notification_thread_entry(JavaThread* thread, TRAPS);
+ NotificationThread(ThreadFunction entry_point) : JavaThread(entry_point) {};
+
+ public:
+ static void initialize();
+
+};
+
+#endif // SHARE_RUNTIME_NOTIFICATIONTHREAD_HPP
--- a/src/hotspot/share/runtime/serviceThread.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/runtime/serviceThread.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -43,6 +43,7 @@
#include "services/diagnosticFramework.hpp"
#include "services/gcNotifier.hpp"
#include "services/lowMemoryDetector.hpp"
+#include "services/threadIdTable.hpp"
ServiceThread* ServiceThread::_instance = NULL;
@@ -101,6 +102,7 @@
bool stringtable_work = false;
bool symboltable_work = false;
bool resolved_method_table_work = false;
+ bool thread_id_table_work = false;
bool protection_domain_table_work = false;
bool oopstorage_work = false;
JvmtiDeferredEvent jvmti_event;
@@ -120,13 +122,14 @@
// only the first recognized bit of work, to avoid frequently true early
// tests from potentially starving later work. Hence the use of
// arithmetic-or to combine results; we don't want short-circuiting.
- while (((sensors_changed = LowMemoryDetector::has_pending_requests()) |
+ while (((sensors_changed = (!UseNotificationThread && LowMemoryDetector::has_pending_requests())) |
(has_jvmti_events = JvmtiDeferredEventQueue::has_events()) |
- (has_gc_notification_event = GCNotifier::has_event()) |
- (has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification()) |
+ (has_gc_notification_event = (!UseNotificationThread && GCNotifier::has_event())) |
+ (has_dcmd_notification_event = (!UseNotificationThread && DCmdFactory::has_pending_jmx_notification())) |
(stringtable_work = StringTable::has_work()) |
(symboltable_work = SymbolTable::has_work()) |
(resolved_method_table_work = ResolvedMethodTable::has_work()) |
+ (thread_id_table_work = ThreadIdTable::has_work()) |
(protection_domain_table_work = SystemDictionary::pd_cache_table()->has_work()) |
(oopstorage_work = OopStorage::has_cleanup_work_and_reset())
) == 0) {
@@ -151,22 +154,28 @@
jvmti_event.post();
}
- if (sensors_changed) {
- LowMemoryDetector::process_sensor_changes(jt);
- }
+ if (!UseNotificationThread) {
+ if (sensors_changed) {
+ LowMemoryDetector::process_sensor_changes(jt);
+ }
- if(has_gc_notification_event) {
- GCNotifier::sendNotification(CHECK);
- }
+ if(has_gc_notification_event) {
+ GCNotifier::sendNotification(CHECK);
+ }
- if(has_dcmd_notification_event) {
- DCmdFactory::send_notification(CHECK);
+ if(has_dcmd_notification_event) {
+ DCmdFactory::send_notification(CHECK);
+ }
}
if (resolved_method_table_work) {
ResolvedMethodTable::do_concurrent_work(jt);
}
+ if (thread_id_table_work) {
+ ThreadIdTable::do_concurrent_work(jt);
+ }
+
if (protection_domain_table_work) {
SystemDictionary::pd_cache_table()->unlink();
}
--- a/src/hotspot/share/runtime/serviceThread.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/runtime/serviceThread.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -27,8 +27,10 @@
#include "runtime/thread.hpp"
-// A JavaThread for low memory detection support and JVMTI
-// compiled-method-load events.
+// A hidden from external view JavaThread for JVMTI compiled-method-load
+// events, oop storage cleanup, and the maintainance of string, symbol,
+// protection domain, and resolved method tables.
+
class ServiceThread : public JavaThread {
friend class VMStructs;
private:
--- a/src/hotspot/share/runtime/vmStructs.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/runtime/vmStructs.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -88,6 +88,7 @@
#include "runtime/globals.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
+#include "runtime/notificationThread.hpp"
#include "runtime/os.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/serviceThread.hpp"
@@ -1366,6 +1367,7 @@
declare_type(JavaThread, Thread) \
declare_type(JvmtiAgentThread, JavaThread) \
declare_type(ServiceThread, JavaThread) \
+ declare_type(NotificationThread, JavaThread) \
declare_type(CompilerThread, JavaThread) \
declare_type(CodeCacheSweeperThread, JavaThread) \
declare_toplevel_type(OSThread) \
--- a/src/hotspot/share/services/diagnosticFramework.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/diagnosticFramework.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -437,9 +437,9 @@
}
void DCmdFactory::push_jmx_notification_request() {
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
_has_pending_jmx_notification = true;
- Service_lock->notify_all();
+ Notification_lock->notify_all();
}
void DCmdFactory::send_notification(TRAPS) {
@@ -455,7 +455,7 @@
HandleMark hm(THREAD);
bool notif = false;
{
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
notif = _has_pending_jmx_notification;
_has_pending_jmx_notification = false;
}
--- a/src/hotspot/share/services/gcNotifier.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/gcNotifier.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -54,18 +54,18 @@
}
void GCNotifier::addRequest(GCNotificationRequest *request) {
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
if(first_request == NULL) {
first_request = request;
} else {
last_request->next = request;
}
last_request = request;
- Service_lock->notify_all();
+ Notification_lock->notify_all();
}
GCNotificationRequest *GCNotifier::getRequest() {
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
GCNotificationRequest *request = first_request;
if(first_request != NULL) {
first_request = first_request->next;
--- a/src/hotspot/share/services/lowMemoryDetector.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/lowMemoryDetector.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -40,7 +40,7 @@
volatile jint LowMemoryDetector::_disabled_count = 0;
bool LowMemoryDetector::has_pending_requests() {
- assert(Service_lock->owned_by_self(), "Must own Service_lock");
+ assert(Notification_lock->owned_by_self(), "Must own Notification_lock");
bool has_requests = false;
int num_memory_pools = MemoryService::num_memory_pools();
for (int i = 0; i < num_memory_pools; i++) {
@@ -62,7 +62,7 @@
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
- // No need to hold Service_lock to call out to Java
+ // No need to hold Notification_lock to call out to Java
int num_memory_pools = MemoryService::num_memory_pools();
for (int i = 0; i < num_memory_pools; i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
@@ -80,7 +80,7 @@
// This method could be called from any Java threads
// and also VMThread.
void LowMemoryDetector::detect_low_memory() {
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
bool has_pending_requests = false;
int num_memory_pools = MemoryService::num_memory_pools();
@@ -98,7 +98,7 @@
}
if (has_pending_requests) {
- Service_lock->notify_all();
+ Notification_lock->notify_all();
}
}
@@ -113,14 +113,14 @@
}
{
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
MemoryUsage usage = pool->get_memory_usage();
sensor->set_gauge_sensor_level(usage,
pool->usage_threshold());
if (sensor->has_pending_requests()) {
// notify sensor state update
- Service_lock->notify_all();
+ Notification_lock->notify_all();
}
}
}
@@ -135,14 +135,14 @@
}
{
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
MemoryUsage usage = pool->get_last_collection_usage();
sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold());
if (sensor->has_pending_requests()) {
// notify sensor state update
- Service_lock->notify_all();
+ Notification_lock->notify_all();
}
}
}
@@ -205,7 +205,7 @@
// If the current level is between high and low threshold, no change.
//
void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
- assert(Service_lock->owned_by_self(), "Must own Service_lock");
+ assert(Notification_lock->owned_by_self(), "Must own Notification_lock");
assert(high_low_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
@@ -260,7 +260,7 @@
// the sensor will be on (i.e. sensor is currently off
// and has pending trigger requests).
void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
- assert(Service_lock->owned_by_self(), "Must own Service_lock");
+ assert(Notification_lock->owned_by_self(), "Must own Notification_lock");
assert(counter_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
@@ -334,8 +334,8 @@
}
{
- // Holds Service_lock and update the sensor state
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ // Holds Notification_lock and update the sensor state
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
assert(_pending_trigger_count > 0, "Must have pending trigger");
_sensor_on = true;
_sensor_count += count;
@@ -345,8 +345,8 @@
void SensorInfo::clear(int count, TRAPS) {
{
- // Holds Service_lock and update the sensor state
- MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ // Holds Notification_lock and update the sensor state
+ MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
if (_pending_clear_count == 0) {
// Bail out if we lost a race to set_*_sensor_level() which may have
// reactivated the sensor in the meantime because it was triggered again.
--- a/src/hotspot/share/services/lowMemoryDetector.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/lowMemoryDetector.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -59,7 +59,8 @@
//
// May need to deal with hysteresis effect.
//
-// Memory detection code runs in the Service thread (serviceThread.hpp).
+// Memory detection code runs in the Notification thread or
+// ServiceThread depending on UseNotificationThread flag.
class OopClosure;
class MemoryPool;
@@ -214,6 +215,7 @@
class LowMemoryDetector : public AllStatic {
friend class LowMemoryDetectorDisabler;
friend class ServiceThread;
+ friend class NotificationThread;
private:
// true if any collected heap has low memory detection enabled
static volatile bool _enabled_for_collected_pools;
--- a/src/hotspot/share/services/management.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/management.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -44,6 +44,7 @@
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
+#include "runtime/notificationThread.hpp"
#include "runtime/os.hpp"
#include "runtime/serviceThread.hpp"
#include "runtime/thread.inline.hpp"
@@ -148,7 +149,9 @@
void Management::initialize(TRAPS) {
// Start the service thread
ServiceThread::initialize();
-
+ if (UseNotificationThread) {
+ NotificationThread::initialize();
+ }
if (ManagementServer) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
--- a/src/hotspot/share/services/threadIdTable.cpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/threadIdTable.cpp Wed Oct 09 23:22:56 2019 +0200
@@ -46,6 +46,7 @@
static volatile size_t _items_count = 0;
volatile bool ThreadIdTable::_is_initialized = false;
+volatile bool ThreadIdTable::_has_work = false;
class ThreadIdTableEntry : public CHeapObj<mtInternal> {
private:
@@ -141,6 +142,26 @@
return (size_t)1 << _local_table->get_size_log2(Thread::current());
}
+void ThreadIdTable::check_concurrent_work() {
+ if (_has_work) {
+ return;
+ }
+
+ double load_factor = get_load_factor();
+ // Resize if we have more items than preferred load factor
+ if ( load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
+ log_debug(thread, table)("Concurrent work triggered, load factor: %g",
+ load_factor);
+ trigger_concurrent_work();
+ }
+}
+
+void ThreadIdTable::trigger_concurrent_work() {
+ MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ _has_work = true;
+ Service_lock->notify_all();
+}
+
void ThreadIdTable::grow(JavaThread* jt) {
ThreadIdTableHash::GrowTask gt(_local_table);
if (!gt.prepare(jt)) {
@@ -192,13 +213,13 @@
}
};
-void ThreadIdTable::grow_if_required() {
- assert(Thread::current()->is_Java_thread(),"Must be Java thread");
+void ThreadIdTable::do_concurrent_work(JavaThread* jt) {
assert(_is_initialized, "Thread table is not initialized");
+ _has_work = false;
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());
+ grow(jt);
}
}
@@ -215,7 +236,7 @@
// The hash table takes ownership of the ThreadTableEntry,
// even if it's not inserted.
if (_local_table->insert(thread, lookup, entry)) {
- grow_if_required();
+ check_concurrent_work();
return java_thread;
}
}
--- a/src/hotspot/share/services/threadIdTable.hpp Wed Oct 09 23:21:07 2019 +0200
+++ b/src/hotspot/share/services/threadIdTable.hpp Wed Oct 09 23:22:56 2019 +0200
@@ -36,6 +36,7 @@
friend class ThreadIdTableConfig;
static volatile bool _is_initialized;
+ static volatile bool _has_work;
public:
// Initialization
@@ -47,12 +48,17 @@
static JavaThread* add_thread(jlong tid, JavaThread* thread);
static bool remove_thread(jlong tid);
+ // Growing
+ static bool has_work() { return _has_work; }
+ static void do_concurrent_work(JavaThread* jt);
+
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 check_concurrent_work();
+ static void trigger_concurrent_work();
static void grow(JavaThread* jt);
static void item_added();
--- a/src/java.base/share/classes/java/lang/Throwable.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/lang/Throwable.java Wed Oct 09 23:22:56 2019 +0200
@@ -230,6 +230,7 @@
* @serial
* @since 1.7
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
/** Message for trying to suppress a null exception. */
--- a/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java Wed Oct 09 23:22:56 2019 +0200
@@ -76,6 +76,7 @@
private final String implMethodSignature;
private final int implMethodKind;
private final String instantiatedMethodType;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final Object[] capturedArgs;
/**
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java Wed Oct 09 23:22:56 2019 +0200
@@ -308,6 +308,7 @@
* the invocation handler for this proxy instance.
* @serial
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
protected InvocationHandler h;
/**
--- a/src/java.base/share/classes/java/net/DatagramSocket.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/net/DatagramSocket.java Wed Oct 09 23:22:56 2019 +0200
@@ -434,14 +434,15 @@
* verify that datagrams are permitted to be sent and received
* respectively.
*
- * <p> When a socket is connected, {@link #receive receive} and
- * {@link #send send} <b>will not perform any security checks</b>
- * on incoming and outgoing packets, other than matching the packet's
- * and the socket's address and port. On a send operation, if the
- * packet's address is set and the packet's address and the socket's
- * address do not match, an {@code IllegalArgumentException} will be
- * thrown. A socket connected to a multicast address may only be used
- * to send packets.
+ * <p> Care should be taken to ensure that a connected datagram socket
+ * is not shared with untrusted code. When a socket is connected,
+ * {@link #receive receive} and {@link #send send} <b>will not perform
+ * any security checks</b> on incoming and outgoing packets, other than
+ * matching the packet's and the socket's address and port. On a send
+ * operation, if the packet's address is set and the packet's address
+ * and the socket's address do not match, an {@code IllegalArgumentException}
+ * will be thrown. A socket connected to a multicast address may only
+ * be used to send packets.
*
* @param address the remote address for the socket
*
@@ -708,9 +709,11 @@
* the length of the received message. If the message is longer than
* the packet's length, the message is truncated.
* <p>
- * If there is a security manager, a packet cannot be received if the
- * security manager's {@code checkAccept} method
- * does not allow it.
+ * If there is a security manager, and the socket is not currently
+ * connected to a remote address, a packet cannot be received if the
+ * security manager's {@code checkAccept} method does not allow it.
+ * Datagrams that are not permitted by the security manager are silently
+ * discarded.
*
* @param p the {@code DatagramPacket} into which to place
* the incoming data.
@@ -896,12 +899,15 @@
*
* @param timeout the specified timeout in milliseconds.
* @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
+ * @throws IllegalArgumentException if {@code timeout} is negative
* @since 1.1
* @see #getSoTimeout()
*/
public synchronized void setSoTimeout(int timeout) throws SocketException {
if (isClosed())
throw new SocketException("Socket is closed");
+ if (timeout < 0)
+ throw new IllegalArgumentException("timeout < 0");
getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
}
--- a/src/java.base/share/classes/java/nio/channels/DatagramChannel.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/nio/channels/DatagramChannel.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -265,7 +265,10 @@
* java.lang.SecurityManager#checkAccept checkAccept} and {@link
* java.lang.SecurityManager#checkConnect checkConnect} methods permit
* datagrams to be received from and sent to, respectively, the given
- * remote address.
+ * remote address. Once connected, no further security checks are performed
+ * for datagrams received from, or sent to, the given remote address. Care
+ * should be taken to ensure that a connected datagram channel is not shared
+ * with untrusted code.
*
* <p> This method may be invoked at any time. It will not have any effect
* on read or write operations that are already in progress at the moment
@@ -325,6 +328,10 @@
* <p> If this channel's socket is not connected, or if the channel is
* closed, then invoking this method has no effect. </p>
*
+ * @apiNote If this method throws an IOException, the channel's socket
+ * may be left in an unspecified state. It is strongly recommended that
+ * the channel be closed when disconnect fails.
+ *
* @return This datagram channel
*
* @throws IOException
@@ -369,9 +376,10 @@
* to a specific remote address and a security manager has been installed
* then for each datagram received this method verifies that the source's
* address and port number are permitted by the security manager's {@link
- * java.lang.SecurityManager#checkAccept checkAccept} method. The overhead
- * of this security check can be avoided by first connecting the socket via
- * the {@link #connect connect} method.
+ * java.lang.SecurityManager#checkAccept checkAccept} method. Datagrams
+ * that are not permitted by the security manager are silently discarded.
+ * The overhead of this security check can be avoided by first connecting
+ * the socket via the {@link #connect connect} method.
*
* <p> This method may be invoked at any time. If another thread has
* already initiated a read operation upon this channel, however, then an
@@ -401,11 +409,6 @@
* closing the channel and setting the current thread's
* interrupt status
*
- * @throws SecurityException
- * If a security manager has been installed
- * and it does not permit datagrams to be accepted
- * from the datagram's sender
- *
* @throws IOException
* If some other I/O error occurs
*/
--- a/src/java.base/share/classes/java/nio/channels/SelectionKey.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/nio/channels/SelectionKey.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,8 @@
package java.nio.channels;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
/**
* A token representing the registration of a {@link SelectableChannel} with a
@@ -428,13 +429,17 @@
// -- Attachments --
+ private static final VarHandle ATTACHMENT;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ ATTACHMENT = l.findVarHandle(SelectionKey.class, "attachment", Object.class);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ }
private volatile Object attachment;
- private static final AtomicReferenceFieldUpdater<SelectionKey,Object>
- attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(
- SelectionKey.class, Object.class, "attachment"
- );
-
/**
* Attaches the given object to this key.
*
@@ -450,7 +455,7 @@
* otherwise {@code null}
*/
public final Object attach(Object ob) {
- return attachmentUpdater.getAndSet(this, ob);
+ return ATTACHMENT.getAndSet(this, ob);
}
/**
--- a/src/java.base/share/classes/java/nio/file/Files.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/nio/file/Files.java Wed Oct 09 23:22:56 2019 +0200
@@ -3550,8 +3550,8 @@
// ensure lines is not null before opening file
Objects.requireNonNull(lines);
CharsetEncoder encoder = cs.newEncoder();
- OutputStream out = newOutputStream(path, options);
- try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
+ try (OutputStream out = newOutputStream(path, options);
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
for (CharSequence line: lines) {
writer.append(line);
writer.newLine();
--- a/src/java.base/share/classes/java/security/GuardedObject.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/security/GuardedObject.java Wed Oct 09 23:22:56 2019 +0200
@@ -52,7 +52,9 @@
@java.io.Serial
private static final long serialVersionUID = -5240450096227834308L;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Object object; // the object we are guarding
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Guard guard; // the guard
/**
--- a/src/java.base/share/classes/java/security/SecureRandom.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/security/SecureRandom.java Wed Oct 09 23:22:56 2019 +0200
@@ -1043,6 +1043,7 @@
/**
* @serial
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private MessageDigest digest = null;
/**
* @serial
--- a/src/java.base/share/classes/java/time/Clock.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/time/Clock.java Wed Oct 09 23:22:56 2019 +0200
@@ -641,6 +641,7 @@
static final class OffsetClock extends Clock implements Serializable {
@java.io.Serial
private static final long serialVersionUID = 2007484719125426256L;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final Clock baseClock;
private final Duration offset;
@@ -692,6 +693,7 @@
static final class TickClock extends Clock implements Serializable {
@java.io.Serial
private static final long serialVersionUID = 6504659149906368850L;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final Clock baseClock;
private final long tickNanos;
--- a/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -109,6 +109,7 @@
/**
* The chronology.
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final Chronology chrono;
/**
* The number of years.
--- a/src/java.base/share/classes/java/util/AbstractMap.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/AbstractMap.java Wed Oct 09 23:22:56 2019 +0200
@@ -607,7 +607,9 @@
@java.io.Serial
private static final long serialVersionUID = -8499721149061103585L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final K key;
+ @SuppressWarnings("serial") // Conditionally serializable
private V value;
/**
@@ -738,7 +740,9 @@
@java.io.Serial
private static final long serialVersionUID = 7138329143949025153L;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final K key;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final V value;
/**
--- a/src/java.base/share/classes/java/util/ArrayPrefixHelpers.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/ArrayPrefixHelpers.java Wed Oct 09 23:22:56 2019 +0200
@@ -103,10 +103,15 @@
static final int MIN_PARTITION = 16;
static final class CumulateTask<T> extends CountedCompleter<Void> {
+ @SuppressWarnings("serial") // Not statically typed as Serializable
final T[] array;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
final BinaryOperator<T> function;
CumulateTask<T> left, right;
- T in, out;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ T in;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ T out;
final int lo, hi, origin, fence, threshold;
/** Root task constructor */
@@ -257,6 +262,7 @@
static final class LongCumulateTask extends CountedCompleter<Void> {
final long[] array;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
final LongBinaryOperator function;
LongCumulateTask left, right;
long in, out;
@@ -408,6 +414,7 @@
static final class DoubleCumulateTask extends CountedCompleter<Void> {
final double[] array;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
final DoubleBinaryOperator function;
DoubleCumulateTask left, right;
double in, out;
@@ -559,6 +566,7 @@
static final class IntCumulateTask extends CountedCompleter<Void> {
final int[] array;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
final IntBinaryOperator function;
IntCumulateTask left, right;
int in, out;
--- a/src/java.base/share/classes/java/util/Arrays.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/Arrays.java Wed Oct 09 23:22:56 2019 +0200
@@ -4339,6 +4339,7 @@
{
@java.io.Serial
private static final long serialVersionUID = -2764017481108945198L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final E[] a;
ArrayList(E[] array) {
--- a/src/java.base/share/classes/java/util/ArraysParallelSortHelpers.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/ArraysParallelSortHelpers.java Wed Oct 09 23:22:56 2019 +0200
@@ -115,8 +115,12 @@
static final class Sorter<T> extends CountedCompleter<Void> {
@java.io.Serial
static final long serialVersionUID = 2446542900576103244L;
- final T[] a, w;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ final T[] a;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ final T[] w;
final int base, size, wbase, gran;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
Comparator<? super T> comparator;
Sorter(CountedCompleter<?> par, T[] a, T[] w, int base, int size,
int wbase, int gran,
@@ -153,8 +157,13 @@
static final class Merger<T> extends CountedCompleter<Void> {
@java.io.Serial
static final long serialVersionUID = 2446542900576103244L;
- final T[] a, w; // main and workspace arrays
+ // main and workspace arrays
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ final T[] a;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ final T[] w;
final int lbase, lsize, rbase, rsize, wbase, gran;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
Comparator<? super T> comparator;
Merger(CountedCompleter<?> par, T[] a, T[] w,
int lbase, int lsize, int rbase,
--- a/src/java.base/share/classes/java/util/Collections.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/Collections.java Wed Oct 09 23:22:56 2019 +0200
@@ -1024,6 +1024,7 @@
@java.io.Serial
private static final long serialVersionUID = 1820017752578914078L;
+ @SuppressWarnings("serial") // Conditionally serializable
final Collection<? extends E> c;
UnmodifiableCollection(Collection<? extends E> c) {
@@ -1164,6 +1165,7 @@
implements SortedSet<E>, Serializable {
@java.io.Serial
private static final long serialVersionUID = -4929149591599911165L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final SortedSet<E> ss;
UnmodifiableSortedSet(SortedSet<E> s) {super(s); ss = s;}
@@ -1244,6 +1246,7 @@
/**
* The instance we are protecting.
*/
+ @SuppressWarnings("serial") // Conditionally serializable
private final NavigableSet<E> ns;
UnmodifiableNavigableSet(NavigableSet<E> s) {super(s); ns = s;}
@@ -1304,6 +1307,7 @@
@java.io.Serial
private static final long serialVersionUID = -283967356065247728L;
+ @SuppressWarnings("serial") // Conditionally serializable
final List<? extends E> list;
UnmodifiableList(List<? extends E> list) {
@@ -1450,6 +1454,7 @@
@java.io.Serial
private static final long serialVersionUID = -1034234728574286014L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final Map<? extends K, ? extends V> m;
UnmodifiableMap(Map<? extends K, ? extends V> m) {
@@ -1809,6 +1814,7 @@
@java.io.Serial
private static final long serialVersionUID = -8806743815996713206L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final SortedMap<K, ? extends V> sm;
UnmodifiableSortedMap(SortedMap<K, ? extends V> m) {super(m); sm = m; }
@@ -1886,6 +1892,7 @@
/**
* The instance we wrap and protect.
*/
+ @SuppressWarnings("serial") // Conditionally serializable
private final NavigableMap<K, ? extends V> nm;
UnmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
@@ -2017,7 +2024,9 @@
@java.io.Serial
private static final long serialVersionUID = 3053995032091335093L;
+ @SuppressWarnings("serial") // Conditionally serializable
final Collection<E> c; // Backing Collection
+ @SuppressWarnings("serial") // Conditionally serializable
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection<E> c) {
@@ -2219,6 +2228,7 @@
@java.io.Serial
private static final long serialVersionUID = 8695801310862127406L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final SortedSet<E> ss;
SynchronizedSortedSet(SortedSet<E> s) {
@@ -2314,6 +2324,7 @@
@java.io.Serial
private static final long serialVersionUID = -5505529816273629798L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final NavigableSet<E> ns;
SynchronizedNavigableSet(NavigableSet<E> s) {
@@ -2424,6 +2435,7 @@
@java.io.Serial
private static final long serialVersionUID = -7754090372962971524L;
+ @SuppressWarnings("serial") // Conditionally serializable
final List<E> list;
SynchronizedList(List<E> list) {
@@ -2591,7 +2603,9 @@
@java.io.Serial
private static final long serialVersionUID = 1978198479659022715L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final Map<K,V> m; // Backing Map
+ @SuppressWarnings("serial") // Conditionally serializable
final Object mutex; // Object on which to synchronize
SynchronizedMap(Map<K,V> m) {
@@ -2788,6 +2802,7 @@
@java.io.Serial
private static final long serialVersionUID = -8798146769416483793L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final SortedMap<K,V> sm;
SynchronizedSortedMap(SortedMap<K,V> m) {
@@ -2891,6 +2906,7 @@
@java.io.Serial
private static final long serialVersionUID = 699392247599746807L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final NavigableMap<K,V> nm;
SynchronizedNavigableMap(NavigableMap<K,V> m) {
@@ -3070,7 +3086,9 @@
@java.io.Serial
private static final long serialVersionUID = 1578914078182001775L;
+ @SuppressWarnings("serial") // Conditionally serializable
final Collection<E> c;
+ @SuppressWarnings("serial") // Conditionally serializable
final Class<E> type;
@SuppressWarnings("unchecked")
@@ -3126,6 +3144,7 @@
public boolean add(E e) { return c.add(typeCheck(e)); }
+ @SuppressWarnings("serial") // Conditionally serializable
private E[] zeroLengthElementArray; // Lazily initialized
private E[] zeroLengthElementArray() {
@@ -3219,6 +3238,7 @@
{
@java.io.Serial
private static final long serialVersionUID = 1433151992604707767L;
+ @SuppressWarnings("serial") // Conditionally serializable
final Queue<E> queue;
CheckedQueue(Queue<E> queue, Class<E> elementType) {
@@ -3323,6 +3343,7 @@
@java.io.Serial
private static final long serialVersionUID = 1599911165492914959L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final SortedSet<E> ss;
CheckedSortedSet(SortedSet<E> s, Class<E> type) {
@@ -3387,6 +3408,7 @@
@java.io.Serial
private static final long serialVersionUID = -5429120189805438922L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final NavigableSet<E> ns;
CheckedNavigableSet(NavigableSet<E> s, Class<E> type) {
@@ -3470,6 +3492,7 @@
{
@java.io.Serial
private static final long serialVersionUID = 65247728283967356L;
+ @SuppressWarnings("serial") // Conditionally serializable
final List<E> list;
CheckedList(List<E> list, Class<E> type) {
@@ -3619,8 +3642,11 @@
@java.io.Serial
private static final long serialVersionUID = 5742860141034234728L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final Map<K, V> m;
+ @SuppressWarnings("serial") // Conditionally serializable
final Class<K> keyType;
+ @SuppressWarnings("serial") // Conditionally serializable
final Class<V> valueType;
private void typeCheck(Object key, Object value) {
@@ -4019,6 +4045,7 @@
@java.io.Serial
private static final long serialVersionUID = 1599671320688067438L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final SortedMap<K, V> sm;
CheckedSortedMap(SortedMap<K, V> m,
@@ -4094,6 +4121,7 @@
@java.io.Serial
private static final long serialVersionUID = -4852462692372534096L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final NavigableMap<K, V> nm;
CheckedNavigableMap(NavigableMap<K, V> m,
@@ -4825,6 +4853,7 @@
@java.io.Serial
private static final long serialVersionUID = 3193687207550431679L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final E element;
SingletonSet(E e) {element = e;}
@@ -4879,6 +4908,7 @@
@java.io.Serial
private static final long serialVersionUID = 3093736618740652951L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final E element;
SingletonList(E obj) {element = obj;}
@@ -4948,7 +4978,9 @@
@java.io.Serial
private static final long serialVersionUID = -6979724477215052911L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final K k;
+ @SuppressWarnings("serial") // Conditionally serializable
private final V v;
SingletonMap(K key, V value) {
@@ -5087,6 +5119,7 @@
private static final long serialVersionUID = 2739099268398711800L;
final int n;
+ @SuppressWarnings("serial") // Conditionally serializable
final E element;
CopiesList(int n, E e) {
@@ -5320,6 +5353,7 @@
*
* @serial
*/
+ @SuppressWarnings("serial") // Conditionally serializable
final Comparator<T> cmp;
ReverseComparator2(Comparator<T> cmp) {
@@ -5601,6 +5635,7 @@
private static class SetFromMap<E> extends AbstractSet<E>
implements Set<E>, Serializable
{
+ @SuppressWarnings("serial") // Conditionally serializable
private final Map<E, Boolean> m; // The backing map
private transient Set<E> s; // Its keySet
@@ -5686,6 +5721,7 @@
implements Queue<E>, Serializable {
@java.io.Serial
private static final long serialVersionUID = 1802017725587941708L;
+ @SuppressWarnings("serial") // Conditionally serializable
private final Deque<E> q;
AsLIFOQueue(Deque<E> q) { this.q = q; }
public boolean add(E e) { q.addFirst(e); return true; }
--- a/src/java.base/share/classes/java/util/Comparators.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/Comparators.java Wed Oct 09 23:22:56 2019 +0200
@@ -66,6 +66,7 @@
private static final long serialVersionUID = -7569533591570686392L;
private final boolean nullFirst;
// if null, non-null Ts are considered equal
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final Comparator<T> real;
@SuppressWarnings("unchecked")
--- a/src/java.base/share/classes/java/util/PriorityQueue.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/PriorityQueue.java Wed Oct 09 23:22:56 2019 +0200
@@ -111,6 +111,7 @@
* The comparator, or null if priority queue uses elements'
* natural ordering.
*/
+ @SuppressWarnings("serial") // Conditionally serializable
private final Comparator<? super E> comparator;
/**
--- a/src/java.base/share/classes/java/util/TreeMap.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/TreeMap.java Wed Oct 09 23:22:56 2019 +0200
@@ -118,6 +118,7 @@
*
* @serial
*/
+ @SuppressWarnings("serial") // Conditionally serializable
private final Comparator<? super K> comparator;
private transient Entry<K,V> root;
@@ -1353,7 +1354,10 @@
* if loInclusive is true, lo is the inclusive bound, else lo
* is the exclusive bound. Similarly for the upper bound.
*/
- final K lo, hi;
+ @SuppressWarnings("serial") // Conditionally serializable
+ final K lo;
+ @SuppressWarnings("serial") // Conditionally serializable
+ final K hi;
final boolean fromStart, toEnd;
final boolean loInclusive, hiInclusive;
@@ -1936,6 +1940,7 @@
super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
}
+ @SuppressWarnings("serial") // Conditionally serializable
private final Comparator<? super K> reverseComparator =
Collections.reverseOrder(m.comparator);
@@ -2024,7 +2029,10 @@
@java.io.Serial
private static final long serialVersionUID = -6520786458950516097L;
private boolean fromStart = false, toEnd = false;
- private K fromKey, toKey;
+ @SuppressWarnings("serial") // Conditionally serializable
+ private K fromKey;
+ @SuppressWarnings("serial") // Conditionally serializable
+ private K toKey;
@java.io.Serial
private Object readResolve() {
return new AscendingSubMap<>(TreeMap.this,
--- a/src/java.base/share/classes/java/util/Vector.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/Vector.java Wed Oct 09 23:22:56 2019 +0200
@@ -102,6 +102,7 @@
*
* @serial
*/
+ @SuppressWarnings("serial") // Conditionally serializable
protected Object[] elementData;
/**
--- a/src/java.base/share/classes/java/util/jar/JarVerifier.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java Wed Oct 09 23:22:56 2019 +0200
@@ -590,6 +590,7 @@
URL vlocation;
CodeSigner[] vsigners;
java.security.cert.Certificate[] vcerts;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
Object csdomain;
VerifierCodeSource(Object csdomain, URL location, CodeSigner[] signers) {
--- a/src/java.base/share/classes/javax/crypto/CryptoPermission.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/javax/crypto/CryptoPermission.java Wed Oct 09 23:22:56 2019 +0200
@@ -55,6 +55,7 @@
private String alg;
private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize
private String exemptionMechanism = null;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private AlgorithmParameterSpec algParamSpec = null;
private boolean checkParam = false; // no restriction on param
--- a/src/java.base/share/classes/javax/security/auth/PrivateCredentialPermission.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/javax/security/auth/PrivateCredentialPermission.java Wed Oct 09 23:22:56 2019 +0200
@@ -119,6 +119,7 @@
* The set contains elements of type,
* {@code PrivateCredentialPermission.CredOwner}.
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Set<Principal> principals; // ignored - kept around for compatibility
private transient CredOwner[] credOwners;
--- a/src/java.base/share/classes/javax/security/auth/Subject.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/javax/security/auth/Subject.java Wed Oct 09 23:22:56 2019 +0200
@@ -111,6 +111,7 @@
* {@code java.security.Principal}.
* The set is a {@code Subject.SecureSet}.
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
Set<Principal> principals;
/**
--- a/src/java.base/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java Wed Oct 09 23:22:56 2019 +0200
@@ -39,6 +39,7 @@
/**
* @serial
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Callback callback;
/**
--- a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Oct 09 23:22:56 2019 +0200
@@ -49,6 +49,7 @@
private static final long serialVersionUID = 100L;
private static final PlatformLogger logger = HttpURLConnection.getHttpLogger();
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final HttpCallerInfo hci;
// These maps are used to manage the GSS availability for diffrent
@@ -67,6 +68,7 @@
}
// The HTTP Negotiate Helper
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Negotiator negotiator = null;
/**
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -875,6 +875,11 @@
if (state == ST_CONNECTED)
throw new AlreadyConnectedException();
+ // ensure that the socket is bound
+ if (localAddress == null) {
+ bindInternal(null);
+ }
+
int n = Net.connect(family,
fd,
isa.getAddress(),
@@ -932,8 +937,21 @@
remoteAddress = null;
state = ST_UNCONNECTED;
- // refresh local address
- localAddress = Net.localAddress(fd);
+ // check whether rebind is needed
+ InetSocketAddress isa = Net.localAddress(fd);
+ if (isa.getPort() == 0) {
+ // On Linux, if bound to ephemeral port,
+ // disconnect does not preserve that port.
+ // In this case, try to rebind to the previous port.
+ int port = localAddress.getPort();
+ localAddress = isa; // in case Net.bind fails
+ Net.bind(family, fd, isa.getAddress(), port);
+ isa = Net.localAddress(fd); // refresh address
+ assert isa.getPort() == port;
+ }
+
+ // refresh localAddress
+ localAddress = isa;
}
} finally {
writeLock.unlock();
--- a/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -208,7 +208,8 @@
if (!(ch instanceof SelChImpl))
throw new IllegalSelectorException();
SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
- k.attach(attachment);
+ if (attachment != null)
+ k.attach(attachment);
// register (if needed) before adding to key set
implRegister(k);
--- a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Wed Oct 09 23:22:56 2019 +0200
@@ -44,6 +44,7 @@
@java.io.Serial
private static final long serialVersionUID = 6182022883658399397L;
private final Class<? extends Annotation> type;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final Map<String, Object> memberValues;
AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
--- a/src/java.base/share/classes/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.java Wed Oct 09 23:22:56 2019 +0200
@@ -36,7 +36,8 @@
class AnnotationTypeMismatchExceptionProxy extends ExceptionProxy {
@java.io.Serial
private static final long serialVersionUID = 7844069490309503934L;
- private Method member;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ private Method member; // Would be more robust to null-out in a writeObject method.
private final String foundType;
/**
--- a/src/java.base/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Wed Oct 09 23:22:56 2019 +0200
@@ -50,7 +50,11 @@
private final SecretKey clientMacKey, serverMacKey;
private final SecretKey clientCipherKey, serverCipherKey;
- private final IvParameterSpec clientIv, serverIv;
+
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ private final IvParameterSpec clientIv;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ private final IvParameterSpec serverIv;
/**
* Constructs a new TlsKeymaterialSpec from the client and server MAC
--- a/src/java.base/share/classes/sun/security/provider/PolicyParser.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/provider/PolicyParser.java Wed Oct 09 23:22:56 2019 +0200
@@ -1315,7 +1315,9 @@
private static final long serialVersionUID = -4330692689482574072L;
private String i18nMessage;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private LocalizedMessage localizedMsg;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Object[] source;
/**
--- a/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java Wed Oct 09 23:22:56 2019 +0200
@@ -54,6 +54,7 @@
private static final Class<?>[] PARAMS = { String.class };
private static final sun.security.util.Debug debug =
sun.security.util.Debug.getInstance("auth", "\t[Auth Access]");
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private ClassLoader sysClassLoader;
/**
--- a/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java Wed Oct 09 23:22:56 2019 +0200
@@ -69,6 +69,7 @@
/**
* List of certificates in this chain
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private List<X509Certificate> certs;
/**
--- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -70,6 +70,7 @@
// Optional parameters associated with this RSA key
// specified in the encoding of its AlgorithmId.
// Must be null for "RSA" keys.
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private AlgorithmParameterSpec keyParams;
/**
--- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -61,6 +61,7 @@
// optional parameters associated with this RSA key
// specified in the encoding of its AlgorithmId.
// must be null for "RSA" keys.
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final AlgorithmParameterSpec keyParams;
/**
--- a/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -62,6 +62,7 @@
// optional parameters associated with this RSA key
// specified in the encoding of its AlgorithmId
// must be null for "RSA" keys.
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private AlgorithmParameterSpec keyParams;
/**
--- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Wed Oct 09 23:22:56 2019 +0200
@@ -98,6 +98,7 @@
* Changed to Object
* @serial
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Object components = null; // path from root
/**
* @serial
--- a/src/java.base/share/classes/sun/security/validator/ValidatorException.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/validator/ValidatorException.java Wed Oct 09 23:22:56 2019 +0200
@@ -62,6 +62,7 @@
public static final Object T_UNTRUSTED_CERT =
"Untrusted certificate";
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Object type;
private X509Certificate cert;
--- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed Oct 09 23:22:56 2019 +0200
@@ -72,6 +72,7 @@
private ObjectIdentifier algid;
// The (parsed) parameters
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private AlgorithmParameters algParams;
private boolean constructedFromDer = true;
@@ -80,6 +81,7 @@
* DER-encoded form; subclasses can be made to automaticaly parse
* them so there is fast access to these parameters.
*/
+ @SuppressWarnings("serial") // Not statically typed as Serializable
protected DerValue params;
--- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Oct 09 23:22:56 2019 +0200
@@ -70,6 +70,7 @@
* @author Hemma Prafullchandra
* @see X509CertInfo
*/
+@SuppressWarnings("serial") // See writeReplace method in Certificate
public class X509CertImpl extends X509Certificate implements DerEncoder {
@java.io.Serial
--- a/src/java.base/share/classes/sun/security/x509/X509Key.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/classes/sun/security/x509/X509Key.java Wed Oct 09 23:22:56 2019 +0200
@@ -84,7 +84,7 @@
private int unusedBits = 0;
/* BitArray form of key */
- private BitArray bitStringKey = null;
+ private transient BitArray bitStringKey = null;
/* The encoding for the key. */
protected byte[] encodedKey;
--- a/src/java.base/share/native/libzip/Deflater.c Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.base/share/native/libzip/Deflater.c Wed Oct 09 23:22:56 2019 +0200
@@ -257,7 +257,7 @@
res = doDeflate(env, addr, input, inputLen, output + outputOff, outputLen,
flush, params);
- (*env)->ReleasePrimitiveArrayCritical(env, outputArray, input, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res);
return retVal;
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Oct 09 23:22:56 2019 +0200
@@ -1391,6 +1391,7 @@
static class KerberosSessionKey implements Key {
private static final long serialVersionUID = 699307378954123869L;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private final EncryptionKey key;
KerberosSessionKey(EncryptionKey key) {
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Wed Oct 09 23:22:56 2019 +0200
@@ -53,7 +53,9 @@
private static final long serialVersionUID = 7723415700837898232L;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Krb5NameElement name;
+ @SuppressWarnings("serial") // Not statically typed as Serializable
private Credentials krb5Credentials;
private Krb5InitCredential(Krb5NameElement name,
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java Wed Oct 09 23:22:56 2019 +0200
@@ -79,7 +79,9 @@
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
* http://www.ietf.org/rfc/rfc4120.txt</a>.
*/
-
+// The instance fields not statically typed as Serializable are ASN.1
+// encoded and written by the writeObject method.
+@SuppressWarnings("serial")
public class KRBError implements java.io.Serializable {
static final long serialVersionUID = 3643809337475284503L;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Wed Oct 09 23:22:56 2019 +0200
@@ -389,7 +389,7 @@
Entry e = table[hash];
Assert.check(e == elems, elems.sym);
table[hash] = elems.shadowed;
- elems = elems.sibling;
+ elems = elems.nextSibling;
}
Assert.check(next.shared > 0);
next.shared--;
@@ -466,15 +466,15 @@
}
// remove e from elems and sibling list
- te = elems;
- if (te == e)
- elems = e.sibling;
- else while (true) {
- if (te.sibling == e) {
- te.sibling = e.sibling;
- break;
- }
- te = te.sibling;
+ if (elems == e) {
+ elems = e.nextSibling;
+ if (elems != null)
+ elems.prevSibling = null;
+ } else {
+ Assert.check(e.prevSibling != null, e.sym);
+ e.prevSibling.nextSibling = e.nextSibling;
+ if (e.nextSibling != null)
+ e.nextSibling.prevSibling = e.prevSibling;
}
removeCount++;
@@ -597,7 +597,7 @@
private Symbol doNext() {
Symbol sym = (currEntry == null ? null : currEntry.sym);
if (currEntry != null) {
- currEntry = currEntry.sibling;
+ currEntry = currEntry.nextSibling;
}
update();
return sym;
@@ -617,7 +617,7 @@
void skipToNextMatchingEntry() {
while (currEntry != null && sf != null && !sf.accepts(currEntry.sym)) {
- currEntry = currEntry.sibling;
+ currEntry = currEntry.nextSibling;
}
}
};
@@ -677,7 +677,7 @@
result.append("Scope[");
for (ScopeImpl s = this; s != null ; s = s.next) {
if (s != this) result.append(" | ");
- for (Entry e = s.elems; e != null; e = e.sibling) {
+ for (Entry e = s.elems; e != null; e = e.nextSibling) {
if (e != s.elems) result.append(", ");
result.append(e.sym);
}
@@ -702,18 +702,24 @@
/** Next entry in same scope.
*/
- public Entry sibling;
+ public Entry nextSibling;
+
+ /** Prev entry in same scope.
+ */
+ public Entry prevSibling;
/** The entry's scope.
* scope == null iff this == sentinel
*/
public ScopeImpl scope;
- public Entry(Symbol sym, Entry shadowed, Entry sibling, ScopeImpl scope) {
+ public Entry(Symbol sym, Entry shadowed, Entry nextSibling, ScopeImpl scope) {
this.sym = sym;
this.shadowed = shadowed;
- this.sibling = sibling;
+ this.nextSibling = nextSibling;
this.scope = scope;
+ if (nextSibling != null)
+ nextSibling.prevSibling = this;
}
/** Return next entry with the same name as this entry, proceeding
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Oct 09 23:22:56 2019 +0200
@@ -3745,12 +3745,9 @@
return cl1;
} else if (shouldSkip.test(cl1.head, cl2.head)) {
return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head);
- } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) {
- return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
} else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) {
return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head);
} else {
- // unrelated types
return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/NotificationThread.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.runtime;
+
+
+import sun.jvm.hotspot.debugger.Address;
+
+public class NotificationThread extends JavaThread {
+ public NotificationThread(Address addr) {
+ super(addr);
+ }
+
+ public boolean isJavaThread() { return false; }
+
+}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java Wed Oct 09 23:22:56 2019 +0200
@@ -158,6 +158,7 @@
}
virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class);
virtualConstructor.addMapping("ServiceThread", ServiceThread.class);
+ virtualConstructor.addMapping("NotificationThread", NotificationThread.class);
}
public Threads() {
@@ -165,14 +166,14 @@
}
/** NOTE: this returns objects of type JavaThread, CompilerThread,
- JvmtiAgentThread, and ServiceThread.
+ JvmtiAgentThread, NotificationThread, and ServiceThread.
The latter four are subclasses of the former. Most operations
(fetching the top frame, etc.) are only allowed to be performed on
a "pure" JavaThread. For this reason, {@link
sun.jvm.hotspot.runtime.JavaThread#isJavaThread} has been
changed from the definition in the VM (which returns true for
all of these thread types) to return true for JavaThreads and
- false for the three subclasses. FIXME: should reconsider the
+ false for the four subclasses. FIXME: should reconsider the
inheritance hierarchy; see {@link
sun.jvm.hotspot.runtime.JavaThread#isJavaThread}. */
public JavaThread getJavaThreadAt(int i) {
--- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -133,8 +133,9 @@
* <ol>
*
* <li><p> If the system property
- * {@code com.sun.net.httpserver.HttpServerProvider} is defined then it
- * is taken to be the fully-qualified name of a concrete provider class.
+ * {@systemProperty com.sun.net.httpserver.HttpServerProvider}
+ * is defined then it is taken to be the fully-qualified name
+ * of a concrete provider class.
* The class is loaded and instantiated; if this process fails then an
* unspecified unchecked error or exception is thrown. </p></li>
*
--- a/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java Wed Oct 09 23:21:07 2019 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java Wed Oct 09 23:22:56 2019 +0200
@@ -140,18 +140,14 @@
return vids;
}
- public Collection<VirtualMachineDescriptor> getVirtualMachineDescriptors(Class<?> excludeClass) {
+ public Collection<VirtualMachineDescriptor> getVirtualMachineDescriptors() {
if (singlePid != null) {
return getSingleVMD(singlePid);
} else {
- return getVMDs(excludeClass, matchClass);
+ return getVMDs(null, matchClass);
}
}
- public Collection<VirtualMachineDescriptor> getVirtualMachineDescriptors() {
- return this.getVirtualMachineDescriptors(null);
- }
-
public Collection<String> getVirtualMachinePids(Class<?> excludeClass) {
if (singlePid != null) {
// There is a bug in AttachProvider, when VM is debuggee-suspended it's not listed by the AttachProvider.
@@ -162,7 +158,4 @@
}
}
- public Collection<String> getVirtualMachinePids() {
- return this.getVirtualMachinePids(null);
- }
}
--- a/test/hotspot/jtreg/ProblemList-graal.txt Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Wed Oct 09 23:22:56 2019 +0200
@@ -236,7 +236,6 @@
runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java 8222582 generic-all
# Graal unit tests
-org.graalvm.compiler.core.test.CheckGraalInvariants 8205081
org.graalvm.compiler.core.test.OptionsVerifierTest 8205081
org.graalvm.compiler.hotspot.test.CompilationWrapperTest 8205081
org.graalvm.compiler.replacements.test.classfile.ClassfileBytecodeProviderTest 8205081
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/CoreAarch64Test.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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
+ * @summary
+ * @requires vm.opt.final.EnableJVMCI == true
+ *
+ * @modules jdk.internal.vm.compiler
+ *
+ * @library /test/lib /compiler/graalunit /
+ *
+ * @build compiler.graalunit.common.GraalUnitTestLauncher
+ *
+ * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
+ *
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.aarch64.test -exclude ExcludeList.txt
+ */
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/CoreJdk9Test.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,40 @@
+/*
+ * 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
+ * @summary
+ * @requires vm.opt.final.EnableJVMCI == true
+ *
+ * @modules jdk.internal.vm.compiler
+ *
+ * @library /test/lib /compiler/graalunit /
+ *
+ * @build compiler.graalunit.common.GraalUnitTestLauncher
+ *
+ * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
+ *
+ * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.jdk9.test -exclude ExcludeList.txt
+ */
+
+/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/EA9Test.java Wed Oct 09 23:21:07 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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
- * @summary
- * @requires vm.opt.final.EnableJVMCI == true
- *
- * @modules jdk.internal.vm.compiler
- *
- * @library /test/lib /compiler/graalunit /
- *
- * @build compiler.graalunit.common.GraalUnitTestLauncher
- *
- * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt
- *
- * @run main compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.core.jdk9.test.ea -exclude ExcludeList.txt
- */
-
-/* DO NOT MODIFY THIS FILE. GENERATED BY generateTests.sh */
--- a/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/TestPackages.txt Wed Oct 09 23:22:56 2019 +0200
@@ -4,18 +4,19 @@
AsmAarch64 org.graalvm.compiler.asm.aarch64.test
AsmAmd64 org.graalvm.compiler.asm.amd64.test
AsmSparc org.graalvm.compiler.asm.sparc.test
-CoreAmd64 org.graalvm.compiler.core.amd64.test
Core org.graalvm.compiler.core.test @requires !vm.graal.enabled
EA org.graalvm.compiler.core.test.ea
-EA9 org.graalvm.compiler.core.jdk9.test.ea
+CoreAmd64 org.graalvm.compiler.core.amd64.test
+CoreAarch64 org.graalvm.compiler.core.aarch64.test
+CoreJdk9 org.graalvm.compiler.core.jdk9.test
Debug org.graalvm.compiler.debug.test
Graph org.graalvm.compiler.graph.test @requires vm.graal.enabled
+Hotspot org.graalvm.compiler.hotspot.test
HotspotAarch64 org.graalvm.compiler.hotspot.aarch64.test
HotspotAmd64 org.graalvm.compiler.hotspot.amd64.test
HotspotJdk9 org.graalvm.compiler.hotspot.jdk9.test
HotspotSparc org.graalvm.compiler.hotspot.sparc.test @requires vm.simpleArch == "sparcv9"
HotspotLir org.graalvm.compiler.hotspot.lir.test
-Hotspot org.graalvm.compiler.hotspot.test
Loop org.graalvm.compiler.loop.test
Nodes org.graalvm.compiler.nodes.test @requires vm.graal.enabled
Options org.graalvm.compiler.options.test
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/FindClassesByAnnotatedMethods.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/FindClassesByAnnotatedMethods.java Wed Oct 09 23:22:56 2019 +0200
@@ -73,7 +73,7 @@
System.out.print(jarFilePath);
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
- if (je.isDirectory() || !je.getName().endsWith(".class")) {
+ if (je.isDirectory() || !je.getName().endsWith(".class") || je.getName().equals("module-info.class")) {
continue;
}
Set<String> methodAnnotationTypes = new HashSet<>();
@@ -84,6 +84,8 @@
} catch (UnsupportedClassVersionError ucve) {
isSupported = false;
unsupportedClasses++;
+ } catch (Throwable t) {
+ throw new InternalError("Error while parsing class from " + je + " in " + jarFilePath, t);
}
String className = je.getName().substring(0, je.getName().length() - ".class".length()).replaceAll("/", ".");
if (!isSupported) {
@@ -129,7 +131,7 @@
/*
* Small bytecode parser that extract annotations.
*/
- private static final int MAJOR_VERSION_JAVA7 = 51;
+ private static final int MAJOR_VERSION_JAVA6 = 50;
private static final int MAJOR_VERSION_OFFSET = 44;
private static final byte CONSTANT_Utf8 = 1;
private static final byte CONSTANT_Integer = 3;
@@ -146,6 +148,8 @@
private static final byte CONSTANT_MethodType = 16;
private static final byte CONSTANT_Dynamic = 17;
private static final byte CONSTANT_InvokeDynamic = 18;
+ private static final byte CONSTANT_Module = 19;
+ private static final byte CONSTANT_Package = 20;
private static void readClassfile(DataInputStream stream, Collection<String> methodAnnotationTypes) throws IOException {
// magic
@@ -154,7 +158,7 @@
int minor = stream.readUnsignedShort();
int major = stream.readUnsignedShort();
- if (major < MAJOR_VERSION_JAVA7) {
+ if (major < MAJOR_VERSION_JAVA6) {
throw new UnsupportedClassVersionError("Unsupported class file version: " + major + "." + minor);
}
// Starting with JDK8, ignore a classfile that has a newer format than the current JDK.
@@ -210,7 +214,9 @@
switch (tag) {
case CONSTANT_Class:
case CONSTANT_String:
- case CONSTANT_MethodType: {
+ case CONSTANT_MethodType:
+ case CONSTANT_Module:
+ case CONSTANT_Package: {
skipFully(stream, 2);
break;
}
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/JLModule.java Wed Oct 09 23:21:07 2019 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.mxtool.junit;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Set;
-
-/**
- * Facade for the {@code java.lang.Module} class introduced in JDK9 that allows tests to be
- * developed against JDK8 but use module logic if deployed on JDK9.
- */
-class JLModule {
-
- private final Object realModule;
-
- JLModule(Object module) {
- this.realModule = module;
- }
-
- private static final Class<?> moduleClass;
- private static final Class<?> layerClass;
-
- private static final Method bootMethod;
- private static final Method modulesMethod;
- private static final Method getModuleMethod;
- private static final Method getUnnamedModuleMethod;
- private static final Method getNameMethod;
- private static final Method getPackagesMethod;
- private static final Method isExportedMethod;
- private static final Method isExported2Method;
- private static final Method addExportsMethod;
- private static final Method addOpensMethod;
- static {
- try {
- moduleClass = findModuleClass();
- Class<?> modulesClass = Class.forName("jdk.internal.module.Modules");
- layerClass = findModuleLayerClass();
- bootMethod = layerClass.getMethod("boot");
- modulesMethod = layerClass.getMethod("modules");
- getModuleMethod = Class.class.getMethod("getModule");
- getUnnamedModuleMethod = ClassLoader.class.getMethod("getUnnamedModule");
- getNameMethod = moduleClass.getMethod("getName");
- getPackagesMethod = moduleClass.getMethod("getPackages");
- isExportedMethod = moduleClass.getMethod("isExported", String.class);
- isExported2Method = moduleClass.getMethod("isExported", String.class, moduleClass);
- addExportsMethod = modulesClass.getDeclaredMethod("addExports", moduleClass, String.class, moduleClass);
- addOpensMethod = getDeclaredMethodOptional(modulesClass, "addOpens", moduleClass, String.class, moduleClass);
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- // API change http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/afedee84773e.
- protected static Class<?> findModuleClass() throws ClassNotFoundException {
- try {
- return Class.forName("java.lang.Module");
- } catch (ClassNotFoundException e) {
- return Class.forName("java.lang.reflect.Module");
- }
- }
-
- // API change http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/afedee84773e.
- protected static Class<?> findModuleLayerClass() throws ClassNotFoundException {
- try {
- return Class.forName("java.lang.ModuleLayer");
- } catch (ClassNotFoundException e) {
- return Class.forName("java.lang.reflect.Layer");
- }
- }
-
- private static Method getDeclaredMethodOptional(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
- try {
- return declaringClass.getDeclaredMethod(name, parameterTypes);
- } catch (NoSuchMethodException e) {
- return null;
- }
- }
-
- public static JLModule fromClass(Class<?> cls) {
- try {
- return new JLModule(getModuleMethod.invoke(cls));
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- @SuppressWarnings("unchecked")
- public static JLModule find(String name) {
- try {
- Object bootLayer = bootMethod.invoke(null);
- Set<Object> modules = (Set<Object>) modulesMethod.invoke(bootLayer);
- for (Object m : modules) {
- JLModule module = new JLModule(m);
- String mname = module.getName();
- if (mname.equals(name)) {
- return module;
- }
- }
- } catch (Exception e) {
- throw new InternalError(e);
- }
- return null;
- }
-
- public static JLModule getUnnamedModuleFor(ClassLoader cl) {
- try {
- return new JLModule(getUnnamedModuleMethod.invoke(cl));
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- public String getName() {
- try {
- return (String) getNameMethod.invoke(realModule);
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- /**
- * Exports all packages in this module to a given module.
- */
- public void exportAllPackagesTo(JLModule module) {
- if (this != module) {
- for (String pkg : getPackages()) {
- // Export all JVMCI packages dynamically instead
- // of requiring a long list of -XaddExports
- // options on the JVM command line.
- if (!isExported(pkg, module)) {
- addExports(pkg, module);
- addOpens(pkg, module);
- }
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- public Iterable<String> getPackages() {
- try {
- // API change http://hg.openjdk.java.net/jdk9/dev/hotspot/rev/afedee84773e#l1.15
- Object res = getPackagesMethod.invoke(realModule);
- if (res instanceof String[]) {
- return Arrays.asList((String[]) res);
- }
- return (Set<String>) res;
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- public boolean isExported(String pn) {
- try {
- return (Boolean) isExportedMethod.invoke(realModule, pn);
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- public boolean isExported(String pn, JLModule other) {
- try {
- return (Boolean) isExported2Method.invoke(realModule, pn, other.realModule);
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- public void addExports(String pn, JLModule other) {
- try {
- addExportsMethod.invoke(null, realModule, pn, other.realModule);
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
- public void addOpens(String pn, JLModule other) {
- if (addOpensMethod != null) {
- try {
- addOpensMethod.invoke(null, realModule, pn, other.realModule);
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
- }
-
- @Override
- public String toString() {
- return realModule.toString();
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/ModuleSupport.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.mxtool.junit;
+
+import java.io.PrintStream;
+import java.util.Set;
+
+/**
+ * Interface to {@code java.lang.Module} related functionality.
+ */
+class ModuleSupport {
+
+ /**
+ * @param out stream to use for printing warnings
+ */
+ ModuleSupport(PrintStream out) {
+ }
+
+ /**
+ * Exports and opens packages based on {@code spec}. See further documentation in
+ * {@code mx_unittest.py}.
+ *
+ * @param spec
+ * @param context
+ * @param opened the set of opens performed are added to this set in the format
+ * {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+ * {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+ * @param exported the set of exports performed are added to this set in the format
+ * {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+ * {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+ */
+ void openPackages(String spec, Object context, Set<String> opened, Set<String> exported) {
+ // Nop on JDK 8
+ }
+
+ /**
+ * Updates modules specified in {@code AddExport} annotations on {@code classes} to export and
+ * open packages to the annotation classes' declaring modules.
+ *
+ * @param classes
+ * @param opened the set of opens performed are added to this set in the format
+ * {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+ * {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+ * @param exported the set of exports performed are added to this set in the format
+ * {@code <module>/<package>=<target-module>(,<target-module>)*} (e.g.
+ * {@code "com.foo/com.foo.util=ALL-NAMED,com.bar"})
+ */
+ void processAddExportsAnnotations(Set<Class<?>> classes, Set<String> opened, Set<String> exported) {
+ // Nop on JDK 8
+ }
+}
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/MxJUnitWrapper.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/MxJUnitWrapper.java Wed Oct 09 23:22:56 2019 +0200
@@ -29,18 +29,13 @@
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.TreeSet;
import org.junit.internal.JUnitSystem;
import org.junit.internal.RealSystem;
@@ -59,6 +54,14 @@
public class MxJUnitWrapper {
+ // Unit tests that start a JVM subprocess can use these system properties to
+ // add --add-exports and --add-opens as necessary to the JVM command line.
+ //
+ // Known usages:
+ // org.graalvm.compiler.test.SubprocessUtil.getPackageOpeningOptions()
+ public static final String OPENED_PACKAGES_PROPERTY_NAME = "com.oracle.mxtool.junit.opens";
+ public static final String EXPORTED_PACKAGES_PROPERTY_NAME = "com.oracle.mxtool.junit.exports";
+
public static class MxJUnitConfig {
public boolean verbose = false;
@@ -136,14 +139,25 @@
String[] expandedArgs = expandArgs(args);
int i = 0;
+ List<String> testSpecs = new ArrayList<>();
+ List<String> openPackagesSpecs = new ArrayList<>();
while (i < expandedArgs.length) {
String each = expandedArgs[i];
if (each.charAt(0) == '-') {
// command line arguments
if (each.contentEquals("-JUnitVerbose")) {
config.verbose = true;
+ config.enableTiming = true;
+ } else if (each.contentEquals("-JUnitOpenPackages")) {
+ if (i + 1 >= expandedArgs.length) {
+ system.out().println("Must include argument for -JUnitAddExports");
+ System.exit(1);
+ }
+ openPackagesSpecs.add(expandedArgs[++i]);
} else if (each.contentEquals("-JUnitVeryVerbose")) {
+ config.verbose = true;
config.veryVerbose = true;
+ config.enableTiming = true;
} else if (each.contentEquals("-JUnitFailFast")) {
config.failFast = true;
} else if (each.contentEquals("-JUnitEnableTiming")) {
@@ -172,21 +186,35 @@
}
} else {
-
- try {
- builder.addTestSpec(each);
- } catch (MxJUnitRequest.BuilderException ex) {
- system.out().println(ex.getMessage());
- System.exit(1);
- }
+ testSpecs.add(each);
}
i++;
}
- MxJUnitRequest request = builder.build();
+ ModuleSupport moduleSupport = new ModuleSupport(system.out());
+ Set<String> opened = new TreeSet<>();
+ Set<String> exported = new TreeSet<>();
+ for (String spec : openPackagesSpecs) {
+ moduleSupport.openPackages(spec, "-JUnitOpenPackages", opened, exported);
+ }
- if (System.getProperty("java.specification.version").compareTo("1.9") >= 0) {
- addExports(request.classes, system.out());
+ for (String spec : testSpecs) {
+ try {
+ builder.addTestSpec(spec);
+ } catch (MxJUnitRequest.BuilderException ex) {
+ system.out().println(ex.getMessage());
+ System.exit(1);
+ }
+ }
+
+ MxJUnitRequest request = builder.build();
+ moduleSupport.processAddExportsAnnotations(request.classes, opened, exported);
+
+ if (!opened.isEmpty()) {
+ System.setProperty(OPENED_PACKAGES_PROPERTY_NAME, String.join(System.lineSeparator(), opened));
+ }
+ if (!exported.isEmpty()) {
+ System.setProperty(EXPORTED_PACKAGES_PROPERTY_NAME, String.join(System.lineSeparator(), exported));
}
for (RunListener p : ServiceLoader.load(RunListener.class)) {
@@ -285,8 +313,6 @@
return result;
}
- private static final Pattern MODULE_PACKAGE_RE = Pattern.compile("([^/]+)/(.+)");
-
private static class Timing<T> implements Comparable<Timing<T>> {
final T subject;
final long value;
@@ -344,93 +370,6 @@
}
/**
- * Adds the super types of {@code cls} to {@code supertypes}.
- */
- private static void gatherSupertypes(Class<?> cls, Set<Class<?>> supertypes) {
- if (!supertypes.contains(cls)) {
- supertypes.add(cls);
- Class<?> superclass = cls.getSuperclass();
- if (superclass != null) {
- gatherSupertypes(superclass, supertypes);
- }
- for (Class<?> iface : cls.getInterfaces()) {
- gatherSupertypes(iface, supertypes);
- }
- }
- }
-
- /**
- * Updates modules specified in {@code AddExport} annotations on {@code classes} to export
- * concealed packages to the annotation classes' declaring modules.
- */
- private static void addExports(Set<Class<?>> classes, PrintStream out) {
- Set<Class<?>> types = new HashSet<>();
- for (Class<?> cls : classes) {
- gatherSupertypes(cls, types);
- }
- for (Class<?> cls : types) {
- Annotation[] annos = cls.getAnnotations();
- for (Annotation a : annos) {
- Class<? extends Annotation> annotationType = a.annotationType();
- if (annotationType.getSimpleName().equals("AddExports")) {
- Optional<String[]> value = getElement("value", String[].class, a);
- if (value.isPresent()) {
- for (String export : value.get()) {
- Matcher m = MODULE_PACKAGE_RE.matcher(export);
- if (m.matches()) {
- String moduleName = m.group(1);
- String packageName = m.group(2);
- JLModule module = JLModule.find(moduleName);
- if (module == null) {
- out.printf("%s: Cannot find module named %s specified in \"AddExports\" annotation: %s%n", cls.getName(), moduleName, a);
- } else {
- if (packageName.equals("*")) {
- module.exportAllPackagesTo(JLModule.fromClass(cls));
- } else {
- module.addExports(packageName, JLModule.fromClass(cls));
- module.addOpens(packageName, JLModule.fromClass(cls));
- }
- }
- } else {
- out.printf("%s: Ignoring \"AddExports\" annotation with value not matching <module>/<package> pattern: %s%n", cls.getName(), a);
- }
- }
- } else {
- out.printf("%s: Ignoring \"AddExports\" annotation without `String value` element: %s%n", cls.getName(), a);
- }
- }
- }
- }
- }
-
- /**
- * Gets the value of the element named {@code name} of type {@code type} from {@code annotation}
- * if present.
- *
- * @return the requested element value wrapped in an {@link Optional} or
- * {@link Optional#empty()} if {@code annotation} has no element named {@code name}
- * @throws AssertionError if {@code annotation} has an element of the given name but whose type
- * is not {@code type} or if there's some problem reading the value via reflection
- */
- private static <T> Optional<T> getElement(String name, Class<T> type, Annotation annotation) {
- Class<? extends Annotation> annotationType = annotation.annotationType();
- Method valueAccessor;
- try {
- valueAccessor = annotationType.getMethod(name);
- if (!valueAccessor.getReturnType().equals(type)) {
- throw new AssertionError(String.format("Element %s of %s is of type %s, not %s ", name, annotationType.getName(), valueAccessor.getReturnType().getName(), type.getName()));
- }
- } catch (NoSuchMethodException e) {
- return Optional.empty();
- }
- try {
- return Optional.of(type.cast(valueAccessor.invoke(annotation)));
- } catch (Exception e) {
- throw new AssertionError(String.format("Could not read %s element from %s", name, annotation), e);
- }
- }
-
- /**
* Expand any arguments starting with @ and return the resulting argument array.
*
* @return the expanded argument array
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TextRunListener.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TextRunListener.java Wed Oct 09 23:22:56 2019 +0200
@@ -74,7 +74,8 @@
}
public static RunListener createRunListener(MxRunListener l) {
- return new TextListener(l.getWriter()) {
+ PrintStream theWriter = l.getWriter();
+ return new TextListener(theWriter) {
private Class<?> lastClass;
private int passedInLastClass;
private int failedInLastClass;
@@ -143,6 +144,15 @@
public void testAssumptionFailure(Failure failure) {
l.testAssumptionFailure(failure);
}
+
+ @Override
+ protected void printFailure(Failure each, String prefix) {
+ // Print out the test message in the same format used to run a single test:
+ // my.package.MyClass#methodName
+ String header = each.getDescription().getClassName() + "#" + each.getDescription().getMethodName();
+ theWriter.println(prefix + ") " + header);
+ theWriter.print(each.getTrace());
+ }
};
}
}
--- a/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TimingDecorator.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/com.oracle.mxtool.junit/com/oracle/mxtool/junit/TimingDecorator.java Wed Oct 09 23:22:56 2019 +0200
@@ -22,8 +22,8 @@
*/
package com.oracle.mxtool.junit;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.junit.runner.Description;
@@ -40,8 +40,8 @@
TimingDecorator(MxRunListener l) {
super(l);
- this.classTimes = new HashMap<>();
- this.testTimes = new HashMap<>();
+ this.classTimes = new ConcurrentHashMap<>();
+ this.testTimes = new ConcurrentHashMap<>();
}
@Override
--- a/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java Wed Oct 09 23:22:56 2019 +0200
@@ -229,6 +229,8 @@
javaFlags.add("jdk.internal.vm.compiler,jdk.internal.vm.ci");
javaFlags.add("--add-exports");
javaFlags.add("java.base/jdk.internal.module=ALL-UNNAMED");
+ javaFlags.add("--add-exports");
+ javaFlags.add("java.base/jdk.internal.misc=ALL-UNNAMED");
javaFlags.addAll(getModuleExports("jdk.internal.vm.compiler", "ALL-UNNAMED"));
javaFlags.addAll(getModuleExports("jdk.internal.vm.ci", "ALL-UNNAMED,jdk.internal.vm.compiler"));
--- a/test/hotspot/jtreg/gc/g1/TestRemsetLoggingThreads.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/gc/g1/TestRemsetLoggingThreads.java Wed Oct 09 23:22:56 2019 +0200
@@ -54,7 +54,7 @@
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- String pattern = "Concurrent RS threads times \\(s\\)$";
+ String pattern = "Concurrent refinement threads times \\(s\\)$";
Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(output.getStdout());
if (!m.find()) {
--- a/test/hotspot/jtreg/gc/g1/TestRemsetLoggingTools.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/gc/g1/TestRemsetLoggingTools.java Wed Oct 09 23:22:56 2019 +0200
@@ -110,7 +110,7 @@
}
public static void expectRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception {
- int actualTotal = result.split("concurrent refinement").length - 1;
+ int actualTotal = result.split("concurrent refinement statistics").length - 1;
int actualCumulative = result.split("Cumulative RS summary").length - 1;
if (expectedCumulative != actualCumulative) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorInfo/GetOwnedMonitorInfoWithEATest.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 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
+ * 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 8230677
+ * @summary Test JVMTI's GetOwnedMonitorInfo with scalar replaced objects and eliminated locks on stack (optimizations based on escape analysis).
+ * @comment Without RFE 8227745 escape analysis needs to be switched off to pass the test. For the implementation of RFE 8227745 it serves as a regression test.
+ * @requires (vm.compMode != "Xcomp" & vm.compiler2.enabled)
+ * @library /test/lib
+ * @compile GetOwnedMonitorInfoWithEATest.java
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
+ * GetOwnedMonitorInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking -XX:-UseOptoBiasInlining
+ * GetOwnedMonitorInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
+ * GetOwnedMonitorInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
+ * GetOwnedMonitorInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
+ * GetOwnedMonitorInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
+ * GetOwnedMonitorInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
+ * GetOwnedMonitorInfoWithEATest
+ */
+
+import jdk.test.lib.Asserts;
+
+public class GetOwnedMonitorInfoWithEATest {
+
+ public static final int COMPILE_THRESHOLD = 20000;
+
+ /**
+ * Native wrapper arround JVMTI's GetOwnedMonitorInfo().
+ * @param t The thread for which the owned monitors information should be retrieved.
+ * @param ownedMonitors Array filled in by the call with the objects associated
+ * with the monitors owned by the given thread.
+ * @param depths Per owned monitor the depth of the frame were it was locked.
+ * Filled in by the call
+ * @return Number of monitors owned by the given thread.
+ */
+ public static native int getOwnedMonitorInfo(Thread t, Object[] ownedMonitors);
+
+ public static void main(String[] args) throws Exception {
+ new GetOwnedMonitorInfoWithEATest().runTest();
+ }
+
+ public void runTest() throws Exception {
+ new TestCase_1().run();
+ new TestCase_2().run();
+ }
+
+ public static abstract class TestCaseBase implements Runnable {
+
+ public long checkSum;
+ public boolean doLoop;
+ public volatile long loopCount;
+ public volatile boolean targetIsInLoop;
+
+ public void run() {
+ try {
+ msgHL("Executing test case " + getClass().getName());
+ warmUp();
+ runTest();
+ } catch (Exception e) {
+ Asserts.fail("Unexpected Exception", e);
+ }
+ }
+
+ public void warmUp() {
+ int callCount = COMPILE_THRESHOLD + 1000;
+ doLoop = true;
+ while (callCount-- > 0) {
+ dontinline_testMethod();
+ }
+ }
+
+ public abstract void runTest() throws Exception;
+ public abstract void dontinline_testMethod();
+
+ public long dontinline_endlessLoop() {
+ long cs = checkSum;
+ while (doLoop && loopCount-- > 0) {
+ targetIsInLoop = true;
+ checkSum += checkSum % ++cs;
+ }
+ loopCount = 3;
+ targetIsInLoop = false;
+ return checkSum;
+ }
+
+ public void waitUntilTargetThreadHasEnteredEndlessLoop() throws Exception {
+ while(!targetIsInLoop) {
+ msg("Target has not yet entered the loop. Sleep 200ms.");
+ try { Thread.sleep(200); } catch (InterruptedException e) { /*ignore */ }
+ }
+ msg("Target has entered the loop.");
+ }
+
+ public void terminateEndlessLoop() throws Exception {
+ msg("Terminate endless loop");
+ do {
+ doLoop = false;
+ } while(targetIsInLoop);
+ }
+
+ public void msg(String m) {
+ System.out.println();
+ System.out.println("### " + m);
+ System.out.println();
+ }
+
+ public void msgHL(String m) {
+ System.out.println();
+ System.out.println("#####################################################");
+ System.out.println("### " + m);
+ System.out.println("###");
+ System.out.println();
+ }
+ }
+
+ /**
+ * Starts target thread T and then queries monitor information for T using JVMTI's GetOwnedMonitorInfo().
+ * With escape analysis enabled the jit compiled method {@link #dontinline_testMethod()} has
+ * scalar replaced objects with eliminated (nested) locking in scope when the monitor
+ * information is retrieved. Effectively the objects escape through the JVMTI call. This works
+ * only with RFE 8227745. Without it escape analysis needs to be disabled.
+ */
+ public static class TestCase_1 extends TestCaseBase {
+
+ public void runTest() throws Exception {
+ loopCount = 1L << 62; // endless loop
+ Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread");
+ t1.start();
+ try {
+ waitUntilTargetThreadHasEnteredEndlessLoop();
+ int expectedMonitorCount = 1;
+ int resultSize = expectedMonitorCount + 3;
+ Object[] ownedMonitors = new Object[resultSize];
+ msg("Get monitor info");
+ int monitorCount = getOwnedMonitorInfo(t1, ownedMonitors);
+ terminateEndlessLoop();
+ t1.join();
+ Asserts.assertGreaterThanOrEqual(monitorCount, 0, "getOwnedMonitorsFor() call failed");
+ msg("Monitor info:");
+ for (int i = 0; i < monitorCount; i++) {
+ System.out.println(i + ": cls=" + (ownedMonitors[i] != null ? ownedMonitors[i].getClass() : null));
+ }
+ Asserts.assertEQ(monitorCount, expectedMonitorCount, "unexpected monitor count returned by getOwnedMonitorsFor()");
+ Asserts.assertNotNull(ownedMonitors[0]);
+ Asserts.assertSame(ownedMonitors[0].getClass(), LockCls.class);
+ } finally {
+ terminateEndlessLoop();
+ t1.join();
+ }
+ }
+
+ public void dontinline_testMethod() {
+ LockCls l1 = new LockCls(); // to be scalar replaced
+ synchronized (l1) {
+ inlinedTestMethodWithNestedLocking(l1);
+ }
+ }
+
+ public void inlinedTestMethodWithNestedLocking(LockCls l1) {
+ synchronized (l1) { // nested
+ dontinline_endlessLoop();
+ }
+ }
+ }
+
+ /**
+ * Similar to {@link TestCase_1}. Additionally the target thread T has got eliminated locking
+ * for a synchronized method of a different type {@linkplain LockCls2}.
+ */
+ public static class TestCase_2 extends TestCaseBase {
+
+ public void runTest() throws Exception {
+ loopCount = 1L << 62; // endless loop
+ Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread");
+ t1.start();
+ try {
+ waitUntilTargetThreadHasEnteredEndlessLoop();
+ int expectedMonitorCount = 2;
+ int resultSize = expectedMonitorCount + 3;
+ Object[] ownedMonitors = new Object[resultSize];
+ msg("Get monitor info");
+ int monitorCount = getOwnedMonitorInfo(t1, ownedMonitors);
+ terminateEndlessLoop();
+ t1.join();
+ Asserts.assertGreaterThanOrEqual(monitorCount, 0, "getOwnedMonitorsFor() call failed");
+ msg("Monitor info:");
+ for (int i = 0; i < monitorCount; i++) {
+ System.out.println(i + ": cls=" + (ownedMonitors[i] != null ? ownedMonitors[i].getClass() : null));
+ }
+ Asserts.assertEQ(monitorCount, expectedMonitorCount, "unexpected monitor count returned by getOwnedMonitorsFor()");
+ Asserts.assertNotNull(ownedMonitors[0]);
+ Asserts.assertSame(ownedMonitors[0].getClass(), LockCls2.class);
+
+ Asserts.assertNotNull(ownedMonitors[1]);
+ Asserts.assertSame(ownedMonitors[1].getClass(), LockCls.class);
+ } finally {
+ terminateEndlessLoop();
+ t1.join();
+ }
+ }
+
+ public void dontinline_testMethod() {
+ LockCls l1 = new LockCls();
+ synchronized (l1) {
+ inlinedTestMethodWithNestedLocking(l1);
+ }
+ }
+
+ public void inlinedTestMethodWithNestedLocking(LockCls l1) {
+ synchronized (l1) {
+ dontinline_testMethod2();
+ }
+ }
+
+ public void dontinline_testMethod2() {
+ // Call synchronized method. Receiver of the call will be scalar replaced,
+ // and locking will be eliminated. Here we use a different type.
+ new LockCls2().inline_synchronized_testMethod(this);
+ }
+ }
+
+ public static class LockCls {
+ }
+
+ public static class LockCls2 {
+ public synchronized void inline_synchronized_testMethod(TestCaseBase testCase) {
+ testCase.dontinline_endlessLoop();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorInfo/libGetOwnedMonitorInfoWithEATest.c Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 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
+ * 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 <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define FAILED -1
+
+static jvmtiEnv *jvmti;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+static void ShowErrorMessage(jvmtiEnv *jvmti, jvmtiError errCode, const char *message) {
+ char *errMsg;
+ jvmtiError result;
+
+ result = (*jvmti)->GetErrorName(jvmti, errCode, &errMsg);
+ if (result == JVMTI_ERROR_NONE) {
+ fprintf(stderr, "%s: %s (%d)\n", message, errMsg, errCode);
+ (*jvmti)->Deallocate(jvmti, (unsigned char *)errMsg);
+ } else {
+ fprintf(stderr, "%s (%d)\n", message, errCode);
+ }
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ jint res;
+ JNIEnv *env;
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &env),
+ JNI_VERSION_9);
+ if (res != JNI_OK || env == NULL) {
+ fprintf(stderr, "Error: GetEnv call failed(%d)!\n", res);
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_9;
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res;
+ jvmtiError err;
+ jvmtiCapabilities caps;
+
+ printf("Agent_OnLoad started\n");
+
+ memset(&caps, 0, sizeof(caps));
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ caps.can_get_owned_monitor_info = 1;
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "Agent_OnLoad: error in JVMTI AddCapabilities");
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->GetCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "Agent_OnLoad: error in JVMTI GetCapabilities");
+ return JNI_ERR;
+ }
+
+ if (!caps.can_get_owned_monitor_info) {
+ fprintf(stderr, "Warning: GetOwnedMonitorInfo is not implemented\n");
+ return JNI_ERR;
+ }
+
+ printf("Agent_OnLoad finished\n");
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Java_GetOwnedMonitorInfoWithEATest_getOwnedMonitorInfo(JNIEnv *env, jclass cls, jobject targetThread, jobjectArray resOwnedMonitors) {
+ jvmtiError err;
+ jvmtiThreadInfo threadInfo;
+ jint monitorCount;
+ jobject* monitors;
+ jint idx;
+
+ err = (*jvmti)->GetThreadInfo(jvmti, targetThread, &threadInfo);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "getOwnedMonitorsFor: error in JVMTI GetThreadInfo");
+ return FAILED;
+ }
+
+ err = (*jvmti)->GetOwnedMonitorInfo(jvmti, targetThread, &monitorCount, &monitors);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "getOwnedMonitorsFor: error in JVMTI GetOwnedMonitorInfo");
+ return FAILED;
+ }
+
+ printf("getOwnedMonitorsFor: %s owns %d monitor(s)\n", threadInfo.name, monitorCount);
+
+ for (idx = 0; idx < monitorCount; idx++) {
+ (*env)->SetObjectArrayElement(env, resOwnedMonitors, idx, monitors[idx]);
+ }
+
+ (*jvmti)->Deallocate(jvmti, (unsigned char *) monitors);
+ (*jvmti)->Deallocate(jvmti, (unsigned char *) threadInfo.name);
+ return monitorCount;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorStackDepthInfo/GetOwnedMonitorStackDepthInfoWithEATest.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 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
+ * 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 8230677
+ * @summary Test JVMTI's GetOwnedMonitorStackDepthInfo with scalar replaced objects and eliminated locks on stack (optimizations based on escape analysis).
+ * @comment Without RFE 8227745 escape analysis needs to be switched off to pass the test. For the implementation of RFE 8227745 it serves as a regression test.
+ * @requires (vm.compMode != "Xcomp" & vm.compiler2.enabled)
+ * @library /test/lib
+ * @compile GetOwnedMonitorStackDepthInfoWithEATest.java
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking -XX:-UseOptoBiasInlining
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ * @run main/othervm/native
+ * -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
+ * -XX:+UnlockDiagnosticVMOptions
+ * -Xms128m -Xmx128m
+ * -XX:CompileCommand=dontinline,*::dontinline_*
+ * -XX:+PrintCompilation
+ * -XX:+PrintInlining
+ * -XX:-TieredCompilation
+ * -Xbatch
+ * -XX:CICompilerCount=1
+ * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
+ * GetOwnedMonitorStackDepthInfoWithEATest
+ */
+
+import jdk.test.lib.Asserts;
+
+public class GetOwnedMonitorStackDepthInfoWithEATest {
+
+ public static final int COMPILE_THRESHOLD = 20000;
+
+ /**
+ * Native wrapper arround JVMTI's GetOwnedMonitorStackDepthInfo().
+ * @param t The thread for which the owned monitors information should be retrieved.
+ * @param ownedMonitors Array filled in by the call with the objects associated
+ * with the monitors owned by the given thread.
+ * @param depths Per owned monitor the depth of the frame were it was locked.
+ * Filled in by the call
+ * @return Number of monitors owned by the given thread.
+ */
+ public static native int getOwnedMonitorStackDepthInfo(Thread t, Object[] ownedMonitors, int[] depths);
+
+ public static void main(String[] args) throws Exception {
+ new GetOwnedMonitorStackDepthInfoWithEATest().runTest();
+ }
+
+ public void runTest() throws Exception {
+ new TestCase_1().run();
+ new TestCase_2().run();
+ }
+
+ public static abstract class TestCaseBase implements Runnable {
+
+ public long checkSum;
+ public boolean doLoop;
+ public volatile long loopCount;
+ public volatile boolean targetIsInLoop;
+
+ public void run() {
+ try {
+ msgHL("Executing test case " + getClass().getName());
+ warmUp();
+ runTest();
+ } catch (Exception e) {
+ Asserts.fail("Unexpected Exception", e);
+ }
+ }
+
+ public void warmUp() {
+ int callCount = COMPILE_THRESHOLD + 1000;
+ doLoop = true;
+ while (callCount-- > 0) {
+ dontinline_testMethod();
+ }
+ }
+
+ public abstract void runTest() throws Exception;
+ public abstract void dontinline_testMethod();
+
+ public long dontinline_endlessLoop() {
+ long cs = checkSum;
+ while (doLoop && loopCount-- > 0) {
+ targetIsInLoop = true;
+ checkSum += checkSum % ++cs;
+ }
+ loopCount = 3;
+ targetIsInLoop = false;
+ return checkSum;
+ }
+
+ public void waitUntilTargetThreadHasEnteredEndlessLoop() throws Exception {
+ while(!targetIsInLoop) {
+ msg("Target has not yet entered the loop. Sleep 200ms.");
+ try { Thread.sleep(200); } catch (InterruptedException e) { /*ignore */ }
+ }
+ msg("Target has entered the loop.");
+ }
+
+ public void terminateEndlessLoop() throws Exception {
+ msg("Terminate endless loop");
+ do {
+ doLoop = false;
+ } while(targetIsInLoop);
+ }
+
+ public void msg(String m) {
+ System.out.println();
+ System.out.println("### " + m);
+ System.out.println();
+ }
+
+ public void msgHL(String m) {
+ System.out.println();
+ System.out.println("#####################################################");
+ System.out.println("### " + m);
+ System.out.println("###");
+ System.out.println();
+ }
+ }
+
+ /**
+ * Starts target thread T and then queries monitor information for T using JVMTI's GetOwnedMonitorStackDepthInfo().
+ * With escape analysis enabled the jit compiled method {@link #dontinline_testMethod()} has
+ * scalar replaced objects with eliminated (nested) locking in scope when the monitor
+ * information is retrieved. Effectively the objects escape through the JVMTI call. This works
+ * only with RFE 8227745. Without it escape analysis needs to be disabled.
+ */
+ public static class TestCase_1 extends TestCaseBase {
+
+ public void runTest() throws Exception {
+ loopCount = 1L << 62; // endless loop
+ Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread");
+ try {
+ t1.start();
+ waitUntilTargetThreadHasEnteredEndlessLoop();
+ int expectedMonitorCount = 1;
+ int resultSize = expectedMonitorCount + 3;
+ Object[] ownedMonitors = new Object[resultSize];
+ int[] depths = new int[resultSize];
+ msg("Get monitor info");
+ int monitorCount = getOwnedMonitorStackDepthInfo(t1, ownedMonitors, depths);
+ Asserts.assertGreaterThanOrEqual(monitorCount, 0, "getOwnedMonitorsFor() call failed");
+ msg("Monitor info:");
+ for (int i = 0; i < monitorCount; i++) {
+ System.out.println(i + ": cls=" + (ownedMonitors[i] != null ? ownedMonitors[i].getClass() : null) + " depth=" + depths[i]);
+ }
+ Asserts.assertEQ(monitorCount, expectedMonitorCount, "unexpected monitor count returned by getOwnedMonitorsFor()");
+ Asserts.assertNotNull(ownedMonitors[0]);
+ Asserts.assertSame(ownedMonitors[0].getClass(), LockCls.class);
+ Asserts.assertEQ(depths[0], 1, "unexpected depth for owned monitor at index 0");
+ } finally {
+ terminateEndlessLoop();
+ t1.join();
+ }
+ }
+
+ public void dontinline_testMethod() {
+ LockCls l1 = new LockCls(); // to be scalar replaced
+ synchronized (l1) {
+ inlinedTestMethodWithNestedLocking(l1);
+ }
+ }
+
+ public void inlinedTestMethodWithNestedLocking(LockCls l1) {
+ synchronized (l1) { // nested
+ dontinline_endlessLoop();
+ }
+ }
+ }
+
+ /**
+ * Similar to {@link TestCase_1}. Additionally the target thread T has got eliminated locking
+ * for a synchronized method of a different type {@linkplain LockCls2}.
+ */
+ public static class TestCase_2 extends TestCaseBase {
+
+ public void runTest() throws Exception {
+ loopCount = 1L << 62; // endless loop
+ Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread");
+ t1.start();
+ try {
+ waitUntilTargetThreadHasEnteredEndlessLoop();
+ int expectedMonitorCount = 2;
+ int resultSize = expectedMonitorCount + 3;
+ Object[] ownedMonitors = new Object[resultSize];
+ int[] depths = new int[resultSize];
+ msg("Get monitor info");
+ int monitorCount = getOwnedMonitorStackDepthInfo(t1, ownedMonitors, depths);
+ terminateEndlessLoop();
+ t1.join();
+ Asserts.assertGreaterThanOrEqual(monitorCount, 0, "getOwnedMonitorsFor() call failed");
+ msg("Monitor info:");
+ for (int i = 0; i < monitorCount; i++) {
+ System.out.println(i + ": cls=" + (ownedMonitors[i] != null ? ownedMonitors[i].getClass() : null) + " depth=" + depths[i]);
+ }
+ Asserts.assertEQ(monitorCount, expectedMonitorCount, "unexpected monitor count returned by getOwnedMonitorsFor()");
+ Asserts.assertNotNull(ownedMonitors[0]);
+ Asserts.assertSame(ownedMonitors[0].getClass(), LockCls2.class);
+ Asserts.assertEQ(depths[0], 1, "unexpected depth for owned monitor at index 0");
+
+ Asserts.assertNotNull(ownedMonitors[1]);
+ Asserts.assertSame(ownedMonitors[1].getClass(), LockCls.class);
+ Asserts.assertEQ(depths[1], 3, "unexpected depth for owned monitor at index 1");
+ } finally {
+ terminateEndlessLoop();
+ t1.join();
+ }
+ }
+
+ public void dontinline_testMethod() {
+ LockCls l1 = new LockCls();
+ synchronized (l1) {
+ inlinedTestMethodWithNestedLocking(l1);
+ }
+ }
+
+ public void inlinedTestMethodWithNestedLocking(LockCls l1) {
+ synchronized (l1) {
+ dontinline_testMethod2();
+ }
+ }
+
+ public void dontinline_testMethod2() {
+ // Call synchronized method. Receiver of the call will be scalar replaced,
+ // and locking will be eliminated. Here we use a different type.
+ new LockCls2().inline_synchronized_testMethod(this);
+ }
+ }
+
+ public static class LockCls {
+ }
+
+ public static class LockCls2 {
+ public synchronized void inline_synchronized_testMethod(TestCaseBase testCase) {
+ testCase.dontinline_endlessLoop();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorStackDepthInfo/libGetOwnedMonitorStackDepthInfoWithEATest.c Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 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
+ * 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 <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define FAILED -1
+
+static jvmtiEnv *jvmti;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+static void ShowErrorMessage(jvmtiEnv *jvmti, jvmtiError errCode, const char *message) {
+ char *errMsg;
+ jvmtiError result;
+
+ result = (*jvmti)->GetErrorName(jvmti, errCode, &errMsg);
+ if (result == JVMTI_ERROR_NONE) {
+ fprintf(stderr, "%s: %s (%d)\n", message, errMsg, errCode);
+ (*jvmti)->Deallocate(jvmti, (unsigned char *)errMsg);
+ } else {
+ fprintf(stderr, "%s (%d)\n", message, errCode);
+ }
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ jint res;
+ JNIEnv *env;
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &env),
+ JNI_VERSION_9);
+ if (res != JNI_OK || env == NULL) {
+ fprintf(stderr, "Error: GetEnv call failed(%d)!\n", res);
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_9;
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res;
+ jvmtiError err;
+ jvmtiCapabilities caps;
+
+ printf("Agent_OnLoad started\n");
+
+ memset(&caps, 0, sizeof(caps));
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ caps.can_get_owned_monitor_stack_depth_info = 1;
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "Agent_OnLoad: error in JVMTI AddCapabilities");
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->GetCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "Agent_OnLoad: error in JVMTI GetCapabilities");
+ return JNI_ERR;
+ }
+
+ if (!caps.can_get_owned_monitor_stack_depth_info) {
+ fprintf(stderr, "Warning: GetOwnedMonitorStackDepthInfo is not implemented\n");
+ return JNI_ERR;
+ }
+
+ printf("Agent_OnLoad finished\n");
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Java_GetOwnedMonitorStackDepthInfoWithEATest_getOwnedMonitorStackDepthInfo(JNIEnv *env, jclass cls, jobject targetThread, jobjectArray ownedMonitors, jintArray depths) {
+ jvmtiError err;
+ jvmtiThreadInfo threadInfo;
+ jint monitorCount;
+ jvmtiMonitorStackDepthInfo* stackDepthInfo;
+ jint* depthsPtr;
+ jint idx = 0;
+
+ err = (*jvmti)->GetThreadInfo(jvmti, targetThread, &threadInfo);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "getOwnedMonitorsFor: error in JVMTI GetThreadInfo");
+ return FAILED;
+ }
+
+ err = (*jvmti)->GetOwnedMonitorStackDepthInfo(jvmti, targetThread, &monitorCount, &stackDepthInfo);
+ if (err != JVMTI_ERROR_NONE) {
+ ShowErrorMessage(jvmti, err,
+ "getOwnedMonitorsFor: error in JVMTI GetOwnedMonitorStackDepthInfo");
+ return FAILED;
+ }
+
+ printf("getOwnedMonitorsFor: %s owns %d monitor(s)\n", threadInfo.name, monitorCount);
+
+ depthsPtr = (*env)->GetIntArrayElements(env, depths, NULL);
+ for (idx = 0; idx < monitorCount; idx++) {
+ (*env)->SetObjectArrayElement(env, ownedMonitors, idx, stackDepthInfo[idx].monitor);
+ depthsPtr[idx] = stackDepthInfo[idx].stack_depth;
+ }
+ (*env)->ReleaseIntArrayElements(env, depths, depthsPtr, 0);
+
+ (*jvmti)->Deallocate(jvmti, (unsigned char *) stackDepthInfo);
+ (*jvmti)->Deallocate(jvmti, (unsigned char *) threadInfo.name);
+ return monitorCount;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/test/hotspot/jtreg/serviceability/sa/TestUniverse.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/serviceability/sa/TestUniverse.java Wed Oct 09 23:22:56 2019 +0200
@@ -86,7 +86,7 @@
break;
case Shenandoah:
- expStrings.add("Shenandoah Heap");
+ expStrings.add("Shenandoah heap");
break;
}
--- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/HighWaterMarkTest.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,8 +42,6 @@
* Test verifies that MinMetaspaceFreeRatio/MaxMetaspaceFreeRatio settings
* affect the frequency of GC. (High-water mark)
*
- * Note: The test doesn't check the GC count if CMS is used.
- *
* Quoting: Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning
* <pre>
* Class metadata is deallocated when the corresponding Java class is unloaded.
@@ -175,11 +173,6 @@
throw new Fault("Committed amount hasn't achieved " + bytes2k(committedLevel));
}
- if (VMRuntimeEnvUtils.isVMOptionEnabled("UseConcMarkSweepGC")) {
- System.out.println("ConcMarkSweep is used, cannot count GC");
- return;
- }
-
int gcCount = getMetaspaceGCCount();
if (gcCount < 0) {
// perhpas, it's better to silently pass here... Let's see.
--- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_0_1/TestDescription.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_0_1/TestDescription.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,11 @@
* @summary converted from VM Testbase metaspace/gc/watermark_0_1.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
+ * @comment Don't run test in configurations where we can't reliably count number of metaspace triggered GCs
+ * @requires vm.gc != null | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "ConcMarkSweep"
+ * @requires vm.gc != "Z"
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
--- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_10_20/TestDescription.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_10_20/TestDescription.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,11 @@
* @summary converted from VM Testbase metaspace/gc/watermark_10_20.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
+ * @comment Don't run test in configurations where we can't reliably count number of metaspace triggered GCs
+ * @requires vm.gc != null | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "ConcMarkSweep"
+ * @requires vm.gc != "Z"
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
--- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_70_80/TestDescription.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_70_80/TestDescription.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,11 @@
* @summary converted from VM Testbase metaspace/gc/watermark_70_80.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
+ * @comment Don't run test in configurations where we can't reliably count number of metaspace triggered GCs
+ * @requires vm.gc != null | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "ConcMarkSweep"
+ * @requires vm.gc != "Z"
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
--- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_99_100/TestDescription.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_99_100/TestDescription.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,11 @@
* @summary converted from VM Testbase metaspace/gc/watermark_99_100.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
+ * @comment Don't run test in configurations where we can't reliably count number of metaspace triggered GCs
+ * @requires vm.gc != null | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark
+ * @requires vm.gc != "ConcMarkSweep"
+ * @requires vm.gc != "Z"
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/JdbStopInNotificationThreadTest.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,148 @@
+/*
+ * 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
+ * @summary Tests that the breakpoint in the notification listener is hit when the
+ * notification thread is enabled and is not hit when the notification thread is disabled
+ * (the service thread delivers the notifications in this case).
+ *
+ * @library /test/lib
+ * @run compile -g JdbStopInNotificationThreadTest.java
+ * @run main/othervm JdbStopInNotificationThreadTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import lib.jdb.JdbCommand;
+import lib.jdb.JdbTest;
+
+import javax.management.Notification;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationListener;
+import java.lang.management.*;
+import java.util.Collection;
+import java.util.LinkedList;
+
+class JdbStopInNotificationThreadTestTarg {
+
+ private static volatile boolean done = false;
+
+ private static final MemoryPoolMXBean tenuredGenPool =
+ findTenuredGenPool();
+
+ public static void main(String[] args) throws Exception {
+ test(); // @1 breakpoint
+ }
+
+ private static void test() throws Exception {
+ setPercentageUsageThreshold(0.1);
+ MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
+ NotificationEmitter emitter = (NotificationEmitter) mbean;
+ emitter.addNotificationListener(new NotificationListener() {
+ public void handleNotification(Notification n, Object hb) {
+ System.out.println("Notification received:" + n.getType());
+ if (n.getType().equals(
+ MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
+ done = true;
+ System.out.println("Notification MEMORY_THRESHOLD_EXCEEDED received:");
+ long maxMemory = tenuredGenPool.getUsage().getMax();
+ long usedMemory = tenuredGenPool.getUsage().getUsed();
+ System.out.println("Memory usage low!!!"); // @2 breakpoint
+ double percentageUsed = ((double) usedMemory) / maxMemory;
+ System.out.println("percentageUsed = " + percentageUsed);
+ }
+ }
+ }, null, null);
+
+ Collection<Object[]> numbers = new LinkedList();
+ long counter = 0;
+ while (!done) {
+ numbers.add(new Object[1000]);
+ counter++;
+ if (counter % 1000 == 0) {
+ Thread.sleep(100);
+ }
+ }
+ System.out.println("Done");
+ }
+
+ private static MemoryPoolMXBean findTenuredGenPool() {
+ for (MemoryPoolMXBean pool :
+ ManagementFactory.getMemoryPoolMXBeans()) {
+ if (pool.getType() == MemoryType.HEAP &&
+ pool.isUsageThresholdSupported()) {
+ return pool;
+ }
+ }
+ throw new RuntimeException("Could not find tenured space");
+ }
+
+ public static void setPercentageUsageThreshold(double percentage) {
+ if (percentage <= 0.0 || percentage > 1.0) {
+ throw new IllegalArgumentException("Percentage not in range");
+ }
+ System.out.println("Setting threashold for pool " + tenuredGenPool.getName() + " percentage:" + percentage);
+ long maxMemory = tenuredGenPool.getUsage().getMax();
+ long warningThreshold = (long) (maxMemory * percentage);
+ tenuredGenPool.setUsageThreshold(warningThreshold);
+ }
+}
+
+public class JdbStopInNotificationThreadTest extends JdbTest {
+
+ private static final String DEBUGGEE_CLASS = JdbStopInNotificationThreadTestTarg.class.getName();
+ private static final String PATTERN1_TEMPLATE = "^Breakpoint hit: \"thread=Notification Thread\", " +
+ "JdbStopInNotificationThreadTestTarg\\$1\\.handleNotification\\(\\), line=%LINE_NUMBER.*\\R%LINE_NUMBER\\s+System\\.out\\.println\\(\"Memory usage low!!!\"\\);.*";
+
+ private JdbStopInNotificationThreadTest() {
+ super(DEBUGGEE_CLASS);
+ }
+
+ public static void main(String argv[]) {
+ new JdbStopInNotificationThreadTest().run();
+ }
+
+ @Override
+ protected void runCases() {
+ if (isNotificationThreadDisabled()) {
+ System.out.println("Notification Thread is disabled. Skipping the test");
+ return;
+ }
+ int bpLine2 = parseBreakpoints(getTestSourcePath("JdbStopInNotificationThreadTest.java"), 2).get(0);
+ jdb.command(JdbCommand.stopAt(DEBUGGEE_CLASS + "$1", bpLine2));
+ String pattern = PATTERN1_TEMPLATE.replaceAll("%LINE_NUMBER", String.valueOf(bpLine2));
+ jdb.command(JdbCommand.cont());
+ new OutputAnalyzer(jdb.getJdbOutput()).shouldMatch(pattern);
+ }
+
+ private boolean isNotificationThreadDisabled() {
+ int bpLine1 = parseBreakpoints(getTestSourcePath("JdbStopInNotificationThreadTest.java"), 1).get(0);
+ jdb.command(JdbCommand.stopAt(DEBUGGEE_CLASS, bpLine1));
+ jdb.command(JdbCommand.run());
+ jdb.command(JdbCommand.threads());
+ if (new OutputAnalyzer(jdb.getJdbOutput()).getOutput().contains("Notification Thread")) {
+ return false;
+ }
+ return true;
+ }
+}
--- a/test/jdk/java/net/DatagramSocket/DatagramTimeout.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/jdk/java/net/DatagramSocket/DatagramTimeout.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,32 +23,56 @@
/**
* @test
- * @bug 4163126
- * @summary test to see if timeout hangs
- * @run main/timeout=15 DatagramTimeout
+ * @bug 4163126 8222829
+ * @summary Test to see if timeout hangs. Also checks that
+ * negative timeout value fails as expected.
+ * @run testng DatagramTimeout
*/
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;
+import java.nio.channels.DatagramChannel;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.expectThrows;
+
public class DatagramTimeout {
- public static void main(String[] args) throws Exception {
- boolean success = false;
- DatagramSocket sock = new DatagramSocket();
+ private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+ private static final Class<SocketTimeoutException> STE = SocketTimeoutException.class;
- try {
- DatagramPacket p;
+ /**
+ * Test DatagramSocket setSoTimeout with a valid timeout value.
+ */
+ @Test
+ public void testSetTimeout() throws Exception {
+ try (DatagramSocket s = new DatagramSocket()) {
byte[] buffer = new byte[50];
- p = new DatagramPacket(buffer, buffer.length);
- sock.setSoTimeout(2);
- sock.receive(p);
- } catch (SocketTimeoutException e) {
- success = true;
- } finally {
- sock.close();
+ DatagramPacket p = new DatagramPacket(buffer, buffer.length);
+ s.setSoTimeout(2);
+ expectThrows(STE, () -> s.receive(p));
}
- if (!success)
- throw new RuntimeException("Socket timeout failure.");
}
+ /**
+ * Test DatagramSocket setSoTimeout with a negative timeout.
+ */
+ @Test
+ public void testSetNegativeTimeout() throws Exception {
+ try (DatagramSocket s = new DatagramSocket()) {
+ expectThrows(IAE, () -> s.setSoTimeout(-1));
+ }
+ }
+
+ /**
+ * Test DatagramSocketAdaptor setSoTimeout with a negative timeout.
+ */
+ @Test
+ public void testNegativeTimeout() throws Exception {
+ try (DatagramChannel dc = DatagramChannel.open()) {
+ var s = dc.socket();
+ expectThrows(IAE, () -> s.setSoTimeout(-1));
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/DatagramChannel/AddressesAfterDisconnect.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,109 @@
+/*
+ * 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
+ * @library /test/lib
+ * @summary Test DatagramChannel local address after disconnect.
+ * @requires (os.family != "mac")
+ * @run testng/othervm AddressesAfterDisconnect
+ * @run testng/othervm -Djava.net.preferIPv6Addresses=true AddressesAfterDisconnect
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true AddressesAfterDisconnect
+ */
+
+import jdk.test.lib.net.IPSupport;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.StandardProtocolFamily;
+import java.nio.channels.DatagramChannel;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+public class AddressesAfterDisconnect {
+
+ public static void main(String[] args) throws IOException {
+ new AddressesAfterDisconnect().execute();
+ }
+
+ @Test
+ public void execute() throws IOException {
+ IPSupport.throwSkippedExceptionIfNonOperational();
+ boolean preferIPv6 = Boolean.getBoolean("java.net.preferIPv6Addresses");
+
+ // test with default protocol family
+ try (DatagramChannel dc = DatagramChannel.open()) {
+ System.out.println("Test with default");
+ dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ test(dc);
+ test(dc);
+ }
+
+ if (IPSupport.hasIPv6()) {
+ // test with IPv6 only
+ System.out.println("Test with IPv6 only");
+ try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) {
+ dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ test(dc);
+ test(dc);
+ }
+ }
+
+ if (IPSupport.hasIPv4() && !preferIPv6) {
+ // test with IPv4 only
+ System.out.println("Test with IPv4 only");
+ try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) {
+ dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ test(dc);
+ test(dc);
+ }
+ }
+ }
+
+ /**
+ * Connect DatagramChannel to a server, write a datagram and disconnect. Invoke
+ * a second or subsequent time with the same DatagramChannel instance to check
+ * that disconnect works as expected.
+ */
+ static void test(DatagramChannel dc) throws IOException {
+ SocketAddress local = dc.getLocalAddress();
+ try (DatagramChannel server = DatagramChannel.open()) {
+ server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ SocketAddress remote = server.getLocalAddress();
+ dc.connect(remote);
+ assertTrue(dc.isConnected());
+ // comment the following two lines on OS X to see JDK-8231259
+ assertEquals(dc.getLocalAddress(), local, "local address after connect");
+ assertEquals(dc.getRemoteAddress(), remote, "remote address after connect");
+ dc.disconnect();
+ assertFalse(dc.isConnected());
+ assertEquals(dc.getLocalAddress(), local, "local address after disconnect");
+ assertEquals(dc.getRemoteAddress(), null, "remote address after disconnect");
+ }
+ }
+
+}
--- a/test/jdk/java/util/zip/FlaterTest.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/jdk/java/util/zip/FlaterTest.java Wed Oct 09 23:22:56 2019 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,10 +23,11 @@
/**
* @test
- * @bug 6348045 6341887
+ * @bug 6348045 6341887 8231770
* @summary GZipOutputStream/InputStream goes critical(calls JNI_Get*Critical)
- * and causes slowness. This test uses Deflater and Inflater directly.
+ * and causes slowness. This test uses Deflater and Inflater directly.
* @key randomness
+ * @run main/othervm -Xcheck:jni FlaterTest
*/
import java.nio.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/management/mxbean/ThreadStartTest.java Wed Oct 09 23:22:56 2019 +0200
@@ -0,0 +1,56 @@
+/*
+ * 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 8231666
+ * @summary Test checks that new threads could be successfully started when the thread
+ * table introduced in 8185005 is growing. The test enables the thread table by calling
+ * ThreadMXBean.getThreadInfo() and then creates a number of threads to force the thread
+ * table to grow.
+ *
+ * @run main ThreadStartTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+
+public class ThreadStartTest {
+ public static void main(String[] args) {
+
+ ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
+ // Enable thread table
+ mbean.getThreadInfo(Thread.currentThread().getId());
+
+ // Create a large number of threads to make the thread table grow
+ for (int i = 0; i < 1000; i++) {
+ Thread t = new Thread(() -> {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ }
+ });
+ t.start();
+ }
+ }
+}
--- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java Wed Oct 09 23:22:56 2019 +0200
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8189131
+ * @bug 8189131 8231887
* @summary Interoperability tests with Comodo RSA, ECC, userTrust RSA, and
* userTrust ECC CAs
* @build ValidatePathWithParams
@@ -112,13 +112,66 @@
// Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
// STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB,
+ // SERIALNUMBER=04058690
+ // Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: a0c7cabcc25ed9358ded02cc1d485545
+ // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIH0TCCBrmgAwIBAgIRAKDHyrzCXtk1je0CzB1IVUUwDQYJKoZIhvcNAQELBQAw\n" +
+ "gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" +
+ "BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD\n" +
+ "VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" +
+ "ciBDQTAeFw0xOTA5MzAwMDAwMDBaFw0yMTEyMjgyMzU5NTlaMIIBPjERMA8GA1UE\n" +
+ "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" +
+ "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRAw\n" +
+ "DgYDVQQHEwdTYWxmb3JkMRYwFAYDVQQJEw1UcmFmZm9yZCBSb2FkMRYwFAYDVQQJ\n" +
+ "Ew1FeGNoYW5nZSBRdWF5MSUwIwYDVQQJExwzcmQgRmxvb3IsIDI2IE9mZmljZSBW\n" +
+ "aWxsYWdlMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxGjAYBgNVBAsTEUNPTU9E\n" +
+ "TyBFViBTR0MgU1NMMTgwNgYDVQQDEy9jb21vZG9yc2FjZXJ0aWZpY2F0aW9uYXV0\n" +
+ "aG9yaXR5LWV2LmNvbW9kb2NhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" +
+ "AQoCggEBAND/eZQBTjpBDsuteKwl+zpTitF8tJzwHAhcQHC2AaLF/GJl1rnjx4Of\n" +
+ "elMhKhN1Od9KU6onHGOd2w4mD4EiYK9TpXwuwTyzfkCmnkqxZjYK3KAJN013o4L+\n" +
+ "8y1zsGVUulpN/GfMaxTb4XdmeSekTP91Phw3xezijBq3sa++1rO5RBaT1IHeHhHv\n" +
+ "iC9WNrG8CIg/j5MyC9i43LZHiRXLER1LzT/MCIRsiG5AEbiYXV5BNd5SiiHtBJ1q\n" +
+ "0ZJH+AxL2ERaT41VCppboZwThmJGGoky9FWjp6z8U6Enx0fAMJIZNEzW6LAJFKPE\n" +
+ "ynEU004jFFCEumPUqqCC4ogxulphY80CAwEAAaOCA3EwggNtMB8GA1UdIwQYMBaA\n" +
+ "FDna/8ooFIqodBMIueQOqdL6fp1pMB0GA1UdDgQWBBQ+S4ZhIrwOoeGs9BBT4uXq\n" +
+ "89Ux/jAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggr\n" +
+ "BgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA7BgwrBgEEAbIxAQIBBQEwKzAp\n" +
+ "BggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwBwYFZ4EM\n" +
+ "AQEwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09N\n" +
+ "T0RPUlNBRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGHBggr\n" +
+ "BgEFBQcBAQR7MHkwUQYIKwYBBQUHMAKGRWh0dHA6Ly9jcnQuY29tb2RvY2EuY29t\n" +
+ "L0NPTU9ET1JTQUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAk\n" +
+ "BggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMDoGA1UdEQQzMDGC\n" +
+ "L2NvbW9kb3JzYWNlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29t\n" +
+ "MIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdQDuS723dc5guuFCaR+r4Z5mow9+\n" +
+ "X7By2IMAxHuJeqj9ywAAAW2DAXefAAAEAwBGMEQCIDqP1einOiPHnaG1fOZMDrEc\n" +
+ "RAxjq3vEl94fp4pkmke7AiBsJOvPE6irgcOO1/lnP7NRuln7iPJjU7T20PEK5/rm\n" +
+ "KwB2AFWB1MIWkDYBSuoLm1c8U/DA5Dh4cCUIFy+jqh0HE9MMAAABbYMBd0kAAAQD\n" +
+ "AEcwRQIhALgUI5XxM1NHbJDdr19h2pe3LhzK4tpuB/OQ9BgCyrGXAiBdr6mNCB/G\n" +
+ "rbdVx0u7iezwC7mq7iaWugR3rrWlSA8fWQB2ALvZ37wfinG1k5Qjl6qSe0c4V5UK\n" +
+ "q1LoGpCWZDaOHtGFAAABbYMBd1oAAAQDAEcwRQIgXbG32dagMeLhuZb+LSpJO1vI\n" +
+ "BmxmRnNdiz5FbG9cCbwCIQCr1X9f+ebT5fhlDUNBURUorTtM8QQciBiueBqvHk7+\n" +
+ "1DANBgkqhkiG9w0BAQsFAAOCAQEAM/A/1dgoc5NP1n+w3SX9qWcN7QT7ExdrnZSl\n" +
+ "Ygn0PF2fx4gz7cvNKucbpQJNA4C9awGydyYK8/o5KDUXt3K7eb1OAZ/NZBjygsJs\n" +
+ "ikXvxlBh8oEoqBOfOtr24l0NGUWnP8Qeu/VPcIMER4V8qX+in0pCXkSd67nkp6Bs\n" +
+ "EcqhDPgmzdSC1gQHsZuBdotG14OfdH1cG1bRK6GadISLG1h8BFukVem42B149v8F\n" +
+ "MCIUQAYprAVv2WlTZKBx9XzuK6IK3+klHZ07Jfvjvt7PPG5HKSMWBMnMaTHKcyQI\n" +
+ "G3t91yw7BnNNInZlBSsFtqjbHhDcr7uruZdbi0rerSsi2qDr0w==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
// ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
// OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
// Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
// ST=Greater Manchester, C=GB
// Serial number: d3df2597cbed1ab6e02ee82021771614
// Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
- private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
"MIIH7jCCBtagAwIBAgIRANPfJZfL7Rq24C7oICF3FhQwDQYJKoZIhvcNAQELBQAw\n" +
"gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" +
"BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD\n" +
@@ -164,60 +217,6 @@
"YrTYerPngjPbZB0bfLOja0vb\n" +
"-----END CERTIFICATE-----";
- // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited,
- // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
- // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
- // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
- // Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
- // ST=Greater Manchester, C=GB
- // Serial number: 720aa2cfa40094521224f901a984b167
- // Valid from: Thu Jun 29 17:00:00 PDT 2017 until: Sun Sep 29 16:59:59 PDT 2019
- private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
- "MIIH8jCCBtqgAwIBAgIQcgqiz6QAlFISJPkBqYSxZzANBgkqhkiG9w0BAQsFADCB\n" +
- "kjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n" +
- "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNV\n" +
- "BAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVy\n" +
- "IENBMB4XDTE3MDYzMDAwMDAwMFoXDTE5MDkyOTIzNTk1OVowggFdMREwDwYDVQQF\n" +
- "EwgwNDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0\n" +
- "ZSBPcmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZ\n" +
- "BgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQG\n" +
- "A1UECRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMG\n" +
- "A1UECRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEaMBgGA1UEChMRQ09N\n" +
- "T0RPIENBIExpbWl0ZWQxGjAYBgNVBAsTEUNPTU9ETyBFViBTR0MgU1NMMTgwNgYD\n" +
- "VQQDEy9jb21vZG9yc2FjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2Nh\n" +
- "LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAND/eZQBTjpBDsut\n" +
- "eKwl+zpTitF8tJzwHAhcQHC2AaLF/GJl1rnjx4OfelMhKhN1Od9KU6onHGOd2w4m\n" +
- "D4EiYK9TpXwuwTyzfkCmnkqxZjYK3KAJN013o4L+8y1zsGVUulpN/GfMaxTb4Xdm\n" +
- "eSekTP91Phw3xezijBq3sa++1rO5RBaT1IHeHhHviC9WNrG8CIg/j5MyC9i43LZH\n" +
- "iRXLER1LzT/MCIRsiG5AEbiYXV5BNd5SiiHtBJ1q0ZJH+AxL2ERaT41VCppboZwT\n" +
- "hmJGGoky9FWjp6z8U6Enx0fAMJIZNEzW6LAJFKPEynEU004jFFCEumPUqqCC4ogx\n" +
- "ulphY80CAwEAAaOCA3QwggNwMB8GA1UdIwQYMBaAFDna/8ooFIqodBMIueQOqdL6\n" +
- "fp1pMB0GA1UdDgQWBBQ+S4ZhIrwOoeGs9BBT4uXq89Ux/jAOBgNVHQ8BAf8EBAMC\n" +
- "BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\n" +
- "TwYDVR0gBEgwRjA7BgwrBgEEAbIxAQIBBQEwKzApBggrBgEFBQcCARYdaHR0cHM6\n" +
- "Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmg\n" +
- "R4ZFaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRWYWxp\n" +
- "ZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwUQYIKwYB\n" +
- "BQUHMAKGRWh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4dGVuZGVk\n" +
- "VmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDov\n" +
- "L29jc3AuY29tb2RvY2EuY29tMDoGA1UdEQQzMDGCL2NvbW9kb3JzYWNlcnRpZmlj\n" +
- "YXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMIIBgAYKKwYBBAHWeQIEAgSC\n" +
- "AXAEggFsAWoAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAVz5\n" +
- "cV7GAAAEAwBHMEUCIQCpgc0Eqw3g4pr+oX88h5xgL1VEAiDpqAhbRtilgYwBbgIg\n" +
- "UaIm+n8AHi55nB//Sb4Nz18GYVcfELfpIzRh1vW9HbYAdwBWFAaaL9fC7NP14b1E\n" +
- "sj7HRna5vJkRXMDvlJhV1onQ3QAAAVz5cVybAAAEAwBIMEYCIQDdsgC4KZ++OP44\n" +
- "X7LbUcNaxe0kFzbctF2L3bnmhp9nXQIhAM0/g+PrZBIBpYlOtzidePi8bBHrLWn2\n" +
- "uBiP3pYIntl4AHcA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFc\n" +
- "+XFeoQAABAMASDBGAiEAoySTb/QKw7JwtZtPHnECEMzgENQSFy58Kl+Mvcd3SmcC\n" +
- "IQD8cU66Ih3ejvt0OTX+lfxQPKyggQfm4Uk/lwn5LEJXbDANBgkqhkiG9w0BAQsF\n" +
- "AAOCAQEAKEaSYWn3Hi8rfJS4cMTJoMkVp2vpPH2dGXySBEy67TEGRw9+f75w3q95\n" +
- "r1m3P+xsR6dBoidTq/6wqUYI51lB4Fq9ylh1Stp5Gj54CuyT+S31l7lD7sl0KMsn\n" +
- "HDUDQHId7hKeORYpiIZOcrKOglKdi1uiGwDgoiLKh98lUrZA6durrhH+sl69wqp2\n" +
- "0XAu+3hurXzCoZFJfyngTO1kt9qcFUAxc5LofIa9QvC6VR7dI4aAh7dUpIRlnjG3\n" +
- "jJ1mUMTqWO6TFTtddb+uQjDqNgkYYYNuSax1WMEIZWbIi13EjXK1GPQUXJe6gQin\n" +
- "NUq9JH9NPK6m8A1YKT+wgzfTDeaV2Q==\n" +
- "-----END CERTIFICATE-----";
-
public void runTest(ValidatePathWithParams pathValidator) throws Exception {
// Validate valid
pathValidator.validate(new String[]{VALID, INT},
@@ -226,7 +225,7 @@
// Validate Revoked
pathValidator.validate(new String[]{REVOKED, INT},
ValidatePathWithParams.Status.REVOKED,
- "Thu Nov 29 08:41:09 PST 2018", System.out);
+ "Wed Oct 02 06:06:24 PDT 2019", System.out);
}
}
@@ -263,13 +262,58 @@
// Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=Sectigo Limited,
// STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB,
+ // SERIALNUMBER=04058690
+ // Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: 7972d9d8472a2d52ad1ee6edfb16cbe1
+ // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGPzCCBeWgAwIBAgIQeXLZ2EcqLVKtHubt+xbL4TAKBggqhkjOPQQDAjCBkjEL\n" +
+ "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" +
+ "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" +
+ "L0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" +
+ "MB4XDTE5MDkzMDAwMDAwMFoXDTIxMTIyODIzNTk1OVowggE6MREwDwYDVQQFEwgw\n" +
+ "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" +
+ "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExEDAOBgNV\n" +
+ "BAcTB1NhbGZvcmQxFjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4\n" +
+ "Y2hhbmdlIFF1YXkxJTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxh\n" +
+ "Z2UxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEWMBQGA1UECxMNQ09NT0RPIEVW\n" +
+ "IFNTTDE4MDYGA1UEAxMvY29tb2RvZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1l\n" +
+ "di5jb21vZG9jYS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS3bqoFLtNG\n" +
+ "7/J9H5GKosDNbYL5SykVmU5FzgSEt81gyAWShkqMSfAnO50fpr65E+o86E+BR3o8\n" +
+ "V9FAU5wuOaGBo4IDcDCCA2wwHwYDVR0jBBgwFoAU007DGbpYWdEcYLdhU0c7p3eP\n" +
+ "+IowHQYDVR0OBBYEFOlnS3MqxwXDpne8IQMXMZHlVKRXMA4GA1UdDwEB/wQEAwIF\n" +
+ "gDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBP\n" +
+ "BgNVHSAESDBGMDsGDCsGAQQBsjEBAgEFATArMCkGCCsGAQUFBwIBFh1odHRwczov\n" +
+ "L3NlY3VyZS5jb21vZG8uY29tL0NQUzAHBgVngQwBATBWBgNVHR8ETzBNMEugSaBH\n" +
+ "hkVodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9FQ0NFeHRlbmRlZFZhbGlk\n" +
+ "YXRpb25TZWN1cmVTZXJ2ZXJDQS5jcmwwgYcGCCsGAQUFBwEBBHsweTBRBggrBgEF\n" +
+ "BQcwAoZFaHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPRUNDRXh0ZW5kZWRW\n" +
+ "YWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8v\n" +
+ "b2NzcC5jb21vZG9jYS5jb20wOgYDVR0RBDMwMYIvY29tb2RvZWNjY2VydGlmaWNh\n" +
+ "dGlvbmF1dGhvcml0eS1ldi5jb21vZG9jYS5jb20wggF8BgorBgEEAdZ5AgQCBIIB\n" +
+ "bASCAWgBZgB1AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABbYME\n" +
+ "EzgAAAQDAEYwRAIgbdo71lBleuJiq+D0ZLp51oVUyWD9EyrtgBSCNwIW4cMCIAqg\n" +
+ "0VFTWHEmAVjaV23fGj3Ybu3mpSiHr6viGlgA2lYaAHUAVYHUwhaQNgFK6gubVzxT\n" +
+ "8MDkOHhwJQgXL6OqHQcT0wwAAAFtgwQTKAAABAMARjBEAiBb/gW1RU7kgFBiNpHx\n" +
+ "LStujKIocyENUTXsMbsac+LktwIgXbEr8vOOCEdBdXQ2F/FKec8ft6gz57mHNmwl\n" +
+ "pp7phbQAdgC72d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAW2DBBM6\n" +
+ "AAAEAwBHMEUCIQDjKN3h86ofR94+JxLFoYuoA+DRtxEY8XGg+NQXlZfUrgIgEoO2\n" +
+ "ZzKbGfohdwj/WtDwJDRX5pjXF4M0nECiwtYXDIwwCgYIKoZIzj0EAwIDSAAwRQIg\n" +
+ "AkIRVQBwrElFjrnqk5XPvnlnwkIm1A70ayqOf1FexoQCIQC8tBTn//RCfrhcgTjd\n" +
+ "ER4wRjFfFoc6lC68OHGVg9CZZg==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
// ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
// OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
// Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
// ST=Greater Manchester, C=GB
// Serial number: 603a5c2f85b63e00ba46ce8c3f6000b0
// Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
- private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
"MIIGXzCCBgWgAwIBAgIQYDpcL4W2PgC6Rs6MP2AAsDAKBggqhkjOPQQDAjCBkjEL\n" +
"MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" +
"BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" +
@@ -307,52 +351,6 @@
"KOC7\n" +
"-----END CERTIFICATE-----";
- // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=COMODO CA Limited,
- // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
- // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
- // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
- // Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
- // ST=Greater Manchester, C=GB
- // Serial number: 414e5d66ec7d15ca504213f2811d57af
- // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019
- private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
- "MIIGYDCCBgWgAwIBAgIQQU5dZux9FcpQQhPygR1XrzAKBggqhkjOPQQDAjCBkjEL\n" +
- "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" +
- "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" +
- "L0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" +
- "MB4XDTE3MDcwNDAwMDAwMFoXDTE5MTAwMzIzNTk1OVowggFZMREwDwYDVQQFEwgw\n" +
- "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" +
- "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZBgNV\n" +
- "BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQGA1UE\n" +
- "CRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMGA1UE\n" +
- "CRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEaMBgGA1UEChMRQ09NT0RP\n" +
- "IENBIExpbWl0ZWQxFjAUBgNVBAsTDUNPTU9ETyBFViBTU0wxODA2BgNVBAMTL2Nv\n" +
- "bW9kb2VjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMFkw\n" +
- "EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt26qBS7TRu/yfR+RiqLAzW2C+UspFZlO\n" +
- "Rc4EhLfNYMgFkoZKjEnwJzudH6a+uRPqPOhPgUd6PFfRQFOcLjmhgaOCA3EwggNt\n" +
- "MB8GA1UdIwQYMBaAFNNOwxm6WFnRHGC3YVNHO6d3j/iKMB0GA1UdDgQWBBTpZ0tz\n" +
- "KscFw6Z3vCEDFzGR5VSkVzAOBgNVHQ8BAf8EBAMCBYAwDAYDVR0TAQH/BAIwADAd\n" +
- "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA7BgwrBgEE\n" +
- "AbIxAQIBBQEwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv\n" +
- "bS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5jb21v\n" +
- "ZG9jYS5jb20vQ09NT0RPRUNDRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVy\n" +
- "Q0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwUQYIKwYBBQUHMAKGRWh0dHA6Ly9jcnQu\n" +
- "Y29tb2RvY2EuY29tL0NPTU9ET0VDQ0V4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNl\n" +
- "cnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29t\n" +
- "MDoGA1UdEQQzMDGCL2NvbW9kb2VjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYu\n" +
- "Y29tb2RvY2EuY29tMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgCkuQmQtBhY\n" +
- "FIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAV0NLqsqAAAEAwBHMEUCIAz9Jjq3\n" +
- "qLUd/a2PYZnLGsEG/MrL7vab5rmGBg8RGAJxAiEA7JJnar07NIjCLLO77xJ3UFcu\n" +
- "UMM3M8JgGC8wbuRwxbUAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ\n" +
- "3QAAAV0NLqjmAAAEAwBHMEUCIHRvPWKr7vPMBWx1gLPkt8inPINWPNSoax178e5A\n" +
- "D0cPAiEAvRL/VP4DLiyHvcU9AOqTzQXGuWCzswWKG59hSm7gS4kAdQDuS723dc5g\n" +
- "uuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAV0NLqsDAAAEAwBGMEQCIFALT043\n" +
- "X5IffLsxIAGXTrWgkZHf12QKgrYKXVB629eOAiAIeci2xi3fUW6mU8tT4LwyjowV\n" +
- "DkrSCw1ZMo0JApsfzTAKBggqhkjOPQQDAgNJADBGAiEA7HUxjwx0MBC+4PuPx4Z1\n" +
- "WpKz7jdHOMTh1sdaoVV5hNoCIQDrnjBFUopXHTvm/rj+aMFIeYejggPqv14KJOqT\n" +
- "gym+uA==\n" +
- "-----END CERTIFICATE-----";
-
public void runTest(ValidatePathWithParams pathValidator) throws Exception {
// Validate valid
pathValidator.validate(new String[]{VALID, INT},
@@ -361,19 +359,61 @@
// Validate Revoked
pathValidator.validate(new String[]{REVOKED, INT},
ValidatePathWithParams.Status.REVOKED,
- "Thu Nov 29 08:12:02 PST 2018", System.out);
+ "Wed Oct 02 06:05:57 PDT 2019", System.out);
}
}
class ComodoUserTrustRSA {
+ // Owner: CN=Sectigo RSA Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
+ // Serial number: 284e39c14b386d889c7299e58cd05a57
+ // Valid from: Thu Nov 01 17:00:00 PDT 2018 until: Tue Dec 31 15:59:59 PST 2030
+ private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGNDCCBBygAwIBAgIQKE45wUs4bYiccpnljNBaVzANBgkqhkiG9w0BAQwFADCB\n" +
+ "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n" +
+ "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n" +
+ "BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx\n" +
+ "MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBkTELMAkGA1UEBhMCR0IxGzAZBgNV\n" +
+ "BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE\n" +
+ "ChMPU2VjdGlnbyBMaW1pdGVkMTkwNwYDVQQDEzBTZWN0aWdvIFJTQSBFeHRlbmRl\n" +
+ "ZCBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4IBDwAwggEKAoIBAQCaoslYBiqFev0Yc4TXPa0s9oliMcn9VaENfTUK4GVT7niB\n" +
+ "QXxC6Mt8kTtvyr5lU92hDQDh2WDPQsZ7oibh75t2kowT3z1S+Sy1GsUDM4NbdOde\n" +
+ "orcmzFm/b4bwD4G/G+pB4EX1HSfjN9eT0Hje+AGvCrd2MmnxJ+Yymv9BH9OB65jK\n" +
+ "rUO9Na4iHr48XWBDFvzsPCJ11Uioof6dRBVp+Lauj88Z7k2X8d606HeXn43h6acp\n" +
+ "LLURWyqXM0CrzedVWBzuXKuBEaqD6w/1VpLJvSU+wl3ScvXSLFp82DSRJVJONXWl\n" +
+ "dp9gjJioPGRByeZw11k3galbbF5gFK9xSnbDx29LAgMBAAGjggGNMIIBiTAfBgNV\n" +
+ "HSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQULGn/gMmHkK40\n" +
+ "4bTnTJOFmUDpp7IwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw\n" +
+ "HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMDoGA1UdIAQzMDEwLwYEVR0g\n" +
+ "ADAnMCUGCCsGAQUFBwIBFhlodHRwczovL2Nwcy51c2VydHJ1c3QuY29tMFAGA1Ud\n" +
+ "HwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RS\n" +
+ "U0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2BggrBgEFBQcBAQRqMGgwPwYI\n" +
+ "KwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FB\n" +
+ "ZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0\n" +
+ "LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAQ4AzPxVypLyy3IjUUmVl7FaxrHsXQq2z\n" +
+ "Zt2gKnHQShuA+5xpRPNndjvhHk4D08PZXUe6Im7E5knqxtyl5aYdldb+HI/7f+zd\n" +
+ "W/1ub2N4Vq4ZYUjcZ1ECOFK7Z2zoNicDmU+Fe/TreXPuPsDicTG/tMcWEVM558OQ\n" +
+ "TJkB2LK3ZhGukWM/RTMRcRdXaXOX8Lh0ylzRO1O0ObXytvOFpkkkD92HGsfS06i7\n" +
+ "NLDPJEeZXqzHE5Tqj7VSAj+2luwfaXaPLD8lQEVci8xmsPGOn0mXE1ZzsChEPhVq\n" +
+ "FYQUsbiRJRhidKauhd+G2CkRTcR5fpsuz+iStB9s5Fks9lKoXnn0hv78VYjvR78C\n" +
+ "Cvj5FW/ounHjWTWMb3il9S5ngbFGcelB1l/MQkR63+1ybdi2OpjNWJCftxOWUpkC\n" +
+ "xaRdnOnSj7GQY0NLn8Gtq9FcSZydtkVgXpouSFZkXNS/MYwbcCCcRKBbrk8ss0SI\n" +
+ "Xg1gTURjh9VP1OHm0OktYcUw9e90wHIDn7h0qA+bWOsZquSRzT4s2crF3ZSA3tuV\n" +
+ "/UJ33mjdVO8wBD8aI5y10QreSPJvZHHNDyCmoyjXvNhR+u3arXUoHWxO+MZBeXbi\n" +
+ "iF7Nwn/IEmQvWBW8l6D26CXIavcY1kAJcfyzHkrPbLo+fAOa/KFl3lIU+0biEVNk\n" +
+ "Q9zXE6hC6X4=\n" +
+ "-----END CERTIFICATE-----";
+
// Owner: CN=USERTrust RSA Extended Validation Secure Server CA,
// O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
// Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network,
// L=Jersey City, ST=New Jersey, C=US
// Serial number: f6bb751efa7d2e8368e606407334f83
// Valid from: Sat Feb 11 16:00:00 PST 2012 until: Thu Feb 11 15:59:59 PST 2027
- private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ "MIIGGTCCBAGgAwIBAgIQD2u3Ue+n0ug2jmBkBzNPgzANBgkqhkiG9w0BAQwFADCB\n"
+ "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n"
+ "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n"
@@ -409,15 +449,69 @@
+ "4fokbdNREXoShKClNIPbB5iY+WdSzb9CKLyb96g=\n"
+ "-----END CERTIFICATE-----";
- // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL,
- // O=Sectigo Limited, STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road,
- // L=Salford, ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, ST=Manchester,
+ // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB,
+ // SERIALNUMBER=04058690
+ // Issuer: CN=Sectigo RSA Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: b07fd164b5790c9d5d1fddff5819cdb2
+ // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIH5TCCBs2gAwIBAgIRALB/0WS1eQydXR/d/1gZzbIwDQYJKoZIhvcNAQELBQAw\n" +
+ "gZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" +
+ "BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE5MDcGA1UE\n" +
+ "AxMwU2VjdGlnbyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVy\n" +
+ "IENBMB4XDTE5MDkzMDAwMDAwMFoXDTIxMTIyODIzNTk1OVowggFWMREwDwYDVQQF\n" +
+ "EwgwNDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0\n" +
+ "ZSBPcmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExEzAR\n" +
+ "BgNVBAgTCk1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAUBgNVBAkTDVRy\n" +
+ "YWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAjBgNVBAkTHDNy\n" +
+ "ZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGDAWBgNVBAoTD1NlY3RpZ28gTGlt\n" +
+ "aXRlZDEaMBgGA1UECxMRQ09NT0RPIEVWIFNHQyBTU0wxOzA5BgNVBAMTMnVzZXJ0\n" +
+ "cnVzdHJzYWNlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMIIB\n" +
+ "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnh/rxeiYwpLa651eLvGnR+RE\n" +
+ "rhDWkTZtqZcHw9Oy7JL2uELyEPbM+v0az40cBHS0bQZJZbWmXNukMUMSwIb4z7t8\n" +
+ "OXlxz9uvxEufvlqBl4qeC/z3LpFBRRHEero3yGKVwkoe1aP2Pq7Udi+7i7eVZZdA\n" +
+ "1ticxZWo/UBU9mwbIOYqf/4xzZ6G891hKb+NAuuEfxG52vXZl8odMThfHuDlkfS7\n" +
+ "nZMQBaO40KJeSEBhr+5TIS7d7tWWye/F6oEQ0+dHBiF9PyZ1dXoO8aue/80mP+0F\n" +
+ "MYTmRFsKHge6ZjojfH9cLlR5kTqtP5Tqh5GBQ4zp3uyIBBU6ylKp9PNHkewGUQID\n" +
+ "AQABo4IDbjCCA2owHwYDVR0jBBgwFoAULGn/gMmHkK404bTnTJOFmUDpp7IwHQYD\n" +
+ "VR0OBBYEFHz7cvDn1LYe2M+z4plwQn7rt938MA4GA1UdDwEB/wQEAwIFoDAMBgNV\n" +
+ "HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBJBgNVHSAE\n" +
+ "QjBAMDUGDCsGAQQBsjEBAgEFATAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3Rp\n" +
+ "Z28uY29tL0NQUzAHBgVngQwBATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js\n" +
+ "LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVT\n" +
+ "ZXJ2ZXJDQS5jcmwwgYYGCCsGAQUFBwEBBHoweDBRBggrBgEFBQcwAoZFaHR0cDov\n" +
+ "L2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBRXh0ZW5kZWRWYWxpZGF0aW9uU2Vj\n" +
+ "dXJlU2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" +
+ "LmNvbTA9BgNVHREENjA0gjJ1c2VydHJ1c3Ryc2FjZXJ0aWZpY2F0aW9uYXV0aG9y\n" +
+ "aXR5LWV2LmNvbW9kb2NhLmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA\n" +
+ "7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFtgzv54wAABAMARzBF\n" +
+ "AiB5PmhsK3zU3XdKvyxw/wWHMmLI7apHLa1yKdjkA8H+ggIhALdUx7Tl8aeWhK6z\n" +
+ "lh+PHvMAdCcAJK6w9qBJGQtSrYO5AHUAVYHUwhaQNgFK6gubVzxT8MDkOHhwJQgX\n" +
+ "L6OqHQcT0wwAAAFtgzv5zgAABAMARjBEAiBumSwAUamibqJXTN2cf/H3mjd0T35/\n" +
+ "UK9w2hu9gFobxgIgSXTLndHyqFUmcmquu3It0WC1yl6YMceGixbQL1e8BQcAdwC7\n" +
+ "2d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAW2DO/nXAAAEAwBIMEYC\n" +
+ "IQDHRs10oYoXE5yq6WsiksjdQsUWZNpbSsrmz0u+KlxTVQIhAJ4rvHItKSeJLkaN\n" +
+ "S3YpVZnkN8tOwuxPsYeyVx/BtaNpMA0GCSqGSIb3DQEBCwUAA4IBAQAPFIsUFymo\n" +
+ "VTp0vntHrZpBApBQzDeriQv7Bi7tmou/Ng47RtXW3DjGdrePGSfOdl7h62k8qprU\n" +
+ "JeLyloDqhvmT/CG/hdwrfZ3Sv3N2xpetGcnW5S3oEi3m+/M1ls9eD+x1vybqV9Kd\n" +
+ "lcjuV7SYDlbvAS9w7TcygudhdW0cI8XTCvesGKohBkAlqaQ/MWYpt4WvsxHjbWgn\n" +
+ "5ZlIYR6A1ZFEjADifViH/5AA79lgGhAskkIWPjvRFalEVKTKtjhRK76eCfZs4Frr\n" +
+ "CEOpon+BeNKk+x/K/r10dSoWe0SV2uGVxTD83zkP++eREwo1hTgn8bXn7ftlnA3j\n" +
+ "7ml+Usz6udaD\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
// OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
// Issuer: CN=USERTrust RSA Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
// ST=New Jersey, C=US
// Serial number: d3c204e8df6a1539568cf15e97e57b1d
// Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
- private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
"MIIIADCCBuigAwIBAgIRANPCBOjfahU5VozxXpflex0wDQYJKoZIhvcNAQELBQAw\n" +
"gZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK\n" +
"ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYD\n" +
@@ -463,81 +557,56 @@
"3Ld31zbQaywKdpCsT74/hEBMfcDiP02mmtyrlqHD4R3tdYne\n" +
"-----END CERTIFICATE-----";
- // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited,
- // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
- // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
- // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
- // Issuer: CN=USERTrust RSA Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
- // ST=New Jersey, C=US
- // Serial number: ffcada019c9fb1155a32300083cb99c9
- // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019
- private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
- "MIIIATCCBumgAwIBAgIRAP/K2gGcn7EVWjIwAIPLmckwDQYJKoZIhvcNAQELBQAw\n" +
- "gZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK\n" +
- "ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYD\n" +
- "VQQDEzJVU0VSVHJ1c3QgUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNl\n" +
- "cnZlciBDQTAeFw0xNzA3MDQwMDAwMDBaFw0xOTEwMDMyMzU5NTlaMIIBYDERMA8G\n" +
- "A1UEBRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFBy\n" +
- "aXZhdGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VR\n" +
- "MRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQx\n" +
- "FjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkx\n" +
- "JTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGjAYBgNVBAoT\n" +
- "EUNPTU9ETyBDQSBMaW1pdGVkMRowGAYDVQQLExFDT01PRE8gRVYgU0dDIFNTTDE7\n" +
- "MDkGA1UEAxMydXNlcnRydXN0cnNhY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5j\n" +
- "b21vZG9jYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeH+vF\n" +
- "6JjCktrrnV4u8adH5ESuENaRNm2plwfD07Lskva4QvIQ9sz6/RrPjRwEdLRtBkll\n" +
- "taZc26QxQxLAhvjPu3w5eXHP26/ES5++WoGXip4L/PcukUFFEcR6ujfIYpXCSh7V\n" +
- "o/Y+rtR2L7uLt5Vll0DW2JzFlaj9QFT2bBsg5ip//jHNnobz3WEpv40C64R/Ebna\n" +
- "9dmXyh0xOF8e4OWR9LudkxAFo7jQol5IQGGv7lMhLt3u1ZbJ78XqgRDT50cGIX0/\n" +
- "JnV1eg7xq57/zSY/7QUxhOZEWwoeB7pmOiN8f1wuVHmROq0/lOqHkYFDjOne7IgE\n" +
- "FTrKUqn080eR7AZRAgMBAAGjggN8MIIDeDAfBgNVHSMEGDAWgBQvgU/iZvq8aL+Z\n" +
- "Q4RSiSA6gvOkpTAdBgNVHQ4EFgQUfPty8OfUth7Yz7PimXBCfuu33fwwDgYDVR0P\n" +
- "AQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n" +
- "AQUFBwMCMEsGA1UdIAREMEIwNwYMKwYBBAGyMQECAQUBMCcwJQYIKwYBBQUHAgEW\n" +
- "GWh0dHBzOi8vY3BzLnVzZXJ0cnVzdC5jb20wBwYFZ4EMAQEwWgYDVR0fBFMwUTBP\n" +
- "oE2gS4ZJaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUV4dGVu\n" +
- "ZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBjQYIKwYBBQUHAQEEgYAw\n" +
- "fjBVBggrBgEFBQcwAoZJaHR0cDovL2NydC51c2VydHJ1c3QuY29tL1VTRVJUcnVz\n" +
- "dFJTQUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAlBggrBgEF\n" +
- "BQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTA9BgNVHREENjA0gjJ1c2Vy\n" +
- "dHJ1c3Ryc2FjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2NhLmNvbTCC\n" +
- "AX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5\n" +
- "G9+443fNDsgN3BAAAAFdDU2iYQAABAMARzBFAiB0o4GnVHD8MeVQ32D0XYu+EQQW\n" +
- "jvN78rmCfk0OEBxyFAIhAKgyctIn0IaDJiZzsrtAiqEnkcMtuh8o+R0Rqw1ygAjk\n" +
- "AHcAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFdDU2gFgAABAMA\n" +
- "SDBGAiEA7mcmZ8H5uHuNCdI0CVxsqDZQcZX/gVk94KckePkzQoACIQCHwm5hcvNC\n" +
- "M8vNmFkboQN79DglRctHrlh143A6mUTk8QB2AO5Lvbd1zmC64UJpH6vhnmajD35f\n" +
- "sHLYgwDEe4l6qP3LAAABXQ1NojoAAAQDAEcwRQIhAPqwijgE0Fr6uJ+yF+TvyXco\n" +
- "Hduv9h7R5WWwJfghXiMyAiBB4+fJm4rIcOnJBZmOqFnRpIjPN0jwDqJT0nDHxaXA\n" +
- "nDANBgkqhkiG9w0BAQsFAAOCAQEACXitF1bTEvV1HX11WrT/XuoMhsoPK4TS16rs\n" +
- "FqztV4iXKlA1/h5qbsjYY1gVrM+/6kQkmEs5qrxsek2WNxY80NO3WAzroRJ3H9Sd\n" +
- "mPn0No2P8LZ5Fs5hvaD/PfWO5xxey80c3kGyvWOej90P3IrL/1RiULyh95TrXBjI\n" +
- "ddCBsZ28904wsQUrPBPMpiu0DKl1HR/em9WkcipMi+onJxxFWjucssz5PW/BzGYF\n" +
- "jfWLDEI0tN5L4CWV3iVXFXOURY1Mwhtsey9jvlEyxSsys55QdKF40yGgtV9VC+os\n" +
- "7hJP33+qA0cvCTaRytiPP6z/l2G/KSIXTyv6SxzGhsTFfzLAOg==\n" +
- "-----END CERTIFICATE-----";
-
public void runTest(ValidatePathWithParams pathValidator) throws Exception {
// Validate valid
- pathValidator.validate(new String[]{VALID, INT},
+ pathValidator.validate(new String[]{VALID, INT_VALID},
ValidatePathWithParams.Status.GOOD, null, System.out);
// Validate Revoked
- pathValidator.validate(new String[]{REVOKED, INT},
+ pathValidator.validate(new String[]{REVOKED, INT_REVOKED},
ValidatePathWithParams.Status.REVOKED,
- "Thu Nov 29 10:58:13 PST 2018", System.out);
+ "Wed Oct 02 06:07:12 PDT 2019", System.out);
}
}
class ComodoUserTrustECC {
+ // Owner: CN=Sectigo ECC Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Issuer: CN=USERTrust ECC Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
+ // Serial number: 80f5606d3a162b143adc12fbe8c2066f
+ // Valid from: Thu Nov 01 17:00:00 PDT 2018 until: Tue Dec 31 15:59:59 PST 2030
+ private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDyTCCA0+gAwIBAgIRAID1YG06FisUOtwS++jCBm8wCgYIKoZIzj0EAwMwgYgx\n" +
+ "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" +
+ "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQD\n" +
+ "EyVVU0VSVHJ1c3QgRUNDIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE4MTEw\n" +
+ "MjAwMDAwMFoXDTMwMTIzMTIzNTk1OVowgZExCzAJBgNVBAYTAkdCMRswGQYDVQQI\n" +
+ "ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoT\n" +
+ "D1NlY3RpZ28gTGltaXRlZDE5MDcGA1UEAxMwU2VjdGlnbyBFQ0MgRXh0ZW5kZWQg\n" +
+ "VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
+ "AQcDQgAEAyJ5Ca9JyXq8bO+krLVWysbtm7fdMSJ54uFD23t0x6JAC4IjxevfQJzW\n" +
+ "z4T6yY+FybTBqtOa++ijJFnkB5wKy6OCAY0wggGJMB8GA1UdIwQYMBaAFDrhCYbU\n" +
+ "zxnClnZ0SXbc4DXGY2OaMB0GA1UdDgQWBBTvwSqVDDLa+3Mw3IoT2BVL9xPo+DAO\n" +
+ "BgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggr\n" +
+ "BgEFBQcDAQYIKwYBBQUHAwIwOgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUH\n" +
+ "AgEWGWh0dHBzOi8vY3BzLnVzZXJ0cnVzdC5jb20wUAYDVR0fBEkwRzBFoEOgQYY/\n" +
+ "aHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdEVDQ0NlcnRpZmljYXRp\n" +
+ "b25BdXRob3JpdHkuY3JsMHYGCCsGAQUFBwEBBGowaDA/BggrBgEFBQcwAoYzaHR0\n" +
+ "cDovL2NydC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdEVDQ0FkZFRydXN0Q0EuY3J0\n" +
+ "MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMAoGCCqGSM49\n" +
+ "BAMDA2gAMGUCMQCjHztBDL90GCRXHlGqm0H7kzP04hd0MxwakKjWzOmstXNFLONj\n" +
+ "RFa0JqI/iKUJMFcCMCbLgyzcFW7DihtY5XE0XCLCw+git0NjxiFB6FaOFIlyDdqT\n" +
+ "j+Th+DJ92JLvICVD/g==\n" +
+ "-----END CERTIFICATE-----";
+
// Owner: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network,
// L=Jersey City, ST=New Jersey, C=US
// Issuer: CN=USERTrust ECC Certification Authority, O=The USERTRUST Network,
// L=Jersey City, ST=New Jersey, C=US
// Serial number: 3d09b24f5c08a7ce8eb85a51d3c1aa52
// Valid from: Sun Apr 14 17:00:00 PDT 2013 until: Fri Apr 14 16:59:59 PDT 2028
- private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ "MIIDwTCCA0igAwIBAgIQPQmyT1wIp86OuFpR08GqUjAKBggqhkjOPQQDAzCBiDEL\n"
+ "MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n"
+ "eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n"
@@ -563,13 +632,58 @@
// Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
// STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB,
+ // SERIALNUMBER=04058690
+ // Issuer: CN=Sectigo ECC Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: 8b72489b7f505a55e2a22659c90ed2ab
+ // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGRTCCBeugAwIBAgIRAItySJt/UFpV4qImWckO0qswCgYIKoZIzj0EAwIwgZEx\n" +
+ "CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV\n" +
+ "BAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE5MDcGA1UEAxMw\n" +
+ "U2VjdGlnbyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" +
+ "MB4XDTE5MDkzMDAwMDAwMFoXDTIxMTIyODIzNTk1OVowggFBMREwDwYDVQQFEwgw\n" +
+ "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" +
+ "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExEDAOBgNV\n" +
+ "BAcTB1NhbGZvcmQxFjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4\n" +
+ "Y2hhbmdlIFF1YXkxJTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxh\n" +
+ "Z2UxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEaMBgGA1UECxMRQ09NT0RPIEVW\n" +
+ "IFNHQyBTU0wxOzA5BgNVBAMTMnVzZXJ0cnVzdGVjY2NlcnRpZmljYXRpb25hdXRo\n" +
+ "b3JpdHktZXYuY29tb2RvY2EuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\n" +
+ "LTJfEd92Wlg+h/AVtPsMmwX9Puvi+WGCv3sgFRpur8Iy2kGVpXHRQTCn2j9aky4t\n" +
+ "FQGm7OG2klJA/MEeevKVaaOCA28wggNrMB8GA1UdIwQYMBaAFO/BKpUMMtr7czDc\n" +
+ "ihPYFUv3E+j4MB0GA1UdDgQWBBSzrWHzmiHwx2Rrm7SjRC0UegNrKzAOBgNVHQ8B\n" +
+ "Af8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" +
+ "BQUHAwIwSQYDVR0gBEIwQDA1BgwrBgEEAbIxAQIBBQEwJTAjBggrBgEFBQcCARYX\n" +
+ "aHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmg\n" +
+ "R4ZFaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvRUNDRXh0ZW5kZWRWYWxp\n" +
+ "ZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGGBggrBgEFBQcBAQR6MHgwUQYIKwYB\n" +
+ "BQUHMAKGRWh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb0VDQ0V4dGVuZGVk\n" +
+ "VmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAjBggrBgEFBQcwAYYXaHR0cDov\n" +
+ "L29jc3Auc2VjdGlnby5jb20wPQYDVR0RBDYwNIIydXNlcnRydXN0ZWNjY2VydGlm\n" +
+ "aWNhdGlvbmF1dGhvcml0eS1ldi5jb21vZG9jYS5jb20wggF/BgorBgEEAdZ5AgQC\n" +
+ "BIIBbwSCAWsBaQB2AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAAB\n" +
+ "bYL/SJoAAAQDAEcwRQIhAL7EJt/Rgz6NBnx2v8Hevux3Gpcxy64kaeyLVgFeNqFk\n" +
+ "AiBRf+OWLOtZzEav/oERljrk8hgZB4CR1nj/Tn98cmRrwwB2AFWB1MIWkDYBSuoL\n" +
+ "m1c8U/DA5Dh4cCUIFy+jqh0HE9MMAAABbYL/SIgAAAQDAEcwRQIgVtZZaiBMC2lu\n" +
+ "atBzUHQmOq4qrUQP7nS83cd3VzPhToECIQDnlpOCdaxJwr8C0MtkvYpKSabwBPFL\n" +
+ "ASEkwmOpjuQErAB3ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAAB\n" +
+ "bYL/SJoAAAQDAEgwRgIhAI8OgzP/kzF1bOJRHU2S/ewij/6HpGPy7Mbm7Hyuv3IU\n" +
+ "AiEAxDmX2FmORlgeerQmQ+ar3D9/TwA9RQckVDu5IrgweREwCgYIKoZIzj0EAwID\n" +
+ "SAAwRQIhAPwQWGWd3oR7YJ7ngCDQ9TAbdPgND51SiR34WfEgaTQtAiAxD4umKm02\n" +
+ "59GEMj5NpyF2ZQEq5mEGcjJNojrn+PC4zg==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
// ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
// OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
// Issuer: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
// ST=New Jersey, C=US
// Serial number: ab1455f9833ae7783f95de8744181f6a
// Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
- private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
"MIIGhjCCBiygAwIBAgIRAKsUVfmDOud4P5Xeh0QYH2owCgYIKoZIzj0EAwIwgZUx\n" +
"CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" +
"ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYDVQQD\n" +
@@ -607,60 +721,14 @@
"11EPtBSCEhUCIBcyI0yl5dRff6+4x8IeCrLiAOYsfzM7Y/a5uRKFnbYz\n" +
"-----END CERTIFICATE-----";
- // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited,
- // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
- // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
- // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
- // Issuer: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
- // ST=New Jersey, C=US
- // Serial number: 9bd0c93cac9ca2edc1a7dd923316b3c6
- // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019
- private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
- "MIIGhzCCBi2gAwIBAgIRAJvQyTysnKLtwafdkjMWs8YwCgYIKoZIzj0EAwIwgZUx\n" +
- "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" +
- "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYDVQQD\n" +
- "EzJVU0VSVHJ1c3QgRUNDIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" +
- "ciBDQTAeFw0xNzA3MDQwMDAwMDBaFw0xOTEwMDMyMzU5NTlaMIIBYDERMA8GA1UE\n" +
- "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" +
- "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRsw\n" +
- "GQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAU\n" +
- "BgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAj\n" +
- "BgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGjAYBgNVBAoTEUNP\n" +
- "TU9ETyBDQSBMaW1pdGVkMRowGAYDVQQLExFDT01PRE8gRVYgU0dDIFNTTDE7MDkG\n" +
- "A1UEAxMydXNlcnRydXN0ZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21v\n" +
- "ZG9jYS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtMl8R33ZaWD6H8BW0\n" +
- "+wybBf0+6+L5YYK/eyAVGm6vwjLaQZWlcdFBMKfaP1qTLi0VAabs4baSUkD8wR56\n" +
- "8pVpo4IDjjCCA4owHwYDVR0jBBgwFoAUKpxa+U6hMNpASyvpS/H1nNwC+S4wHQYD\n" +
- "VR0OBBYEFLOtYfOaIfDHZGubtKNELRR6A2srMA4GA1UdDwEB/wQEAwIFgDAMBgNV\n" +
- "HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBQBgNVHSAE\n" +
- "STBHMDwGDCsGAQQBsjEBAgEFATAsMCoGCCsGAQUFBwIBFh5odHRwczovL2Nwcy50\n" +
- "cnVzdC1wcm92aWRlci5jb20wBwYFZ4EMAQEwXwYDVR0fBFgwVjBUoFKgUIZOaHR0\n" +
- "cDovL2NybC50cnVzdC1wcm92aWRlci5jb20vVVNFUlRydXN0RUNDRXh0ZW5kZWRW\n" +
- "YWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGYBggrBgEFBQcBAQSBizCBiDBa\n" +
- "BggrBgEFBQcwAoZOaHR0cDovL2NydC50cnVzdC1wcm92aWRlci5jb20vVVNFUlRy\n" +
- "dXN0RUNDRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCoGCCsG\n" +
- "AQUFBzABhh5odHRwOi8vb2NzcC50cnVzdC1wcm92aWRlci5jb20wPQYDVR0RBDYw\n" +
- "NIIydXNlcnRydXN0ZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21vZG9j\n" +
- "YS5jb20wggF8BgorBgEEAdZ5AgQCBIIBbASCAWgBZgB1AKS5CZC0GFgUh7sTosxn\n" +
- "cAo8NZgE+RvfuON3zQ7IDdwQAAABXQ0/jQ0AAAQDAEYwRAIgPbaNWgoi6OfyNwL2\n" +
- "+jiySsoLrkx+0d4NJE1WnZQcfzwCICW4yvsXaMxoOXpQp3EPgrYk5Ajfvy/dY3Ui\n" +
- "0/dbQtHxAHYAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFdDT+K\n" +
- "xwAABAMARzBFAiB3GQasrX+akoHX02ZvXCcvhWCqv6qQOhLCUqflPoRbuAIhALwe\n" +
- "hrQo8S1Tm5vbMcxGiViq5ZcawxENWhxZ9hS0BZweAHUA7ku9t3XOYLrhQmkfq+Ge\n" +
- "ZqMPfl+wctiDAMR7iXqo/csAAAFdDT+M4AAABAMARjBEAiAjvp8w/fdTVW1VGE0T\n" +
- "I0YcCIXTYFDgzUMsEUiKHANAgwIgETQUcac7Hiis2fgQ+GdGF9yuh+xMo2Z8QXNu\n" +
- "1Cknf+8wCgYIKoZIzj0EAwIDSAAwRQIgQ5UiUI7xodmmMYNs3CmqlZHw/04BQRAR\n" +
- "4gRm7blZSIMCIQDHvIWTaPzSO6vwVzs6wSD6FqebLiFxoddC6aZG8Nm0wQ==\n" +
- "-----END CERTIFICATE-----";
-
public void runTest(ValidatePathWithParams pathValidator) throws Exception {
// Validate valid
- pathValidator.validate(new String[]{VALID, INT},
+ pathValidator.validate(new String[]{VALID, INT_VALID},
ValidatePathWithParams.Status.GOOD, null, System.out);
// Validate Revoked
- pathValidator.validate(new String[]{REVOKED, INT},
+ pathValidator.validate(new String[]{REVOKED, INT_REVOKED},
ValidatePathWithParams.Status.REVOKED,
- "Thu Nov 29 10:06:00 PST 2018", System.out);
+ "Wed Oct 02 06:06:50 PDT 2019", System.out);
}
}
--- a/test/jtreg-ext/requires/VMProps.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/jtreg-ext/requires/VMProps.java Wed Oct 09 23:22:56 2019 +0200
@@ -305,6 +305,7 @@
*/
protected void vmOptFinalFlags(SafeMap map) {
vmOptFinalFlag(map, "ClassUnloading");
+ vmOptFinalFlag(map, "ClassUnloadingWithConcurrentMark");
vmOptFinalFlag(map, "UseCompressedOops");
vmOptFinalFlag(map, "EnableJVMCI");
vmOptFinalFlag(map, "EliminateAllocations");
--- a/test/langtools/tools/javac/lib/DPrinter.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/langtools/tools/javac/lib/DPrinter.java Wed Oct 09 23:22:56 2019 +0200
@@ -437,7 +437,8 @@
Scope scope = (Scope) getField(e, e.getClass(), "scope");
return "(" + sym.name + ":" + sym
+ ",shdw:" + entryToString(callMethod(e, e.getClass(), "next"), table, true)
- + ",sibl:" + entryToString(getField(e, e.getClass(), "sibling"), table, true)
+ + ",nextSibling:" + entryToString(getField(e, e.getClass(), "nextSibling"), table, true)
+ + ",prevSibling:" + entryToString(getField(e, e.getClass(), "prevSibling"), table, true)
+ ((sym.owner != scope.owner)
? (",BOGUS[" + sym.owner + "," + scope.owner + "]")
: "")
--- a/test/langtools/tools/javac/scope/RemoveSymbolUnitTest.java Wed Oct 09 23:21:07 2019 +0200
+++ b/test/langtools/tools/javac/scope/RemoveSymbolUnitTest.java Wed Oct 09 23:22:56 2019 +0200
@@ -33,8 +33,13 @@
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.*;
+import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.file.JavacFileManager;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
public class RemoveSymbolUnitTest {
@@ -63,36 +68,66 @@
// Try enter and remove in different shuffled combinations.
// working with fresh scope each time.
- WriteableScope cs = WriteableScope.create(clazz);
- cs.enter(v);
- cs.enter(m);
+ WriteableScope cs = writeableScope(clazz, v, m);
cs.remove(v);
Symbol s = cs.findFirst(hasNext);
if (s != m)
throw new AssertionError("Wrong symbol");
- cs = WriteableScope.create(clazz);
- cs.enter(m);
- cs.enter(v);
+ cs = writeableScope(clazz, m, v);
cs.remove(v);
s = cs.findFirst(hasNext);
if (s != m)
throw new AssertionError("Wrong symbol");
- cs = WriteableScope.create(clazz);
- cs.enter(v);
- cs.enter(m);
+ cs = writeableScope(clazz, v, m);
cs.remove(m);
s = cs.findFirst(hasNext);
if (s != v)
throw new AssertionError("Wrong symbol");
- cs = WriteableScope.create(clazz);
+ cs = writeableScope(clazz);
cs.enter(m);
cs.enter(v);
cs.remove(m);
s = cs.findFirst(hasNext);
if (s != v)
throw new AssertionError("Wrong symbol");
+
+ // Test multiple removals in the same scope.
+ VarSymbol v1 = new VarSymbol(0, names.fromString("name1"), Type.noType, clazz);
+ VarSymbol v2 = new VarSymbol(0, names.fromString("name2"), Type.noType, clazz);
+ VarSymbol v3 = new VarSymbol(0, names.fromString("name3"), Type.noType, clazz);
+ VarSymbol v4 = new VarSymbol(0, names.fromString("name4"), Type.noType, clazz);
+
+ cs = writeableScope(clazz, v1, v2, v3, v4);
+ cs.remove(v2);
+ assertRemainingSymbols(cs, v1, v3, v4);
+ cs.remove(v3);
+ assertRemainingSymbols(cs, v1, v4);
+ cs.remove(v1);
+ assertRemainingSymbols(cs, v4);
+ cs.remove(v4);
+ assertRemainingSymbols(cs);
+ }
+
+ private WriteableScope writeableScope(ClassSymbol classSymbol, Symbol... symbols) {
+ WriteableScope cs = WriteableScope.create(classSymbol);
+ for (Symbol symbol : symbols) {
+ cs.enter(symbol);
+ }
+ return cs;
+ }
+
+ private void assertRemainingSymbols(WriteableScope cs, Symbol... symbols) {
+ List<Symbol> expectedSymbols = Arrays.asList(symbols);
+ List<Symbol> actualSymbols = new ArrayList<>();
+ cs.getSymbols().forEach(symbol -> actualSymbols.add(symbol));
+ // The symbols are stored in reverse order
+ Collections.reverse(actualSymbols);
+ if (!actualSymbols.equals(expectedSymbols)) {
+ throw new AssertionError(
+ String.format("Wrong symbols: %s. Expected %s", actualSymbols, expectedSymbols));
+ }
}
}