diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index f53e149a6c7..b0d42a5f5ef 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1213,7 +1213,7 @@ var getJibProfilesDependencies = function (input, common) { jcov: { organization: common.organization, - revision: "3.0-16-jdk-asm+1.0", + revision: "3.0-17-jdk-asm+1.0", ext: "zip", environment_name: "JCOV_HOME", }, diff --git a/make/modules/jdk.jpackage/Java.gmk b/make/modules/jdk.jpackage/Java.gmk index 9d31e5417e9..d60e9ac2814 100644 --- a/make/modules/jdk.jpackage/Java.gmk +++ b/make/modules/jdk.jpackage/Java.gmk @@ -27,6 +27,6 @@ DISABLED_WARNINGS_java += dangling-doc-comments COPY += .gif .png .txt .spec .script .prerm .preinst \ .postrm .postinst .list .sh .desktop .copyright .control .plist .template \ - .icns .scpt .wxs .wxl .wxi .ico .bmp .tiff .service + .icns .scpt .wxs .wxl .wxi .ico .bmp .tiff .service .xsl CLEAN += .properties diff --git a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java index 3497d03292d..34e933eb22d 100644 --- a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java +++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -663,7 +663,7 @@ private static void printJfrEventControlHpp(Metadata metadata, File outputFile) out.write(""); out.write("union JfrNativeSettings {"); out.write(" // Array version."); - out.write(" jfrNativeEventSetting bits[NUMBER_OF_EVENTS];"); + out.write(" jfrNativeEventSetting bits[NUMBER_OF_EVENTS + NUMBER_OF_RESERVED_EVENTS];"); out.write(" // Then, to make it easy to debug,"); out.write(" // add named struct members also."); out.write(" struct {"); diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 1b8b9801f3c..2f2bee6e22f 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -5628,24 +5628,24 @@ operand cmpOpLtGe() // used for certain unsigned integral comparisons which can be // converted to cbxx or tbxx instructions -operand cmpOpUEqNeLtGe() +operand cmpOpUEqNeLeGt() %{ match(Bool); op_cost(0); - predicate(n->as_Bool()->_test._test == BoolTest::eq - || n->as_Bool()->_test._test == BoolTest::ne - || n->as_Bool()->_test._test == BoolTest::lt - || n->as_Bool()->_test._test == BoolTest::ge); + predicate(n->as_Bool()->_test._test == BoolTest::eq || + n->as_Bool()->_test._test == BoolTest::ne || + n->as_Bool()->_test._test == BoolTest::le || + n->as_Bool()->_test._test == BoolTest::gt); format %{ "" %} interface(COND_INTER) %{ equal(0x0, "eq"); not_equal(0x1, "ne"); - less(0xb, "lt"); - greater_equal(0xa, "ge"); - less_equal(0xd, "le"); - greater(0xc, "gt"); + less(0x3, "lo"); + greater_equal(0x2, "hs"); + less_equal(0x9, "ls"); + greater(0x8, "hi"); overflow(0x6, "vs"); no_overflow(0x7, "vc"); %} @@ -7780,7 +7780,7 @@ instruct membar_acquire() %{ ins_cost(VOLATILE_REF_COST); format %{ "membar_acquire\n\t" - "dmb ish" %} + "dmb ishld" %} ins_encode %{ __ block_comment("membar_acquire"); @@ -7834,11 +7834,13 @@ instruct membar_release() %{ ins_cost(VOLATILE_REF_COST); format %{ "membar_release\n\t" - "dmb ish" %} + "dmb ishst\n\tdmb ishld" %} ins_encode %{ __ block_comment("membar_release"); - __ membar(Assembler::LoadStore|Assembler::StoreStore); + // These will be merged if AlwaysMergeDMB is enabled. + __ membar(Assembler::StoreStore); + __ membar(Assembler::LoadStore); %} ins_pipe(pipe_serial); %} @@ -15685,7 +15687,7 @@ instruct cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN oop, immP0 zero, label ins_pipe(pipe_cmp_branch); %} -instruct cmpUI_imm0_branch(cmpOpUEqNeLtGe cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsRegU cr) %{ +instruct cmpUI_imm0_branch(cmpOpUEqNeLeGt cmp, iRegIorL2I op1, immI0 op2, label labl) %{ match(If cmp (CmpU op1 op2)); effect(USE labl); @@ -15694,15 +15696,17 @@ instruct cmpUI_imm0_branch(cmpOpUEqNeLtGe cmp, iRegIorL2I op1, immI0 op2, label ins_encode %{ Label* L = $labl$$label; Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; - if (cond == Assembler::EQ || cond == Assembler::LS) + if (cond == Assembler::EQ || cond == Assembler::LS) { __ cbzw($op1$$Register, *L); - else + } else { + assert(cond == Assembler::NE || cond == Assembler::HI, "unexpected condition"); __ cbnzw($op1$$Register, *L); + } %} ins_pipe(pipe_cmp_branch); %} -instruct cmpUL_imm0_branch(cmpOpUEqNeLtGe cmp, iRegL op1, immL0 op2, label labl, rFlagsRegU cr) %{ +instruct cmpUL_imm0_branch(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 op2, label labl) %{ match(If cmp (CmpUL op1 op2)); effect(USE labl); @@ -15711,10 +15715,12 @@ instruct cmpUL_imm0_branch(cmpOpUEqNeLtGe cmp, iRegL op1, immL0 op2, label labl, ins_encode %{ Label* L = $labl$$label; Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; - if (cond == Assembler::EQ || cond == Assembler::LS) + if (cond == Assembler::EQ || cond == Assembler::LS) { __ cbz($op1$$Register, *L); - else + } else { + assert(cond == Assembler::NE || cond == Assembler::HI, "unexpected condition"); __ cbnz($op1$$Register, *L); + } %} ins_pipe(pipe_cmp_branch); %} diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index b14295ca15c..1ebc6408a60 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -135,9 +135,9 @@ source %{ (opcode == Op_VectorCastL2X && bt == T_FLOAT) || (opcode == Op_CountLeadingZerosV && bt == T_LONG) || (opcode == Op_CountTrailingZerosV && bt == T_LONG) || - // The vector implementation of Op_AddReductionVD/F is for the Vector API only. - // It is not suitable for auto-vectorization because it does not add the elements - // in the same order as sequential code, and FP addition is non-associative. + // The implementations of Op_AddReductionVD/F in Neon are for the Vector API only. + // They are not suitable for auto-vectorization because the result would not conform + // to the JLS, Section Evaluation Order. opcode == Op_AddReductionVD || opcode == Op_AddReductionVF || opcode == Op_MulReductionVD || opcode == Op_MulReductionVF || opcode == Op_MulVL) { @@ -2858,14 +2858,14 @@ instruct reduce_addL_sve(iRegLNoSp dst, iRegL isrc, vReg vsrc, vRegD tmp) %{ %} // reduction addF -// Floating-point addition is not associative, so the rules for AddReductionVF -// on NEON can't be used to auto-vectorize floating-point reduce-add. -// Currently, on NEON, AddReductionVF is only generated by Vector API. -instruct reduce_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ - predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 2); + +instruct reduce_non_strict_order_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ + // Non-strictly ordered floating-point add reduction for a 64-bits-long vector. This rule is + // intended for the VectorAPI (which allows for non-strictly ordered add reduction). + predicate(Matcher::vector_length(n->in(2)) == 2 && !n->as_Reduction()->requires_strict_order()); match(Set dst (AddReductionVF fsrc vsrc)); effect(TEMP_DEF dst); - format %{ "reduce_add2F_neon $dst, $fsrc, $vsrc" %} + format %{ "reduce_non_strict_order_add2F_neon $dst, $fsrc, $vsrc" %} ins_encode %{ __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ S); __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $fsrc$$FloatRegister); @@ -2873,11 +2873,13 @@ instruct reduce_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ ins_pipe(pipe_slow); %} -instruct reduce_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ - predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 4); +instruct reduce_non_strict_order_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ + // Non-strictly ordered floating-point add reduction for 128-bits-long vector. This rule is + // intended for the VectorAPI (which allows for non-strictly ordered add reduction). + predicate(Matcher::vector_length(n->in(2)) == 4 && !n->as_Reduction()->requires_strict_order()); match(Set dst (AddReductionVF fsrc vsrc)); effect(TEMP_DEF dst, TEMP tmp); - format %{ "reduce_add4F_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} + format %{ "reduce_non_strict_order_add4F_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} ins_encode %{ __ faddp($tmp$$FloatRegister, __ T4S, $vsrc$$FloatRegister, $vsrc$$FloatRegister); __ faddp($dst$$FloatRegister, $tmp$$FloatRegister, __ S); @@ -2886,11 +2888,21 @@ instruct reduce_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ ins_pipe(pipe_slow); %} +// This rule calculates the reduction result in strict order. Two cases will +// reach here: +// 1. Non strictly-ordered AddReductionVF when vector size > 128-bits. For example - +// AddReductionVF generated by Vector API. For vector size > 128-bits, it is more +// beneficial performance-wise to generate direct SVE instruction even if it is +// strictly ordered. +// 2. Strictly-ordered AddReductionVF. For example - AddReductionVF generated by +// auto-vectorization on SVE machine. instruct reduce_addF_sve(vRegF dst_src1, vReg src2) %{ - predicate(UseSVE > 0); + predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) || + n->as_Reduction()->requires_strict_order()); match(Set dst_src1 (AddReductionVF dst_src1 src2)); format %{ "reduce_addF_sve $dst_src1, $dst_src1, $src2" %} ins_encode %{ + assert(UseSVE > 0, "must be sve"); uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2); assert(length_in_bytes == MaxVectorSize, "invalid vector length"); __ sve_fadda($dst_src1$$FloatRegister, __ S, ptrue, $src2$$FloatRegister); @@ -2899,14 +2911,14 @@ instruct reduce_addF_sve(vRegF dst_src1, vReg src2) %{ %} // reduction addD -// Floating-point addition is not associative, so the rule for AddReductionVD -// on NEON can't be used to auto-vectorize floating-point reduce-add. -// Currently, on NEON, AddReductionVD is only generated by Vector API. -instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ - predicate(UseSVE == 0); + +instruct reduce_non_strict_order_add2D_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ + // Non-strictly ordered floating-point add reduction for doubles. This rule is + // intended for the VectorAPI (which allows for non-strictly ordered add reduction). + predicate(!n->as_Reduction()->requires_strict_order()); match(Set dst (AddReductionVD dsrc vsrc)); effect(TEMP_DEF dst); - format %{ "reduce_addD_neon $dst, $dsrc, $vsrc\t# 2D" %} + format %{ "reduce_non_strict_order_add2D_neon $dst, $dsrc, $vsrc\t# 2D" %} ins_encode %{ __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ D); __ faddd($dst$$FloatRegister, $dst$$FloatRegister, $dsrc$$FloatRegister); @@ -2914,11 +2926,21 @@ instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ ins_pipe(pipe_slow); %} +// This rule calculates the reduction result in strict order. Two cases will +// reach here: +// 1. Non strictly-ordered AddReductionVD when vector size > 128-bits. For example - +// AddReductionVD generated by Vector API. For vector size > 128-bits, it is more +// beneficial performance-wise to generate direct SVE instruction even if it is +// strictly ordered. +// 2. Strictly-ordered AddReductionVD. For example - AddReductionVD generated by +// auto-vectorization on SVE machine. instruct reduce_addD_sve(vRegD dst_src1, vReg src2) %{ - predicate(UseSVE > 0); + predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) || + n->as_Reduction()->requires_strict_order()); match(Set dst_src1 (AddReductionVD dst_src1 src2)); format %{ "reduce_addD_sve $dst_src1, $dst_src1, $src2" %} ins_encode %{ + assert(UseSVE > 0, "must be sve"); uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2); assert(length_in_bytes == MaxVectorSize, "invalid vector length"); __ sve_fadda($dst_src1$$FloatRegister, __ D, ptrue, $src2$$FloatRegister); diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index 060bb4a11d4..29f92772368 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -125,9 +125,9 @@ source %{ (opcode == Op_VectorCastL2X && bt == T_FLOAT) || (opcode == Op_CountLeadingZerosV && bt == T_LONG) || (opcode == Op_CountTrailingZerosV && bt == T_LONG) || - // The vector implementation of Op_AddReductionVD/F is for the Vector API only. - // It is not suitable for auto-vectorization because it does not add the elements - // in the same order as sequential code, and FP addition is non-associative. + // The implementations of Op_AddReductionVD/F in Neon are for the Vector API only. + // They are not suitable for auto-vectorization because the result would not conform + // to the JLS, Section Evaluation Order. opcode == Op_AddReductionVD || opcode == Op_AddReductionVF || opcode == Op_MulReductionVD || opcode == Op_MulReductionVF || opcode == Op_MulVL) { @@ -1752,14 +1752,14 @@ REDUCE_ADD_INT_NEON_SVE_PAIRWISE(I, iRegIorL2I) REDUCE_ADD_INT_NEON_SVE_PAIRWISE(L, iRegL) // reduction addF -// Floating-point addition is not associative, so the rules for AddReductionVF -// on NEON can't be used to auto-vectorize floating-point reduce-add. -// Currently, on NEON, AddReductionVF is only generated by Vector API. -instruct reduce_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ - predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 2); + +instruct reduce_non_strict_order_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ + // Non-strictly ordered floating-point add reduction for a 64-bits-long vector. This rule is + // intended for the VectorAPI (which allows for non-strictly ordered add reduction). + predicate(Matcher::vector_length(n->in(2)) == 2 && !n->as_Reduction()->requires_strict_order()); match(Set dst (AddReductionVF fsrc vsrc)); effect(TEMP_DEF dst); - format %{ "reduce_add2F_neon $dst, $fsrc, $vsrc" %} + format %{ "reduce_non_strict_order_add2F_neon $dst, $fsrc, $vsrc" %} ins_encode %{ __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ S); __ fadds($dst$$FloatRegister, $dst$$FloatRegister, $fsrc$$FloatRegister); @@ -1767,11 +1767,13 @@ instruct reduce_add2F_neon(vRegF dst, vRegF fsrc, vReg vsrc) %{ ins_pipe(pipe_slow); %} -instruct reduce_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ - predicate(UseSVE == 0 && Matcher::vector_length(n->in(2)) == 4); +instruct reduce_non_strict_order_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{ + // Non-strictly ordered floating-point add reduction for 128-bits-long vector. This rule is + // intended for the VectorAPI (which allows for non-strictly ordered add reduction). + predicate(Matcher::vector_length(n->in(2)) == 4 && !n->as_Reduction()->requires_strict_order()); match(Set dst (AddReductionVF fsrc vsrc)); effect(TEMP_DEF dst, TEMP tmp); - format %{ "reduce_add4F_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} + format %{ "reduce_non_strict_order_add4F_neon $dst, $fsrc, $vsrc\t# KILL $tmp" %} ins_encode %{ __ faddp($tmp$$FloatRegister, __ T4S, $vsrc$$FloatRegister, $vsrc$$FloatRegister); __ faddp($dst$$FloatRegister, $tmp$$FloatRegister, __ S); @@ -1783,11 +1785,21 @@ dnl dnl REDUCE_ADD_FP_SVE($1, $2 ) dnl REDUCE_ADD_FP_SVE(type, size) define(`REDUCE_ADD_FP_SVE', ` +// This rule calculates the reduction result in strict order. Two cases will +// reach here: +// 1. Non strictly-ordered AddReductionV$1 when vector size > 128-bits. For example - +// AddReductionV$1 generated by Vector API. For vector size > 128-bits, it is more +// beneficial performance-wise to generate direct SVE instruction even if it is +// strictly ordered. +// 2. Strictly-ordered AddReductionV$1. For example - AddReductionV$1 generated by +// auto-vectorization on SVE machine. instruct reduce_add$1_sve(vReg$1 dst_src1, vReg src2) %{ - predicate(UseSVE > 0); + predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) || + n->as_Reduction()->requires_strict_order()); match(Set dst_src1 (AddReductionV$1 dst_src1 src2)); format %{ "reduce_add$1_sve $dst_src1, $dst_src1, $src2" %} ins_encode %{ + assert(UseSVE > 0, "must be sve"); uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2); assert(length_in_bytes == MaxVectorSize, "invalid vector length"); __ sve_fadda($dst_src1$$FloatRegister, __ $2, ptrue, $src2$$FloatRegister); @@ -1798,14 +1810,14 @@ dnl REDUCE_ADD_FP_SVE(F, S) // reduction addD -// Floating-point addition is not associative, so the rule for AddReductionVD -// on NEON can't be used to auto-vectorize floating-point reduce-add. -// Currently, on NEON, AddReductionVD is only generated by Vector API. -instruct reduce_addD_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ - predicate(UseSVE == 0); + +instruct reduce_non_strict_order_add2D_neon(vRegD dst, vRegD dsrc, vReg vsrc) %{ + // Non-strictly ordered floating-point add reduction for doubles. This rule is + // intended for the VectorAPI (which allows for non-strictly ordered add reduction). + predicate(!n->as_Reduction()->requires_strict_order()); match(Set dst (AddReductionVD dsrc vsrc)); effect(TEMP_DEF dst); - format %{ "reduce_addD_neon $dst, $dsrc, $vsrc\t# 2D" %} + format %{ "reduce_non_strict_order_add2D_neon $dst, $dsrc, $vsrc\t# 2D" %} ins_encode %{ __ faddp($dst$$FloatRegister, $vsrc$$FloatRegister, __ D); __ faddd($dst$$FloatRegister, $dst$$FloatRegister, $dsrc$$FloatRegister); diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index 2f83838fc0f..9c20e3737c8 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -124,6 +124,8 @@ define_pd_global(intx, InlineSmallCode, 1000); range(1, 99) \ product(ccstr, UseBranchProtection, "none", \ "Branch Protection to use: none, standard, pac-ret") \ + product(bool, AlwaysMergeDMB, true, DIAGNOSTIC, \ + "Always merge DMB instructions in code emission") \ // end of ARCH_FLAGS diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 1929077fa16..f90aefc8fd3 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -2350,14 +2350,36 @@ void MacroAssembler::membar(Membar_mask_bits order_constraint) { address last = code()->last_insn(); if (last != nullptr && nativeInstruction_at(last)->is_Membar() && prev == last) { NativeMembar *bar = NativeMembar_at(prev); - // We are merging two memory barrier instructions. On AArch64 we - // can do this simply by ORing them together. - bar->set_kind(bar->get_kind() | order_constraint); - BLOCK_COMMENT("merged membar"); - } else { - code()->set_last_insn(pc()); - dmb(Assembler::barrier(order_constraint)); + if (AlwaysMergeDMB) { + bar->set_kind(bar->get_kind() | order_constraint); + BLOCK_COMMENT("merged membar(always)"); + return; + } + // Don't promote DMB ST|DMB LD to DMB (a full barrier) because + // doing so would introduce a StoreLoad which the caller did not + // intend + if (bar->get_kind() == order_constraint + || bar->get_kind() == AnyAny + || order_constraint == AnyAny) { + // We are merging two memory barrier instructions. On AArch64 we + // can do this simply by ORing them together. + bar->set_kind(bar->get_kind() | order_constraint); + BLOCK_COMMENT("merged membar"); + return; + } else { + // A special case like "DMB ST;DMB LD;DMB ST", the last DMB can be skipped + // We need check the last 2 instructions + address prev2 = prev - NativeMembar::instruction_size; + if (last != code()->last_label() && nativeInstruction_at(prev2)->is_Membar()) { + NativeMembar *bar2 = NativeMembar_at(prev2); + assert(bar2->get_kind() == order_constraint, "it should be merged before"); + BLOCK_COMMENT("merged membar(elided)"); + return; + } + } } + code()->set_last_insn(pc()); + dmb(Assembler::barrier(order_constraint)); } bool MacroAssembler::try_merge_ldst(Register rt, const Address &adr, size_t size_in_bytes, bool is_store) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 7b7ecf49c8c..3bfd6e70872 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -150,6 +150,7 @@ class MacroAssembler: public Assembler { void bind(Label& L) { Assembler::bind(L); code()->clear_last_insn(); + code()->set_last_label(pc()); } void membar(Membar_mask_bits order_constraint); diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp index 84caef57f87..974214d985b 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp @@ -168,6 +168,7 @@ class NativeCall: public NativeInstruction { return_address_offset = 4 }; + static int byte_size() { return instruction_size; } address instruction_address() const { return addr_at(instruction_offset); } address next_instruction_address() const { return addr_at(return_address_offset); } int displacement() const { return (int_at(displacement_offset) << 6) >> 4; } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 18f310c746c..aa64f411dbf 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -230,6 +230,9 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(OnSpinWaitInstCount)) { FLAG_SET_DEFAULT(OnSpinWaitInstCount, 1); } + if (FLAG_IS_DEFAULT(AlwaysMergeDMB)) { + FLAG_SET_DEFAULT(AlwaysMergeDMB, false); + } } if (_cpu == CPU_ARM) { diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index 15b57188730..e26c23cd983 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -415,6 +415,7 @@ inline NativeJump* nativeJump_at(address address) { class NativeCall: public RawNativeCall { public: + static int byte_size() { return instruction_size; } // NativeCall::next_instruction_address() is used only to define the // range where to look for the relocation information. We need not // walk over composed instructions (as long as the relocation information diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 3ae35949b21..0c1e23c6353 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -1827,18 +1827,17 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { int flags = op->flags(); ciArrayKlass* default_type = op->expected_type(); - BasicType basic_type = default_type != nullptr ? default_type->element_type()->basic_type() : T_ILLEGAL; + BasicType basic_type = (default_type != nullptr) ? default_type->element_type()->basic_type() : T_ILLEGAL; if (basic_type == T_ARRAY) basic_type = T_OBJECT; // Set up the arraycopy stub information. ArrayCopyStub* stub = op->stub(); - const int frame_resize = frame::native_abi_reg_args_size - sizeof(frame::java_abi); // C calls need larger frame. // Always do stub if no type information is available. It's ok if // the known type isn't loaded since the code sanity checks // in debug mode and the type isn't required when we know the exact type // also check that the type is an array type. - if (op->expected_type() == nullptr) { + if (default_type == nullptr) { assert(src->is_nonvolatile() && src_pos->is_nonvolatile() && dst->is_nonvolatile() && dst_pos->is_nonvolatile() && length->is_nonvolatile(), "must preserve"); address copyfunc_addr = StubRoutines::generic_arraycopy(); @@ -1873,7 +1872,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { return; } - assert(default_type != nullptr && default_type->is_array_klass(), "must be true at this point"); + assert(default_type != nullptr && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point"); Label cont, slow, copyfunc; bool simple_check_flag_set = flags & (LIR_OpArrayCopy::src_null_check | @@ -1968,7 +1967,11 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { int shift = shift_amount(basic_type); if (!(flags & LIR_OpArrayCopy::type_check)) { - __ b(cont); + if (stub != nullptr) { + __ b(cont); + __ bind(slow); + __ b(*stub->entry()); + } } else { // We don't know the array types are compatible. if (basic_type != T_OBJECT) { @@ -2089,9 +2092,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ add(dst_pos, tmp, dst_pos); } } + __ bind(slow); + __ b(*stub->entry()); } - __ bind(slow); - __ b(*stub->entry()); __ bind(cont); #ifdef ASSERT @@ -2104,7 +2107,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // subtype which we can't check or src is the same array as dst // but not necessarily exactly of type default_type. Label known_ok, halt; - metadata2reg(op->expected_type()->constant_encoding(), tmp); + metadata2reg(default_type->constant_encoding(), tmp); if (UseCompressedClassPointers) { // Tmp holds the default type. It currently comes uncompressed after the // load of a constant, so encode it. @@ -2180,7 +2183,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ mr(len, length); __ call_c_with_frame_resize(entry, /*stub does not need resized frame*/ 0); - __ bind(*stub->continuation()); + if (stub != nullptr) { + __ bind(*stub->continuation()); + } } @@ -2301,7 +2306,8 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { arrayOopDesc::base_offset_in_bytes(op->type()), type2aelembytes(op->type()), op->klass()->as_register(), - *op->stub()->entry()); + *op->stub()->entry(), + op->zero_array()); } __ bind(*op->stub()->continuation()); } diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp index 2caca1dc556..04762a22c61 100644 --- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -758,7 +758,13 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { assert(x->number_of_arguments() == 5, "wrong type"); // Make all state_for calls early since they can emit code. - CodeEmitInfo* info = state_for(x, x->state()); + CodeEmitInfo* info = nullptr; + if (x->state_before() != nullptr && x->state_before()->force_reexecute()) { + info = state_for(x, x->state_before()); + info->set_force_reexecute(); + } else { + info = state_for(x, x->state()); + } LIRItem src (x->argument_at(0), this); LIRItem src_pos (x->argument_at(1), this); @@ -778,7 +784,9 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { int flags; ciArrayKlass* expected_type; arraycopy_helper(x, &flags, &expected_type); - + if (x->check_flag(Instruction::OmitChecksFlag)) { + flags = 0; + } __ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), length.result(), tmp, expected_type, flags, info); @@ -903,7 +911,13 @@ void LIRGenerator::do_NewInstance(NewInstance* x) { void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { // Evaluate state_for early since it may emit code. - CodeEmitInfo* info = state_for(x, x->state()); + CodeEmitInfo* info = nullptr; + if (x->state_before() != nullptr && x->state_before()->force_reexecute()) { + info = state_for(x, x->state_before()); + info->set_force_reexecute(); + } else { + info = state_for(x, x->state()); + } LIRItem length(x->length(), this); length.load_item(); @@ -921,7 +935,7 @@ void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { __ metadata2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg); CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info); - __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path); + __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path, x->zero_array()); // Must prevent reordering of stores for object initialization // with stores that publish the new object. diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 9da5a2c6580..abc439df827 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -310,7 +310,8 @@ void C1_MacroAssembler::allocate_array( int base_offset_in_bytes, // elements offset in bytes int elt_size, // element size in bytes Register klass, // object klass - Label& slow_case // continuation point if fast allocation fails + Label& slow_case, // continuation point if fast allocation fails + bool zero_array // zero the allocated array or not ) { assert_different_registers(obj, len, t1, t2, t3, klass); @@ -346,22 +347,24 @@ void C1_MacroAssembler::allocate_array( try_allocate(obj, arr_size, 0, t2, t3, slow_case); initialize_header(obj, klass, len, t2, t3); - // Initialize body. - const Register base = t2; - const Register index = t3; - addi(base, obj, base_offset_in_bytes); // compute address of first element - addi(index, arr_size, -(base_offset_in_bytes)); // compute index = number of bytes to clear - - // Zero first 4 bytes, if start offset is not word aligned. - if (!is_aligned(base_offset_in_bytes, BytesPerWord)) { - assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned"); - li(t1, 0); - stw(t1, 0, base); - addi(base, base, BytesPerInt); - // Note: initialize_body will align index down, no need to correct it here. - } + if (zero_array) { + // Initialize body. + const Register base = t2; + const Register index = t3; + addi(base, obj, base_offset_in_bytes); // compute address of first element + addi(index, arr_size, -(base_offset_in_bytes)); // compute index = number of bytes to clear + + // Zero first 4 bytes, if start offset is not word aligned. + if (!is_aligned(base_offset_in_bytes, BytesPerWord)) { + assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned"); + li(t1, 0); + stw(t1, 0, base); + addi(base, base, BytesPerInt); + // Note: initialize_body will align index down, no need to correct it here. + } - initialize_body(base, index); + initialize_body(base, index); + } if (CURRENT_ENV->dtrace_alloc_probes()) { Unimplemented(); diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp index ab31431e67d..c0a3dd3b83c 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -83,7 +83,8 @@ int base_offset_in_bytes, // elements offset in bytes int elt_size, // element size in bytes Register klass, // object klass - Label& slow_case // continuation point if fast allocation fails + Label& slow_case, // continuation point if fast allocation fails + bool zero_array // zero the allocated array or not ); void null_check(Register r, Label *Lnull = nullptr); diff --git a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp index 7175f727437..45859f33bfb 100644 --- a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp +++ b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2023 SAP SE. All rights reserved. - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024 SAP SE. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,7 +187,7 @@ void DowncallLinker::StubGenerator::generate() { _oop_maps = _needs_transition ? new OopMapSet() : nullptr; address start = __ pc(); - __ save_LR_CR(tmp); // Save in old frame. + __ save_LR(tmp); // Save in old frame. __ mr(callerSP, R1_SP); // preset (used to access caller frame argument slots) __ push_frame(allocated_frame_size, tmp); @@ -302,7 +302,7 @@ void DowncallLinker::StubGenerator::generate() { } __ pop_frame(); - __ restore_LR_CR(tmp); + __ restore_LR(tmp); __ blr(); ////////////////////////////////////////////////////////////////////////////// diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp index 45438f81345..7d230d301c2 100644 --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2023 SAP SE. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024 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 @@ -67,7 +67,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm __ cmpdi(CCR0, R0, 0); __ beq(CCR0, filtered); - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame(frame_size, R0); int slot_nr = 0; __ std(from, frame_size - (++slot_nr) * wordSize, R1_SP); @@ -89,7 +89,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm if (preserve1 != noreg) { __ ld(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); } if (preserve2 != noreg) { __ ld(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); } __ addi(R1_SP, R1_SP, frame_size); // pop_frame() - __ restore_LR_CR(R0); + __ restore_LR(R0); __ bind(filtered); } @@ -100,13 +100,13 @@ void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* mas int spill_slots = (preserve != noreg) ? 1 : 0; const int frame_size = align_up(frame::native_abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame(frame_size, R0); if (preserve != noreg) { __ std(preserve, frame_size - 1 * wordSize, R1_SP); } __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), addr, count); if (preserve != noreg) { __ ld(preserve, frame_size - 1 * wordSize, R1_SP); } __ addi(R1_SP, R1_SP, frame_size); // pop_frame(); - __ restore_LR_CR(R0); + __ restore_LR(R0); } void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, DecoratorSet decorators, @@ -206,7 +206,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, Decorator __ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); } - __ save_LR_CR(tmp1); + __ save_LR(tmp1); __ push_frame_reg_args(nbytes_save, tmp2); } @@ -220,7 +220,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, Decorator if (needs_frame) { __ pop_frame(); - __ restore_LR_CR(tmp1); + __ restore_LR(tmp1); if (preserve_gp_registers) { __ restore_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 44bb03aa6d8..535fe88a680 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 2018, 2024, Red Hat, Inc. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -150,7 +150,7 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, Dec __ std(dst, -BytesPerWord * ++highest_preserve_register_index, R1_SP); __ std(count, -BytesPerWord * ++highest_preserve_register_index, R1_SP); - __ save_LR_CR(R11_tmp); + __ save_LR(R11_tmp); __ push_frame_reg_args(-BytesPerWord * highest_preserve_register_index, R11_tmp); } @@ -169,7 +169,7 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, Dec // Restore to-be-preserved registers. { __ pop_frame(); - __ restore_LR_CR(R11_tmp); + __ restore_LR(R11_tmp); __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP); __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP); @@ -304,7 +304,7 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm __ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); } - __ save_LR_CR(tmp1); + __ save_LR(tmp1); __ push_frame_reg_args(nbytes_save, tmp2); } @@ -325,7 +325,7 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm if (needs_frame) { __ pop_frame(); - __ restore_LR_CR(tmp1); + __ restore_LR(tmp1); if (preserve_gp_registers) { __ restore_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); @@ -477,7 +477,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_impl( __ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); } - __ save_LR_CR(tmp1); + __ save_LR(tmp1); __ push_frame_reg_args(nbytes_save, tmp1); } @@ -517,7 +517,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_impl( if (needs_frame) { __ pop_frame(); - __ restore_LR_CR(tmp1); + __ restore_LR(tmp1); if (preserve_gp_registers) { __ restore_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers); @@ -916,7 +916,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss // Save to-be-preserved registers. const int nbytes_save = (MacroAssembler::num_volatile_regs + caller_stack_slots) * BytesPerWord; __ save_volatile_gprs(R1_SP, -nbytes_save); - __ save_LR_CR(R11_tmp1); + __ save_LR(R11_tmp1); __ push_frame_reg_args(nbytes_save, R11_tmp1); // Invoke runtime. @@ -924,7 +924,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss // Restore to-be-preserved registers. __ pop_frame(); - __ restore_LR_CR(R11_tmp1); + __ restore_LR(R11_tmp1); __ restore_volatile_gprs(R1_SP, -nbytes_save); __ bind(skip_barrier); @@ -989,7 +989,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s } assert(jrt_address != nullptr, "load reference barrier runtime routine cannot be found"); - __ save_LR_CR(R11_tmp); + __ save_LR(R11_tmp); __ push_frame_reg_args(nbytes_save, R11_tmp); // Invoke runtime. Arguments are already stored in the corresponding registers. @@ -997,7 +997,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s // Restore to-be-preserved registers. __ pop_frame(); - __ restore_LR_CR(R11_tmp); + __ restore_LR(R11_tmp); __ restore_volatile_gprs(R1_SP, -nbytes_save, true, false); // Skip 'R3_RET' register. __ blr(); diff --git a/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp index 7db34177d3a..ca826e47352 100644 --- a/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/x/xBarrierSetAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2022 SAP SE. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 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 @@ -116,7 +116,7 @@ void XBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators __ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers, preserve_R3); } - __ save_LR_CR(tmp1); + __ save_LR(tmp1); __ push_frame_reg_args(nbytes_save, tmp1); } @@ -138,7 +138,7 @@ void XBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators Register result = R3_RET; if (needs_frame) { __ pop_frame(); - __ restore_LR_CR(tmp1); + __ restore_LR(tmp1); if (preserve_R3) { __ mr(R0, R3_RET); @@ -220,7 +220,7 @@ void XBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet __ std(dst, -BytesPerWord * ++nbytes_save, R1_SP); __ std(count, -BytesPerWord * ++nbytes_save, R1_SP); - __ save_LR_CR(tmp_R11); + __ save_LR(tmp_R11); __ push_frame_reg_args(nbytes_save, tmp_R11); } @@ -243,7 +243,7 @@ void XBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet __ call_VM_leaf(XBarrierSetRuntime::load_barrier_on_oop_array_addr()); __ pop_frame(); - __ restore_LR_CR(tmp_R11); + __ restore_LR(tmp_R11); { __ ld(count, -BytesPerWord * nbytes_save--, R1_SP); @@ -357,7 +357,7 @@ void XBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_parameters) * BytesPerWord; __ save_volatile_gprs(R1_SP, -nbytes_save); - __ save_LR_CR(R0); + __ save_LR(R0); // Load arguments back again from the stack. __ ld(R3_ARG1, (intptr_t) -1 * BytesPerWord, R1_SP); // ref @@ -371,7 +371,7 @@ void XBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* __ mr(R0, R3_RET); __ pop_frame(); - __ restore_LR_CR(R3_RET); + __ restore_LR(R3_RET); __ restore_volatile_gprs(R1_SP, -nbytes_save); __ blr(); diff --git a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp index 5696b78eba8..9e606054fe9 100644 --- a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2023 SAP SE. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 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 @@ -73,7 +73,7 @@ class ZRuntimeCallSpill { __ save_volatile_gprs(R1_SP, -_nbytes_save, _preserve_fp_registers, preserve_R3); } - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame_reg_args(_nbytes_save, R0); } } @@ -84,7 +84,7 @@ class ZRuntimeCallSpill { Register result = R3_RET; if (_needs_frame) { __ pop_frame(); - __ restore_LR_CR(R0); + __ restore_LR(R0); if (_preserve_gp_registers) { bool restore_R3 = _result != R3_ARG1; @@ -785,7 +785,7 @@ void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_parameters) * BytesPerWord; __ save_volatile_gprs(R1_SP, -nbytes_save); - __ save_LR_CR(R0); + __ save_LR(R0); // Load arguments back again from the stack. __ ld(R3_ARG1, -1 * BytesPerWord, R1_SP); // ref @@ -799,7 +799,7 @@ void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* __ mr(R0, R3_RET); __ pop_frame(); - __ restore_LR_CR(R3_RET); + __ restore_LR(R3_RET); __ restore_volatile_gprs(R1_SP, -nbytes_save); __ blr(); @@ -815,7 +815,7 @@ void ZBarrierSetAssembler::generate_c1_store_barrier_runtime_stub(StubAssembler* __ save_volatile_gprs(R1_SP, -nbytes_save); __ mr(R3_ARG1, R0); // store address - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame_reg_args(nbytes_save, R0); if (self_healing) { @@ -825,7 +825,7 @@ void ZBarrierSetAssembler::generate_c1_store_barrier_runtime_stub(StubAssembler* } __ pop_frame(); - __ restore_LR_CR(R3_RET); + __ restore_LR(R3_RET); __ restore_volatile_gprs(R1_SP, -nbytes_save); __ blr(); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 4b74b1ae941..6aaa7f3c057 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -895,18 +895,26 @@ void MacroAssembler::restore_volatile_gprs(Register src, int offset, bool includ } } -void MacroAssembler::save_LR_CR(Register tmp) { - mfcr(tmp); - std(tmp, _abi0(cr), R1_SP); +void MacroAssembler::save_LR(Register tmp) { mflr(tmp); std(tmp, _abi0(lr), R1_SP); - // Tmp must contain lr on exit! (see return_addr and prolog in ppc64.ad) } -void MacroAssembler::restore_LR_CR(Register tmp) { +void MacroAssembler::restore_LR(Register tmp) { assert(tmp != R1_SP, "must be distinct"); ld(tmp, _abi0(lr), R1_SP); mtlr(tmp); +} + +void MacroAssembler::save_LR_CR(Register tmp) { + mfcr(tmp); + std(tmp, _abi0(cr), R1_SP); + save_LR(tmp); + // Tmp must contain lr on exit! (see return_addr and prolog in ppc64.ad) +} + +void MacroAssembler::restore_LR_CR(Register tmp) { + restore_LR(tmp); ld(tmp, _abi0(cr), R1_SP); mtcr(tmp); } diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp index c92f8564376..4444690e3a3 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -298,7 +298,9 @@ class MacroAssembler: public Assembler { bool include_fp_regs = true, bool include_R3_RET_reg = true); void restore_volatile_gprs(Register src_base, int offset, bool include_fp_regs = true, bool include_R3_RET_reg = true); - void save_LR_CR( Register tmp); // tmp contains LR on return. + void save_LR(Register tmp); + void restore_LR(Register tmp); + void save_LR_CR(Register tmp); // tmp contains LR on return. void restore_LR_CR(Register tmp); // Get current PC using bl-next-instruction trick. diff --git a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp index 1ac9a35b6ba..6e5ac325e50 100644 --- a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp +++ b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -581,7 +581,7 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt const Register tmp = R11; // Will be preserved. const int nbytes_save = MacroAssembler::num_volatile_regs * 8; __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0 - __ save_LR_CR(tmp); // save in old frame + __ save_LR(tmp); // save in old frame __ mr(R5_ARG3, R1_SP); // saved_sp __ push_frame_reg_args(nbytes_save, tmp); @@ -592,7 +592,7 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub)); __ pop_frame(); - __ restore_LR_CR(tmp); + __ restore_LR(tmp); __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0 BLOCK_COMMENT("} trace_method_handle"); diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp index 113cedfee7c..f21d76f8a67 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp @@ -137,6 +137,8 @@ class NativeCall: public NativeInstruction { instruction_size = 16 // Used in shared code for calls with reloc_info. }; + static int byte_size() { return instruction_size; } + static bool is_call_at(address a) { return Assembler::is_bl(*(int*)(a)); } diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 12afe49537d..14aa768e3ff 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -290,9 +290,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble __ std(R30, frame_size_in_bytes - 2*reg_size - vsregstosave_num * vs_reg_size, R1_SP); // save the flags - // Do the save_LR_CR by hand and adjust the return pc if requested. - __ mfcr(R30); - __ std(R30, frame_size_in_bytes + _abi0(cr), R1_SP); + // Do the save_LR by hand and adjust the return pc if requested. switch (return_pc_location) { case return_pc_is_lr: __ mflr(R31); break; case return_pc_is_pre_saved: assert(return_pc_adjustment == 0, "unsupported"); break; @@ -436,9 +434,6 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm, __ ld(R31, frame_size_in_bytes + _abi0(lr), R1_SP); __ mtlr(R31); - __ ld(R31, frame_size_in_bytes + _abi0(cr), R1_SP); - __ mtcr(R31); - // restore scratch register's value __ ld(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP); @@ -2241,7 +2236,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ bind(L_skip_barrier); } - __ save_LR_CR(r_temp_1); + __ save_LR(r_temp_1); __ generate_stack_overflow_check(frame_size_in_bytes); // Check before creating frame. __ mr(r_callers_sp, R1_SP); // Remember frame pointer. __ push_frame(frame_size_in_bytes, r_temp_1); // Push the c2n adapter's frame. @@ -2694,7 +2689,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // -------------------------------------------------------------------------- __ pop_frame(); - __ restore_LR_CR(R11); + __ restore_LR(R11); __ blr(); @@ -2706,7 +2701,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ bind(handle_pending_exception); __ pop_frame(); - __ restore_LR_CR(R11); + __ restore_LR(R11); __ b64_patchable((address)StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); @@ -3064,7 +3059,7 @@ void SharedRuntime::generate_deopt_blob() { // Pop the unpack frame. __ pop_frame(); - __ restore_LR_CR(R0); + __ restore_LR(R0); // stack: (top interpreter frame, ..., optional interpreter frame, // optional c2i, caller of deoptee, ...). @@ -3111,7 +3106,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { // vframe array and return the `UnrollBlock' information. // Save LR to compiled frame. - __ save_LR_CR(R11_scratch1); + __ save_LR(R11_scratch1); // Push an "uncommon_trap" frame. __ push_frame_reg_args(0, R11_scratch1); @@ -3201,7 +3196,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { // Pop the `unpack frame'. __ pop_frame(); // Restore LR from top interpreter frame. - __ restore_LR_CR(R11_scratch1); + __ restore_LR(R11_scratch1); // stack: (top interpreter frame, ..., optional interpreter frame, // optional c2i, caller of deoptee, ...). diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index ad8b76ba667..ee7aa27a630 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2023 SAP SE. All rights reserved. + * Copyright (c) 2012, 2024 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 @@ -469,7 +469,7 @@ class StubGenerator: public StubCodeGenerator { } // Save LR/CR and copy exception pc (LR) into R4_ARG2. - __ save_LR_CR(R4_ARG2); + __ save_LR(R4_ARG2); __ push_frame_reg_args(0, R0); // Find exception handler. __ call_VM_leaf(CAST_FROM_FN_PTR(address, @@ -479,7 +479,7 @@ class StubGenerator: public StubCodeGenerator { // Copy handler's address. __ mtctr(R3_RET); __ pop_frame(); - __ restore_LR_CR(R0); + __ restore_LR(R0); // Set up the arguments for the exception handler: // - R3_ARG1: exception oop @@ -550,7 +550,7 @@ class StubGenerator: public StubCodeGenerator { address start = __ pc(); - __ save_LR_CR(R11_scratch1); + __ save_LR(R11_scratch1); // Push a frame. __ push_frame_reg_args(0, R11_scratch1); @@ -604,7 +604,7 @@ class StubGenerator: public StubCodeGenerator { // Pop frame. __ pop_frame(); - __ restore_LR_CR(R11_scratch1); + __ restore_LR(R11_scratch1); __ load_const(R11_scratch1, StubRoutines::forward_exception_entry()); __ mtctr(R11_scratch1); @@ -3571,14 +3571,14 @@ class StubGenerator: public StubCodeGenerator { // and pass that one instead. __ addi(R3_ARG1, R1_SP, _abi0(lr)); - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame_reg_args(nbytes_save, R0); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier)); __ mr(R0, R3_RET); __ pop_frame(); - __ restore_LR_CR(R3_RET /* used as tmp register */); + __ restore_LR(R3_RET /* used as tmp register */); __ restore_volatile_gprs(R1_SP, -nbytes_save, true); __ cmpdi(CCR0, R0, 0); @@ -3597,7 +3597,7 @@ class StubGenerator: public StubCodeGenerator { // Restore link register. Required as the 'wrong method stub' needs the caller's frame // to properly deoptimize this method (e.g. by re-resolving the call site for compiled methods). // This method's prologue is aborted. - __ restore_LR_CR(R0); + __ restore_LR(R0); __ bctr(); return stub_address; diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index db49ca5cf22..c4eaf0493e3 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2023 SAP SE. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024 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 @@ -121,7 +121,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { address entry = __ function_entry(); - __ save_LR_CR(R0); + __ save_LR(R0); __ save_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); // We use target_sp for storing arguments in the C frame. __ mr(target_sp, R1_SP); @@ -311,7 +311,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { __ pop_frame(); __ restore_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); - __ restore_LR_CR(R0); + __ restore_LR(R0); __ blr(); @@ -441,7 +441,7 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) { __ set_top_ijava_frame_at_SP_as_last_Java_frame(R1_SP, R12_scratch2/*tmp*/); // Push a new C frame and save LR. - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame_reg_args(0, R11_scratch1); // This is not a leaf but we have a JavaFrameAnchor now and we will @@ -451,7 +451,7 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) { // Pop the C frame and restore LR. __ pop_frame(); - __ restore_LR_CR(R0); + __ restore_LR(R0); // Reset JavaFrameAnchor from call_VM_leaf above. __ reset_last_Java_frame(); @@ -1126,14 +1126,14 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M //__ call_c_and_return_to_caller(R12_scratch2); // Push a new C frame and save LR. - __ save_LR_CR(R0); + __ save_LR(R0); __ push_frame_reg_args(0, R11_scratch1); __ call_VM_leaf(runtime_entry); // Pop the C frame and restore LR. __ pop_frame(); - __ restore_LR_CR(R0); + __ restore_LR(R0); } // Restore caller sp for c2i case (from compiled) and for resized sender frame (from interpreted). diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 616aee82b99..fbb3200f40b 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1828,10 +1828,12 @@ enum Nf { // Vector unordered indexed load instructions INSN( vluxei8_v, 0b0000111, 0b000, 0b01, 0b0); INSN(vluxei32_v, 0b0000111, 0b110, 0b01, 0b0); + INSN(vluxei64_v, 0b0000111, 0b111, 0b01, 0b0); // Vector unordered indexed store instructions INSN( vsuxei8_v, 0b0100111, 0b000, 0b01, 0b0); INSN(vsuxei32_v, 0b0100111, 0b110, 0b01, 0b0); + INSN(vsuxei64_v, 0b0100111, 0b111, 0b01, 0b0); #undef INSN diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index e9b3624d9d2..f925f8950aa 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -126,6 +126,7 @@ class NativeCall: public NativeInstruction { return_address_offset = 4 }; + static int byte_size() { return instruction_size; } address instruction_address() const { return addr_at(instruction_offset); } address next_instruction_address() const { return addr_at(return_address_offset); } address return_address() const { return addr_at(return_address_offset); } diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index db2c2861949..4a71da9f20c 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -4795,12 +4795,11 @@ instruct vcountTrailingZeros(vReg dst, vReg src) %{ // ------------------------------ Vector Load Gather --------------------------- -instruct gather_load(vReg dst, indirect mem, vReg idx) %{ - predicate(type2aelembytes(Matcher::vector_element_basic_type(n)) == 4 || - type2aelembytes(Matcher::vector_element_basic_type(n)) == 8); +instruct gather_loadS(vReg dst, indirect mem, vReg idx) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n)) == 4); match(Set dst (LoadVectorGather mem idx)); effect(TEMP_DEF dst); - format %{ "gather_load $dst, $mem, $idx" %} + format %{ "gather_loadS $dst, $mem, $idx" %} ins_encode %{ __ vmv1r_v(as_VectorRegister($dst$$reg), as_VectorRegister($idx$$reg)); BasicType bt = Matcher::vector_element_basic_type(this); @@ -4813,12 +4812,28 @@ instruct gather_load(vReg dst, indirect mem, vReg idx) %{ ins_pipe(pipe_slow); %} -instruct gather_load_masked(vReg dst, indirect mem, vReg idx, vRegMask_V0 v0, vReg tmp) %{ - predicate(type2aelembytes(Matcher::vector_element_basic_type(n)) == 4 || - type2aelembytes(Matcher::vector_element_basic_type(n)) == 8); +instruct gather_loadD(vReg dst, indirect mem, vReg idx) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n)) == 8); + match(Set dst (LoadVectorGather mem idx)); + effect(TEMP_DEF dst); + format %{ "gather_loadD $dst, $mem, $idx" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vzext_vf2(as_VectorRegister($dst$$reg), as_VectorRegister($idx$$reg)); + __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg), (int)sew); + __ vluxei64_v(as_VectorRegister($dst$$reg), as_Register($mem$$base), + as_VectorRegister($dst$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct gather_loadS_masked(vReg dst, indirect mem, vReg idx, vRegMask_V0 v0, vReg tmp) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n)) == 4); match(Set dst (LoadVectorGatherMasked mem (Binary idx v0))); effect(TEMP_DEF dst, TEMP tmp); - format %{ "gather_load_masked $dst, $mem, $idx, $v0\t# KILL $tmp" %} + format %{ "gather_loadS_masked $dst, $mem, $idx, $v0\t# KILL $tmp" %} ins_encode %{ __ vmv1r_v(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg)); BasicType bt = Matcher::vector_element_basic_type(this); @@ -4833,14 +4848,32 @@ instruct gather_load_masked(vReg dst, indirect mem, vReg idx, vRegMask_V0 v0, vR ins_pipe(pipe_slow); %} +instruct gather_loadD_masked(vReg dst, indirect mem, vReg idx, vRegMask_V0 v0, vReg tmp) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n)) == 8); + match(Set dst (LoadVectorGatherMasked mem (Binary idx v0))); + effect(TEMP_DEF dst, TEMP tmp); + format %{ "gather_loadD_masked $dst, $mem, $idx, $v0\t# KILL $tmp" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vzext_vf2(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg)); + __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($tmp$$reg), (int)sew); + __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg), + as_VectorRegister($dst$$reg)); + __ vluxei64_v(as_VectorRegister($dst$$reg), as_Register($mem$$base), + as_VectorRegister($tmp$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + // ------------------------------ Vector Store Scatter ------------------------- -instruct scatter_store(indirect mem, vReg src, vReg idx, vReg tmp) %{ - predicate(type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 4 || - type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 8); +instruct scatter_storeS(indirect mem, vReg src, vReg idx, vReg tmp) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 4); match(Set mem (StoreVectorScatter mem (Binary src idx))); effect(TEMP tmp); - format %{ "scatter_store $mem, $idx, $src\t# KILL $tmp" %} + format %{ "scatter_storeS $mem, $idx, $src\t# KILL $tmp" %} ins_encode %{ __ vmv1r_v(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg)); BasicType bt = Matcher::vector_element_basic_type(this, $src); @@ -4853,12 +4886,28 @@ instruct scatter_store(indirect mem, vReg src, vReg idx, vReg tmp) %{ ins_pipe(pipe_slow); %} -instruct scatter_store_masked(indirect mem, vReg src, vReg idx, vRegMask_V0 v0, vReg tmp) %{ - predicate(type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 4 || - type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 8); +instruct scatter_storeD(indirect mem, vReg src, vReg idx, vReg tmp) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 8); + match(Set mem (StoreVectorScatter mem (Binary src idx))); + effect(TEMP tmp); + format %{ "scatter_storeD $mem, $idx, $src\t# KILL $tmp" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $src); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli_helper(bt, Matcher::vector_length(this, $src)); + __ vzext_vf2(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg)); + __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($tmp$$reg), (int)sew); + __ vsuxei64_v(as_VectorRegister($src$$reg), as_Register($mem$$base), + as_VectorRegister($tmp$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct scatter_storeS_masked(indirect mem, vReg src, vReg idx, vRegMask_V0 v0, vReg tmp) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 4); match(Set mem (StoreVectorScatterMasked mem (Binary src (Binary idx v0)))); effect(TEMP tmp); - format %{ "scatter_store_masked $mem, $idx, $src, $v0\t# KILL $tmp" %} + format %{ "scatter_storeS_masked $mem, $idx, $src, $v0\t# KILL $tmp" %} ins_encode %{ __ vmv1r_v(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg)); BasicType bt = Matcher::vector_element_basic_type(this, $src); @@ -4871,6 +4920,23 @@ instruct scatter_store_masked(indirect mem, vReg src, vReg idx, vRegMask_V0 v0, ins_pipe(pipe_slow); %} +instruct scatter_storeD_masked(indirect mem, vReg src, vReg idx, vRegMask_V0 v0, vReg tmp) %{ + predicate(type2aelembytes(Matcher::vector_element_basic_type(n->in(3)->in(1))) == 8); + match(Set mem (StoreVectorScatterMasked mem (Binary src (Binary idx v0)))); + effect(TEMP tmp); + format %{ "scatter_storeD_masked $mem, $idx, $src, $v0\t# KILL $tmp" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $src); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli_helper(bt, Matcher::vector_length(this, $src)); + __ vzext_vf2(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg)); + __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($tmp$$reg), (int)sew); + __ vsuxei64_v(as_VectorRegister($src$$reg), as_Register($mem$$base), + as_VectorRegister($tmp$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + // ------------------------------ Populate Index to a Vector ------------------- instruct populateindex(vReg dst, iRegIorL2I src1, iRegIorL2I src2, vReg tmp) %{ diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index cf80d164faf..58200958289 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2023 SAP SE. All rights reserved. + * Copyright (c) 2016, 2024 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 @@ -986,6 +986,9 @@ class Assembler : public AbstractAssembler { #define BCR_ZOPC (unsigned int)(7 << 8) #define BALR_ZOPC (unsigned int)(5 << 8) #define BASR_ZOPC (unsigned int)(13 << 8) +#define BCT_ZOPC (unsigned int)(70 << 24) +#define BCTR_ZOPC (unsigned int)(6 << 8) +#define BCTG_ZOPC (unsigned int)(227L << 40 | 70) #define BCTGR_ZOPC (unsigned long)(0xb946 << 16) // Absolute #define BC_ZOPC (unsigned int)(71 << 24) @@ -1607,6 +1610,9 @@ class Assembler : public AbstractAssembler { static int inv_simm32(long x) { return (inv_s_field(x, 31, 0)); } // 6-byte instructions only static int inv_uimm12(long x) { return (inv_u_field(x, 11, 0)); } // 4-byte instructions only + // NOTE: PLEASE DON'T USE IT NAKED UNTIL WE DROP SUPPORT FOR MACHINES OLDER THAN Z15!!!! + inline void z_popcnt(Register r1, Register r2, int64_t m3); // population count + private: // Encode u_field from long value. @@ -1887,7 +1893,14 @@ class Assembler : public AbstractAssembler { //inline void z_brcl(branch_condition i1, int64_t i2); // branch i1 ? pc = pc + i2_imm32 inline void z_brcl(branch_condition i1, address a); // branch i1 ? pc = a inline void z_brcl(branch_condition i1, Label& L); // branch i1 ? pc = Label - inline void z_bctgr(Register r1, Register r2); // branch on count r1 -= 1; (r1!=0) ? pc = r2 ; r1 is int64 + + // branch on count Instructions + inline void z_bct( Register r1, int64_t d2, Register x2, Register b2); // branch on count r1 -= 1; (r1!=0) ? pc = (d2_uimm12+x2+b2) ; r1 is int32 + inline void z_bct( Register r1, const Address &a); // branch on count r1 -= 1; (r1!=0) ? pc = *(a); r1 is int32 + inline void z_bctr( Register r1, Register r2); // branch on count r1 -= 1; (r1!=0) ? pc = r2 ; r1 is int32 + inline void z_bctgr(Register r1, Register r2); // branch on count r1 -= 1; (r1!=0) ? pc = r2 ; r1 is int64 + inline void z_bctg( Register r1, const Address &a); // branch on count r1 -= 1; (r1!=0) ? pc = *(a); r1 is int64 + inline void z_bctg( Register r1, int64_t d2, Register x2, Register b2); // branch on count r1 -= 1; (r1!=0) ? pc = (d2_imm20+x2+b2) ; r1 is int64 // branch unconditional / always inline void z_br(Register r2); // branch to r2, nop if r2 == Z_R0 @@ -3061,6 +3074,10 @@ class Assembler : public AbstractAssembler { inline void z_braz(Label& L); inline void z_brnp(Label& L); + // Branch on count; + inline void z_bct( Register r1, int64_t d2, Register b2); + inline void z_bctg(Register r1, int64_t d2, Register b2); + inline void z_btrue( Label& L); inline void z_bfalse(Label& L); @@ -3092,7 +3109,6 @@ class Assembler : public AbstractAssembler { // Ppopulation count intrinsics. inline void z_flogr(Register r1, Register r2); // find leftmost one - inline void z_popcnt(Register r1, Register r2); // population count inline void z_ahhhr(Register r1, Register r2, Register r3); // ADD halfword high high inline void z_ahhlr(Register r1, Register r2, Register r3); // ADD halfword high low diff --git a/src/hotspot/cpu/s390/assembler_s390.inline.hpp b/src/hotspot/cpu/s390/assembler_s390.inline.hpp index 126dd83ee22..2649d0f7a34 100644 --- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2023 SAP SE. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024 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 @@ -724,7 +724,14 @@ inline void Assembler::z_bcr( branch_condition m1, Register r2) { emit_16( BCR_Z inline void Assembler::z_brc( branch_condition i1, int64_t i2) { emit_32( BRC_ZOPC | uimm4(i1, 8, 32) | simm16(i2, 16, 32)); } inline void Assembler::z_brc( branch_condition i1, address a) { emit_32( BRC_ZOPC | uimm4(i1, 8, 32) | simm16(RelAddr::pcrel_off16(a, pc()), 16, 32)); } inline void Assembler::z_brcl(branch_condition i1, address a) { emit_48( BRCL_ZOPC | uimm4(i1, 8, 48) | simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } -inline void Assembler::z_bctgr(Register r1, Register r2) { emit_32( BCTGR_ZOPC | reg( r1, 24, 32) | reg( r2, 28, 32)); }; + +// branch on count +inline void Assembler::z_bct( Register r1, const Address &a) { z_bct( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_bct( Register r1, int64_t d2, Register x2, Register b2) { emit_32( BCT_ZOPC | reg(r1, 8, 32) | rxmask_32(d2, x2, b2)); } +inline void Assembler::z_bctr (Register r1, Register r2) { emit_16( BCTR_ZOPC | reg( r1, 8, 16) | reg( r2, 12, 16)); }; +inline void Assembler::z_bctgr(Register r1, Register r2) { emit_32( BCTGR_ZOPC | reg( r1, 24, 32) | reg( r2, 28, 32)); }; +inline void Assembler::z_bctg( Register r1, const Address &a) { z_bctg( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); } +inline void Assembler::z_bctg( Register r1, int64_t d2, Register x2, Register b2) { emit_48( BCTG_ZOPC | reg(r1, 8, 48) | rxymask_48(d2, x2, b2)); } inline void Assembler::z_basr( Register r1, Register r2) { emit_16( BASR_ZOPC | regt(r1, 8, 16) | reg(r2, 12, 16)); } inline void Assembler::z_brasl(Register r1, address a) { emit_48( BRASL_ZOPC | regt(r1, 8, 48) | simm32(RelAddr::pcrel_off32(a, pc()), 16, 48)); } @@ -741,7 +748,7 @@ inline void Assembler::z_brxhg(Register r1, Register r3, Label& L) {z_brxhg(r1, inline void Assembler::z_brxlg(Register r1, Register r3, Label& L) {z_brxlg(r1, r3, target(L)); } inline void Assembler::z_flogr( Register r1, Register r2) { emit_32( FLOGR_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } -inline void Assembler::z_popcnt(Register r1, Register r2) { emit_32( POPCNT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32)); } +inline void Assembler::z_popcnt(Register r1, Register r2, int64_t m3) { emit_32( POPCNT_ZOPC | reg(r1, 24, 32) | reg(r2, 28, 32) | uimm4(m3, 16, 32)); } inline void Assembler::z_ahhhr( Register r1, Register r2, Register r3) { emit_32( AHHHR_ZOPC | reg(r3, 16, 32) | reg(r1, 24, 32) | reg(r2, 28, 32)); } inline void Assembler::z_ahhlr( Register r1, Register r2, Register r3) { emit_32( AHHLR_ZOPC | reg(r3, 16, 32) | reg(r1, 24, 32) | reg(r2, 28, 32)); } @@ -1396,6 +1403,8 @@ inline void Assembler::z_brno( Label& L) { z_brc(bcondNotOrdered, target(L)); } inline void Assembler::z_brc( branch_condition m, Label& L) { z_brc(m, target(L)); } inline void Assembler::z_brcl(branch_condition m, Label& L) { z_brcl(m, target(L)); } +inline void Assembler::z_bct( Register r1, int64_t d2, Register b2) { z_bct( r1, d2, Z_R0, b2);} +inline void Assembler::z_bctg(Register r1, int64_t d2, Register b2) { z_bctg(r1, d2, Z_R0, b2);} // Instruction len bits must be stored right-justified in argument. inline unsigned int Assembler::instr_len(unsigned char len_bits) { diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index ef5216a12ba..275f4a8d832 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -5803,3 +5803,87 @@ void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register tmp z_alsi(in_bytes(JavaThread::lock_stack_top_offset()), Z_thread, -oopSize); // pop object z_cr(tmp, tmp); // set CC to EQ } + +void MacroAssembler::pop_count_int(Register r_dst, Register r_src, Register r_tmp) { + BLOCK_COMMENT("pop_count_int {"); + + assert(r_tmp != noreg, "temp register required for pop_count_int, as code may run on machine older than z15"); + assert_different_registers(r_dst, r_tmp); // if r_src is same as r_tmp, it should be fine + + if (VM_Version::has_MiscInstrExt3()) { + pop_count_int_with_ext3(r_dst, r_src); + } else { + pop_count_int_without_ext3(r_dst, r_src, r_tmp); + } + + BLOCK_COMMENT("} pop_count_int"); +} + +void MacroAssembler::pop_count_long(Register r_dst, Register r_src, Register r_tmp) { + BLOCK_COMMENT("pop_count_long {"); + + assert(r_tmp != noreg, "temp register required for pop_count_long, as code may run on machine older than z15"); + assert_different_registers(r_dst, r_tmp); // if r_src is same as r_tmp, it should be fine + + if (VM_Version::has_MiscInstrExt3()) { + pop_count_long_with_ext3(r_dst, r_src); + } else { + pop_count_long_without_ext3(r_dst, r_src, r_tmp); + } + + BLOCK_COMMENT("} pop_count_long"); +} + +void MacroAssembler::pop_count_int_without_ext3(Register r_dst, Register r_src, Register r_tmp) { + BLOCK_COMMENT("pop_count_int_without_ext3 {"); + + assert(r_tmp != noreg, "temp register required for popcnt, for machines < z15"); + assert_different_registers(r_dst, r_tmp); // if r_src is same as r_tmp, it should be fine + + z_popcnt(r_dst, r_src, 0); + z_srlg(r_tmp, r_dst, 16); + z_alr(r_dst, r_tmp); + z_srlg(r_tmp, r_dst, 8); + z_alr(r_dst, r_tmp); + z_llgcr(r_dst, r_dst); + + BLOCK_COMMENT("} pop_count_int_without_ext3"); +} + +void MacroAssembler::pop_count_long_without_ext3(Register r_dst, Register r_src, Register r_tmp) { + BLOCK_COMMENT("pop_count_long_without_ext3 {"); + + assert(r_tmp != noreg, "temp register required for popcnt, for machines < z15"); + assert_different_registers(r_dst, r_tmp); // if r_src is same as r_tmp, it should be fine + + z_popcnt(r_dst, r_src, 0); + z_ahhlr(r_dst, r_dst, r_dst); + z_sllg(r_tmp, r_dst, 16); + z_algr(r_dst, r_tmp); + z_sllg(r_tmp, r_dst, 8); + z_algr(r_dst, r_tmp); + z_srlg(r_dst, r_dst, 56); + + BLOCK_COMMENT("} pop_count_long_without_ext3"); +} + +void MacroAssembler::pop_count_long_with_ext3(Register r_dst, Register r_src) { + BLOCK_COMMENT("pop_count_long_with_ext3 {"); + + guarantee(VM_Version::has_MiscInstrExt3(), + "this hardware doesn't support miscellaneous-instruction-extensions facility 3, still pop_count_long_with_ext3 is used"); + z_popcnt(r_dst, r_src, 8); + + BLOCK_COMMENT("} pop_count_long_with_ext3"); +} + +void MacroAssembler::pop_count_int_with_ext3(Register r_dst, Register r_src) { + BLOCK_COMMENT("pop_count_int_with_ext3 {"); + + guarantee(VM_Version::has_MiscInstrExt3(), + "this hardware doesn't support miscellaneous-instruction-extensions facility 3, still pop_count_long_with_ext3 is used"); + z_llgfr(r_dst, r_src); + z_popcnt(r_dst, r_dst, 8); + + BLOCK_COMMENT("} pop_count_int_with_ext3"); +} diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index 924583abdf5..9f45542dd65 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -1,6 +1,7 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2023 SAP SE. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024 SAP SE. All rights reserved. + * Copyright (c) 2024 IBM Corporation. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1021,6 +1022,19 @@ class MacroAssembler: public Assembler { Register z, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5); + + // These generate optimized code for all supported s390 implementations, and are preferred for most uses. + void pop_count_int(Register dst, Register src, Register tmp); + void pop_count_long(Register dst, Register src, Register tmp); + + // For legacy (pre-z15) use, but will work on all supported s390 implementations. + void pop_count_int_without_ext3(Register dst, Register src, Register tmp); + void pop_count_long_without_ext3(Register dst, Register src, Register tmp); + + // Only for use on z15 or later s390 implementations. + void pop_count_int_with_ext3(Register dst, Register src); + void pop_count_long_with_ext3(Register dst, Register src); + }; /** diff --git a/src/hotspot/cpu/s390/nativeInst_s390.hpp b/src/hotspot/cpu/s390/nativeInst_s390.hpp index 13f15224f8b..8003e1d42f2 100644 --- a/src/hotspot/cpu/s390/nativeInst_s390.hpp +++ b/src/hotspot/cpu/s390/nativeInst_s390.hpp @@ -212,6 +212,7 @@ class NativeCall: public NativeInstruction { call_far_pcrelative_displacement_alignment = 4 }; + static int byte_size() { return instruction_size; } // Maximum size (in bytes) of a call to an absolute address. // Used when emitting call to deopt handler blob, which is a diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 28cac16864d..56cf494d27e 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -10675,10 +10675,49 @@ instruct countTrailingZerosL(revenRegI dst, iRegL src, roddRegL tmp, flagsReg cr // bit count +instruct popCountI_Ext3(iRegI dst, iRegI src, flagsReg cr) %{ + match(Set dst (PopCountI src)); + effect(TEMP_DEF dst, KILL cr); + predicate(UsePopCountInstruction && + VM_Version::has_PopCount() && + VM_Version::has_MiscInstrExt3()); + ins_cost(DEFAULT_COST); + size(8); // popcnt + llgfr + format %{ "POPCNT $dst,$src\t # pop count int" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rsrc = $src$$Register; + + __ pop_count_int_with_ext3(Rdst, Rsrc); + + %} + ins_pipe(pipe_class_dummy); +%} + +instruct popCountL_Ext3(iRegI dst, iRegL src, flagsReg cr) %{ + match(Set dst (PopCountL src)); + effect(TEMP_DEF dst, KILL cr); + predicate(UsePopCountInstruction && + VM_Version::has_PopCount() && + VM_Version::has_MiscInstrExt3()); + ins_cost(DEFAULT_COST); + size(4); // popcnt + format %{ "POPCNT $dst,$src\t # pop count long" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rsrc = $src$$Register; + + __ pop_count_long_with_ext3(Rdst, Rsrc); + %} + ins_pipe(pipe_class_dummy); +%} + instruct popCountI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{ match(Set dst (PopCountI src)); effect(TEMP_DEF dst, TEMP tmp, KILL cr); - predicate(UsePopCountInstruction && VM_Version::has_PopCount()); + predicate(UsePopCountInstruction && + VM_Version::has_PopCount() && + (!VM_Version::has_MiscInstrExt3())); ins_cost(DEFAULT_COST); size(24); format %{ "POPCNT $dst,$src\t # pop count int" %} @@ -10687,17 +10726,8 @@ instruct popCountI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{ Register Rsrc = $src$$Register; Register Rtmp = $tmp$$Register; - // Prefer compile-time assertion over run-time SIGILL. - assert(VM_Version::has_PopCount(), "bad predicate for countLeadingZerosI"); - assert_different_registers(Rdst, Rtmp); + __ pop_count_int_without_ext3(Rdst, Rsrc, Rtmp); - // Version 2: shows 10%(z196) improvement over original. - __ z_popcnt(Rdst, Rsrc); - __ z_srlg(Rtmp, Rdst, 16); // calc byte4+byte6 and byte5+byte7 - __ z_alr(Rdst, Rtmp); // into byte6 and byte7 - __ z_srlg(Rtmp, Rdst, 8); // calc (byte4+byte6) + (byte5+byte7) - __ z_alr(Rdst, Rtmp); // into byte7 - __ z_llgcr(Rdst, Rdst); // zero-extend sum %} ins_pipe(pipe_class_dummy); %} @@ -10705,27 +10735,18 @@ instruct popCountI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{ instruct popCountL(iRegI dst, iRegL src, iRegL tmp, flagsReg cr) %{ match(Set dst (PopCountL src)); effect(TEMP_DEF dst, TEMP tmp, KILL cr); - predicate(UsePopCountInstruction && VM_Version::has_PopCount()); + predicate(UsePopCountInstruction && + VM_Version::has_PopCount() && + (!VM_Version::has_MiscInstrExt3())); ins_cost(DEFAULT_COST); - // TODO: s390 port size(FIXED_SIZE); + size(34); format %{ "POPCNT $dst,$src\t # pop count long" %} ins_encode %{ Register Rdst = $dst$$Register; Register Rsrc = $src$$Register; Register Rtmp = $tmp$$Register; - // Prefer compile-time assertion over run-time SIGILL. - assert(VM_Version::has_PopCount(), "bad predicate for countLeadingZerosI"); - assert_different_registers(Rdst, Rtmp); - - // Original version. Using LA instead of algr seems to be a really bad idea (-35%). - __ z_popcnt(Rdst, Rsrc); - __ z_ahhlr(Rdst, Rdst, Rdst); - __ z_sllg(Rtmp, Rdst, 16); - __ z_algr(Rdst, Rtmp); - __ z_sllg(Rtmp, Rdst, 8); - __ z_algr(Rdst, Rtmp); - __ z_srlg(Rdst, Rdst, 56); + __ pop_count_long_without_ext3(Rdst, Rsrc, Rtmp); %} ins_pipe(pipe_class_dummy); %} diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 50f957aef99..66a782ba9c6 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -172,310 +172,6 @@ inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vle } } -#if INCLUDE_RTM_OPT - -// Update rtm_counters based on abort status -// input: abort_status -// rtm_counters (RTMLockingCounters*) -// flags are killed -void C2_MacroAssembler::rtm_counters_update(Register abort_status, Register rtm_counters) { - - atomic_incptr(Address(rtm_counters, RTMLockingCounters::abort_count_offset())); - if (PrintPreciseRTMLockingStatistics) { - for (int i = 0; i < RTMLockingCounters::ABORT_STATUS_LIMIT; i++) { - Label check_abort; - testl(abort_status, (1< 0) { - // Delay calculation - movptr(tmpReg, ExternalAddress((address) RTMLockingCounters::rtm_calculation_flag_addr())); - testptr(tmpReg, tmpReg); - jccb(Assembler::equal, L_done); - } - // Abort ratio calculation only if abort_count > RTMAbortThreshold - // Aborted transactions = abort_count * 100 - // All transactions = total_count * RTMTotalCountIncrRate - // Set no_rtm bit if (Aborted transactions >= All transactions * RTMAbortRatio) - - movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::abort_count_offset())); - cmpptr(tmpReg, RTMAbortThreshold); - jccb(Assembler::below, L_check_always_rtm2); - imulptr(tmpReg, tmpReg, 100); - - Register scrReg = rtm_counters_Reg; - movptr(scrReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset())); - imulptr(scrReg, scrReg, RTMTotalCountIncrRate); - imulptr(scrReg, scrReg, RTMAbortRatio); - cmpptr(tmpReg, scrReg); - jccb(Assembler::below, L_check_always_rtm1); - if (method_data != nullptr) { - // set rtm_state to "no rtm" in MDO - mov_metadata(tmpReg, method_data); - lock(); - orl(Address(tmpReg, MethodData::rtm_state_offset()), NoRTM); - } - jmpb(L_done); - bind(L_check_always_rtm1); - // Reload RTMLockingCounters* address - lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters)); - bind(L_check_always_rtm2); - movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset())); - cmpptr(tmpReg, RTMLockingThreshold / RTMTotalCountIncrRate); - jccb(Assembler::below, L_done); - if (method_data != nullptr) { - // set rtm_state to "always rtm" in MDO - mov_metadata(tmpReg, method_data); - lock(); - orl(Address(tmpReg, MethodData::rtm_state_offset()), UseRTM); - } - bind(L_done); -} - -// Update counters and perform abort ratio calculation -// input: abort_status_Reg -// rtm_counters_Reg, flags are killed -void C2_MacroAssembler::rtm_profiling(Register abort_status_Reg, - Register rtm_counters_Reg, - RTMLockingCounters* rtm_counters, - Metadata* method_data, - bool profile_rtm) { - - assert(rtm_counters != nullptr, "should not be null when profiling RTM"); - // update rtm counters based on rax value at abort - // reads abort_status_Reg, updates flags - lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters)); - rtm_counters_update(abort_status_Reg, rtm_counters_Reg); - if (profile_rtm) { - // Save abort status because abort_status_Reg is used by following code. - if (RTMRetryCount > 0) { - push(abort_status_Reg); - } - assert(rtm_counters != nullptr, "should not be null when profiling RTM"); - rtm_abort_ratio_calculation(abort_status_Reg, rtm_counters_Reg, rtm_counters, method_data); - // restore abort status - if (RTMRetryCount > 0) { - pop(abort_status_Reg); - } - } -} - -// Retry on abort if abort's status is 0x6: can retry (0x2) | memory conflict (0x4) -// inputs: retry_count_Reg -// : abort_status_Reg -// output: retry_count_Reg decremented by 1 -// flags are killed -void C2_MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register abort_status_Reg, Label& retryLabel) { - Label doneRetry; - assert(abort_status_Reg == rax, ""); - // The abort reason bits are in eax (see all states in rtmLocking.hpp) - // 0x6 = conflict on which we can retry (0x2) | memory conflict (0x4) - // if reason is in 0x6 and retry count != 0 then retry - andptr(abort_status_Reg, 0x6); - jccb(Assembler::zero, doneRetry); - testl(retry_count_Reg, retry_count_Reg); - jccb(Assembler::zero, doneRetry); - pause(); - decrementl(retry_count_Reg); - jmp(retryLabel); - bind(doneRetry); -} - -// Spin and retry if lock is busy, -// inputs: box_Reg (monitor address) -// : retry_count_Reg -// output: retry_count_Reg decremented by 1 -// : clear z flag if retry count exceeded -// tmp_Reg, scr_Reg, flags are killed -void C2_MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg, - Register tmp_Reg, Register scr_Reg, Label& retryLabel) { - Label SpinLoop, SpinExit, doneRetry; - int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner); - - testl(retry_count_Reg, retry_count_Reg); - jccb(Assembler::zero, doneRetry); - decrementl(retry_count_Reg); - movptr(scr_Reg, RTMSpinLoopCount); - - bind(SpinLoop); - pause(); - decrementl(scr_Reg); - jccb(Assembler::lessEqual, SpinExit); - movptr(tmp_Reg, Address(box_Reg, owner_offset)); - testptr(tmp_Reg, tmp_Reg); - jccb(Assembler::notZero, SpinLoop); - - bind(SpinExit); - jmp(retryLabel); - bind(doneRetry); - incrementl(retry_count_Reg); // clear z flag -} - -// Use RTM for normal stack locks -// Input: objReg (object to lock) -void C2_MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Register scrReg, - Register retry_on_abort_count_Reg, - RTMLockingCounters* stack_rtm_counters, - Metadata* method_data, bool profile_rtm, - Label& DONE_LABEL, Label& IsInflated) { - assert(UseRTMForStackLocks, "why call this otherwise?"); - assert(tmpReg == rax, ""); - assert(scrReg == rdx, ""); - Label L_rtm_retry, L_decrement_retry, L_on_abort; - - if (RTMRetryCount > 0) { - movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort - bind(L_rtm_retry); - } - movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); - testptr(tmpReg, markWord::monitor_value); // inflated vs stack-locked|neutral - jcc(Assembler::notZero, IsInflated); - - if (PrintPreciseRTMLockingStatistics || profile_rtm) { - Label L_noincrement; - if (RTMTotalCountIncrRate > 1) { - // tmpReg, scrReg and flags are killed - branch_on_random_using_rdtsc(tmpReg, scrReg, RTMTotalCountIncrRate, L_noincrement); - } - assert(stack_rtm_counters != nullptr, "should not be null when profiling RTM"); - atomic_incptr(ExternalAddress((address)stack_rtm_counters->total_count_addr()), scrReg); - bind(L_noincrement); - } - xbegin(L_on_abort); - movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword - andptr(tmpReg, markWord::lock_mask_in_place); // look at 2 lock bits - cmpptr(tmpReg, markWord::unlocked_value); // bits = 01 unlocked - jcc(Assembler::equal, DONE_LABEL); // all done if unlocked - - Register abort_status_Reg = tmpReg; // status of abort is stored in RAX - if (UseRTMXendForLockBusy) { - xend(); - movptr(abort_status_Reg, 0x2); // Set the abort status to 2 (so we can retry) - jmp(L_decrement_retry); - } - else { - xabort(0); - } - bind(L_on_abort); - if (PrintPreciseRTMLockingStatistics || profile_rtm) { - rtm_profiling(abort_status_Reg, scrReg, stack_rtm_counters, method_data, profile_rtm); - } - bind(L_decrement_retry); - if (RTMRetryCount > 0) { - // retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4) - rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry); - } -} - -// Use RTM for inflating locks -// inputs: objReg (object to lock) -// boxReg (on-stack box address (displaced header location) - KILLED) -// tmpReg (ObjectMonitor address + markWord::monitor_value) -void C2_MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg, - Register scrReg, Register retry_on_busy_count_Reg, - Register retry_on_abort_count_Reg, - RTMLockingCounters* rtm_counters, - Metadata* method_data, bool profile_rtm, - Label& DONE_LABEL) { - assert(UseRTMLocking, "why call this otherwise?"); - assert(tmpReg == rax, ""); - assert(scrReg == rdx, ""); - Label L_rtm_retry, L_decrement_retry, L_on_abort; - int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner); - - movptr(Address(boxReg, 0), checked_cast(markWord::unused_mark().value())); - movptr(boxReg, tmpReg); // Save ObjectMonitor address - - if (RTMRetryCount > 0) { - movl(retry_on_busy_count_Reg, RTMRetryCount); // Retry on lock busy - movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort - bind(L_rtm_retry); - } - if (PrintPreciseRTMLockingStatistics || profile_rtm) { - Label L_noincrement; - if (RTMTotalCountIncrRate > 1) { - // tmpReg, scrReg and flags are killed - branch_on_random_using_rdtsc(tmpReg, scrReg, RTMTotalCountIncrRate, L_noincrement); - } - assert(rtm_counters != nullptr, "should not be null when profiling RTM"); - atomic_incptr(ExternalAddress((address)rtm_counters->total_count_addr()), scrReg); - bind(L_noincrement); - } - xbegin(L_on_abort); - movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); - movptr(tmpReg, Address(tmpReg, owner_offset)); - testptr(tmpReg, tmpReg); - jcc(Assembler::zero, DONE_LABEL); - if (UseRTMXendForLockBusy) { - xend(); - jmp(L_decrement_retry); - } - else { - xabort(0); - } - bind(L_on_abort); - Register abort_status_Reg = tmpReg; // status of abort is stored in RAX - if (PrintPreciseRTMLockingStatistics || profile_rtm) { - rtm_profiling(abort_status_Reg, scrReg, rtm_counters, method_data, profile_rtm); - } - if (RTMRetryCount > 0) { - // retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4) - rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry); - } - - movptr(tmpReg, Address(boxReg, owner_offset)) ; - testptr(tmpReg, tmpReg) ; - jccb(Assembler::notZero, L_decrement_retry) ; - - // Appears unlocked - try to swing _owner from null to non-null. - // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. -#ifdef _LP64 - Register threadReg = r15_thread; -#else - get_thread(scrReg); - Register threadReg = scrReg; -#endif - lock(); - cmpxchgptr(threadReg, Address(boxReg, owner_offset)); // Updates tmpReg - - if (RTMRetryCount > 0) { - // success done else retry - jccb(Assembler::equal, DONE_LABEL) ; - bind(L_decrement_retry); - // Spin and retry if lock is busy. - rtm_retry_lock_on_busy(retry_on_busy_count_Reg, boxReg, tmpReg, scrReg, L_rtm_retry); - } - else { - bind(L_decrement_retry); - } -} - -#endif // INCLUDE_RTM_OPT - // fast_lock and fast_unlock used by C2 // Because the transitions from emitted code to the runtime @@ -554,21 +250,13 @@ void C2_MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, R // scr: tmp -- KILLED void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg, Register scrReg, Register cx1Reg, Register cx2Reg, Register thread, - RTMLockingCounters* rtm_counters, - RTMLockingCounters* stack_rtm_counters, - Metadata* method_data, - bool use_rtm, bool profile_rtm) { + Metadata* method_data) { assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight"); // Ensure the register assignments are disjoint assert(tmpReg == rax, ""); - - if (use_rtm) { - assert_different_registers(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg); - } else { - assert(cx1Reg == noreg, ""); - assert(cx2Reg == noreg, ""); - assert_different_registers(objReg, boxReg, tmpReg, scrReg); - } + assert(cx1Reg == noreg, ""); + assert(cx2Reg == noreg, ""); + assert_different_registers(objReg, boxReg, tmpReg, scrReg); // Possible cases that we'll encounter in fast_lock // ------------------------------------------------ @@ -594,15 +282,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp jcc(Assembler::notZero, DONE_LABEL); } -#if INCLUDE_RTM_OPT - if (UseRTMForStackLocks && use_rtm) { - assert(LockingMode != LM_MONITOR, "LockingMode == 0 (LM_MONITOR) and +UseRTMForStackLocks are mutually exclusive"); - rtm_stack_locking(objReg, tmpReg, scrReg, cx2Reg, - stack_rtm_counters, method_data, profile_rtm, - DONE_LABEL, IsInflated); - } -#endif // INCLUDE_RTM_OPT - movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // [FETCH] testptr(tmpReg, markWord::monitor_value); // inflated vs stack-locked|neutral jcc(Assembler::notZero, IsInflated); @@ -632,14 +311,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp bind(IsInflated); // The object is inflated. tmpReg contains pointer to ObjectMonitor* + markWord::monitor_value -#if INCLUDE_RTM_OPT - // Use the same RTM locking code in 32- and 64-bit VM. - if (use_rtm) { - rtm_inflated_locking(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg, - rtm_counters, method_data, profile_rtm, DONE_LABEL); - } else { -#endif // INCLUDE_RTM_OPT - #ifndef _LP64 // The object is inflated. @@ -700,9 +371,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp incq(Address(scrReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); xorq(rax, rax); // Set ZF = 1 (success) for recursive lock, denoting locking success #endif // _LP64 -#if INCLUDE_RTM_OPT - } // use_rtm() -#endif bind(DONE_LABEL); // ZFlag == 1 count in fast path @@ -755,27 +423,13 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp // A perfectly viable alternative is to elide the owner check except when // Xcheck:jni is enabled. -void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) { +void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg) { assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight"); assert(boxReg == rax, ""); assert_different_registers(objReg, boxReg, tmpReg); Label DONE_LABEL, Stacked, COUNT, NO_COUNT; -#if INCLUDE_RTM_OPT - if (UseRTMForStackLocks && use_rtm) { - assert(LockingMode != LM_MONITOR, "LockingMode == 0 (LM_MONITOR) and +UseRTMForStackLocks are mutually exclusive"); - Label L_regular_unlock; - movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword - andptr(tmpReg, markWord::lock_mask_in_place); // look at 2 lock bits - cmpptr(tmpReg, markWord::unlocked_value); // bits = 01 unlocked - jccb(Assembler::notEqual, L_regular_unlock); // if !HLE RegularLock - xend(); // otherwise end... - jmp(DONE_LABEL); // ... and we're done - bind(L_regular_unlock); - } -#endif - if (LockingMode == LM_LEGACY) { cmpptr(Address(boxReg, 0), NULL_WORD); // Examine the displaced header jcc (Assembler::zero, COUNT); // 0 indicates recursive stack-lock @@ -788,19 +442,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t // It's inflated. -#if INCLUDE_RTM_OPT - if (use_rtm) { - Label L_regular_inflated_unlock; - int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner); - movptr(boxReg, Address(tmpReg, owner_offset)); - testptr(boxReg, boxReg); - jccb(Assembler::notZero, L_regular_inflated_unlock); - xend(); - jmp(DONE_LABEL); - bind(L_regular_inflated_unlock); - } -#endif - // Despite our balanced locking property we still check that m->_owner == Self // as java routines or native JNI code called by this thread might // have released the lock. @@ -4491,13 +4132,21 @@ void C2_MacroAssembler::count_positives(Register ary1, Register len, // Compare char[] or byte[] arrays aligned to 4 bytes or substrings. void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register ary2, Register limit, Register result, Register chr, - XMMRegister vec1, XMMRegister vec2, bool is_char, KRegister mask) { + XMMRegister vec1, XMMRegister vec2, bool is_char, + KRegister mask, bool expand_ary2) { + // for expand_ary2, limit is the (smaller) size of the second array. ShortBranchVerifier sbv(this); Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR, COMPARE_BYTE; + assert((!expand_ary2) || ((expand_ary2) && (UseAVX == 2)), + "Expansion only implemented for AVX2"); + int length_offset = arrayOopDesc::length_offset_in_bytes(); int base_offset = arrayOopDesc::base_offset_in_bytes(is_char ? T_CHAR : T_BYTE); + Address::ScaleFactor scaleFactor = expand_ary2 ? Address::times_2 : Address::times_1; + int scaleIncr = expand_ary2 ? 8 : 16; + if (is_array_equ) { // Check the input args cmpoop(ary1, ary2); @@ -4533,14 +4182,20 @@ void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register if (UseAVX >= 2) { // With AVX2, use 32-byte vector compare - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + Label COMPARE_WIDE_VECTORS, COMPARE_WIDE_VECTORS_16, COMPARE_TAIL, COMPARE_TAIL_16; // Compare 32-byte vectors - andl(result, 0x0000001f); // tail count (in bytes) - andl(limit, 0xffffffe0); // vector count (in bytes) - jcc(Assembler::zero, COMPARE_TAIL); + if (expand_ary2) { + andl(result, 0x0000000f); // tail count (in bytes) + andl(limit, 0xfffffff0); // vector count (in bytes) + jcc(Assembler::zero, COMPARE_TAIL); + } else { + andl(result, 0x0000001f); // tail count (in bytes) + andl(limit, 0xffffffe0); // vector count (in bytes) + jcc(Assembler::zero, COMPARE_TAIL_16); + } - lea(ary1, Address(ary1, limit, Address::times_1)); + lea(ary1, Address(ary1, limit, scaleFactor)); lea(ary2, Address(ary2, limit, Address::times_1)); negptr(limit); @@ -4583,25 +4238,59 @@ void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register }//if (VM_Version::supports_avx512vlbw()) #endif //_LP64 bind(COMPARE_WIDE_VECTORS); - vmovdqu(vec1, Address(ary1, limit, Address::times_1)); - vmovdqu(vec2, Address(ary2, limit, Address::times_1)); + vmovdqu(vec1, Address(ary1, limit, scaleFactor)); + if (expand_ary2) { + vpmovzxbw(vec2, Address(ary2, limit, Address::times_1), Assembler::AVX_256bit); + } else { + vmovdqu(vec2, Address(ary2, limit, Address::times_1)); + } vpxor(vec1, vec2); vptest(vec1, vec1); jcc(Assembler::notZero, FALSE_LABEL); - addptr(limit, 32); + addptr(limit, scaleIncr * 2); jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); testl(result, result); jcc(Assembler::zero, TRUE_LABEL); - vmovdqu(vec1, Address(ary1, result, Address::times_1, -32)); - vmovdqu(vec2, Address(ary2, result, Address::times_1, -32)); + vmovdqu(vec1, Address(ary1, result, scaleFactor, -32)); + if (expand_ary2) { + vpmovzxbw(vec2, Address(ary2, result, Address::times_1, -16), Assembler::AVX_256bit); + } else { + vmovdqu(vec2, Address(ary2, result, Address::times_1, -32)); + } vpxor(vec1, vec2); vptest(vec1, vec1); - jccb(Assembler::notZero, FALSE_LABEL); - jmpb(TRUE_LABEL); + jcc(Assembler::notZero, FALSE_LABEL); + jmp(TRUE_LABEL); + + bind(COMPARE_TAIL_16); // limit is zero + movl(limit, result); + + // Compare 16-byte chunks + andl(result, 0x0000000f); // tail count (in bytes) + andl(limit, 0xfffffff0); // vector count (in bytes) + jcc(Assembler::zero, COMPARE_TAIL); + + lea(ary1, Address(ary1, limit, scaleFactor)); + lea(ary2, Address(ary2, limit, Address::times_1)); + negptr(limit); + + bind(COMPARE_WIDE_VECTORS_16); + movdqu(vec1, Address(ary1, limit, scaleFactor)); + if (expand_ary2) { + vpmovzxbw(vec2, Address(ary2, limit, Address::times_1), Assembler::AVX_128bit); + } else { + movdqu(vec2, Address(ary2, limit, Address::times_1)); + } + pxor(vec1, vec2); + + ptest(vec1, vec1); + jcc(Assembler::notZero, FALSE_LABEL); + addptr(limit, scaleIncr); + jcc(Assembler::notZero, COMPARE_WIDE_VECTORS_16); bind(COMPARE_TAIL); // limit is zero movl(limit, result); @@ -4646,19 +4335,34 @@ void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register } // Compare 4-byte vectors - andl(limit, 0xfffffffc); // vector count (in bytes) - jccb(Assembler::zero, COMPARE_CHAR); + if (expand_ary2) { + testl(result, result); + jccb(Assembler::zero, TRUE_LABEL); + } else { + andl(limit, 0xfffffffc); // vector count (in bytes) + jccb(Assembler::zero, COMPARE_CHAR); + } - lea(ary1, Address(ary1, limit, Address::times_1)); + lea(ary1, Address(ary1, limit, scaleFactor)); lea(ary2, Address(ary2, limit, Address::times_1)); negptr(limit); bind(COMPARE_VECTORS); - movl(chr, Address(ary1, limit, Address::times_1)); - cmpl(chr, Address(ary2, limit, Address::times_1)); - jccb(Assembler::notEqual, FALSE_LABEL); - addptr(limit, 4); - jcc(Assembler::notZero, COMPARE_VECTORS); + if (expand_ary2) { + // There are no "vector" operations for bytes to shorts + movzbl(chr, Address(ary2, limit, Address::times_1)); + cmpw(Address(ary1, limit, Address::times_2), chr); + jccb(Assembler::notEqual, FALSE_LABEL); + addptr(limit, 1); + jcc(Assembler::notZero, COMPARE_VECTORS); + jmp(TRUE_LABEL); + } else { + movl(chr, Address(ary1, limit, Address::times_1)); + cmpl(chr, Address(ary2, limit, Address::times_1)); + jccb(Assembler::notEqual, FALSE_LABEL); + addptr(limit, 4); + jcc(Assembler::notZero, COMPARE_VECTORS); + } // Compare trailing char (final 2 bytes), if any bind(COMPARE_CHAR); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 8c22990892b..e268ed3dd7a 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -37,39 +37,13 @@ // See full description in macroAssembler_x86.cpp. void fast_lock(Register obj, Register box, Register tmp, Register scr, Register cx1, Register cx2, Register thread, - RTMLockingCounters* rtm_counters, - RTMLockingCounters* stack_rtm_counters, - Metadata* method_data, - bool use_rtm, bool profile_rtm); - void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm); + Metadata* method_data); + void fast_unlock(Register obj, Register box, Register tmp); void fast_lock_lightweight(Register obj, Register box, Register rax_reg, Register t, Register thread); void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread); -#if INCLUDE_RTM_OPT - void rtm_counters_update(Register abort_status, Register rtm_counters); - void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel); - void rtm_abort_ratio_calculation(Register tmp, Register rtm_counters_reg, - RTMLockingCounters* rtm_counters, - Metadata* method_data); - void rtm_profiling(Register abort_status_Reg, Register rtm_counters_Reg, - RTMLockingCounters* rtm_counters, Metadata* method_data, bool profile_rtm); - void rtm_retry_lock_on_abort(Register retry_count, Register abort_status, Label& retryLabel); - void rtm_retry_lock_on_busy(Register retry_count, Register box, Register tmp, Register scr, Label& retryLabel); - void rtm_stack_locking(Register obj, Register tmp, Register scr, - Register retry_on_abort_count, - RTMLockingCounters* stack_rtm_counters, - Metadata* method_data, bool profile_rtm, - Label& DONE_LABEL, Label& IsInflated); - void rtm_inflated_locking(Register obj, Register box, Register tmp, - Register scr, Register retry_on_busy_count, - Register retry_on_abort_count, - RTMLockingCounters* rtm_counters, - Metadata* method_data, bool profile_rtm, - Label& DONE_LABEL); -#endif - // Generic instructions support for use in .ad files C2 code generation void vabsnegd(int opcode, XMMRegister dst, XMMRegister src); void vabsnegd(int opcode, XMMRegister dst, XMMRegister src, int vector_len); @@ -289,10 +263,11 @@ void count_positives(Register ary1, Register len, Register result, Register tmp1, XMMRegister vec1, XMMRegister vec2, KRegister mask1 = knoreg, KRegister mask2 = knoreg); + // Compare char[] or byte[] arrays. - void arrays_equals(bool is_array_equ, Register ary1, Register ary2, - Register limit, Register result, Register chr, - XMMRegister vec1, XMMRegister vec2, bool is_char, KRegister mask = knoreg); + void arrays_equals(bool is_array_equ, Register ary1, Register ary2, Register limit, + Register result, Register chr, XMMRegister vec1, XMMRegister vec2, + bool is_char, KRegister mask = knoreg, bool expand_ary2 = false); void arrays_hashcode(Register str1, Register cnt1, Register result, Register tmp1, Register tmp2, Register tmp3, XMMRegister vnext, diff --git a/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp new file mode 100644 index 00000000000..34f8bec8d11 --- /dev/null +++ b/src/hotspot/cpu/x86/c2_stubGenerator_x86_64_string.cpp @@ -0,0 +1,1837 @@ +/* + * Copyright (c) 2024, Intel Corporation. All rights reserved. + * + * 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 "macroAssembler_x86.hpp" +#include "stubGenerator_x86_64.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/intrinsicnode.hpp" + +/******************************************************************************/ +// String handling intrinsics +// -------------------------- +// +// Currently implements scheme described in http://0x80.pl/articles/simd-strfind.html +// Implementation can be found at https://github.com/WojciechMula/sse4-strstr +// +// The general idea is as follows: +// 1. Broadcast the first byte of the needle to a ymm register (32 bytes) +// 2. Broadcast the last byte of the needle to a different ymm register +// 3. Compare the first-byte ymm register to the first 32 bytes of the haystack +// 4. Compare the last-byte register to the 32 bytes of the haystack at the (k-1)st position +// where k is the length of the needle +// 5. Logically AND the results of the comparison +// +// The result of the AND yields the position within the haystack where both the first +// and last bytes of the needle exist in their correct relative positions. Check the full +// needle value against the haystack to confirm a match. +// +// This implementation uses memcmp to compare when the size of the needle is >= 32 bytes. +// For other needle sizes, the comparison is done with register compares to eliminate the +// overhead of the call (including range checks, etc.). The size of the comparison is +// known, and it is also known to be safe reading the haystack for the full width of the needle. +// +// The original algorithm as implemented will potentially read past the end of the haystack. +// This implementation protects against that. Instead of reading as many 32-byte chunks as +// possible and then handling the tail, we calculate the last position of a vaild 32-byte +// read and adjust the starting position of the second read such that the last read will not +// go beyond the end of the haystack. So the first comparison is to the first 32 bytes of the +// haystack, and the second is offset by an amount to make the last read legal. The remainder of +// the comparisons are done incrementing by 32 bytes. +// +// This will cause 16 bytes on average to be examined twice, but that is cheaper than the +// logic required for tail processing. +// +/******************************************************************************/ + +#define __ _masm-> +#define __C2 ((C2_MacroAssembler *) _masm)-> + +// Register definitions for consistency +// These registers can be counted on to always contain +// the correct values (once set up) +#define XMM_BYTE_0 xmm0 +#define XMM_BYTE_K xmm1 +#define XMM_BYTE_1 xmm12 +#define save_r12 xmm4 +#define save_r13 xmm5 +#define save_r14 xmm6 +#define save_r15 xmm7 +#define save_rbx xmm8 +#define nMinusK r10 + +// Global temporary xmm registers +#define XMM_TMP1 xmm15 +#define XMM_TMP2 xmm14 +#define XMM_TMP3 xmm2 +#define XMM_TMP4 xmm3 + +// This macro handles clearing the bits of the mask register depending +// on whether we're comparing bytes or words. +#define CLEAR_BIT(mask) \ + if (isU) { \ + __ blsrl(mask, mask); \ + __ blsrl(mask, mask); \ + } else { \ + __ blsrl(mask, mask); \ + } + +#define NUMBER_OF_CASES 10 + +#undef STACK_SPACE +#undef MAX_NEEDLE_LEN_TO_EXPAND +#define MAX_NEEDLE_LEN_TO_EXPAND 0x28 + +// Stack layout: +# define COPIED_HAYSTACK_STACK_OFFSET (0x0) // MUST BE ZERO! +# define COPIED_HAYSTACK_STACK_SIZE (64) // MUST BE 64! + +# define EXPANDED_NEEDLE_STACK_OFFSET (COPIED_HAYSTACK_STACK_OFFSET + COPIED_HAYSTACK_STACK_SIZE) +# define EXPANDED_NEEDLE_STACK_SIZE (MAX_NEEDLE_LEN_TO_EXPAND * 2 + 32) + +# define SAVED_HAYSTACK_STACK_OFFSET (EXPANDED_NEEDLE_STACK_OFFSET + EXPANDED_NEEDLE_STACK_SIZE) +# define SAVED_HAYSTACK_STACK_SIZE (8) + +# define SAVED_INCREMENT_STACK_OFFSET (SAVED_HAYSTACK_STACK_OFFSET + SAVED_HAYSTACK_STACK_SIZE) +# define SAVED_INCREMENT_STACK_SIZE (8) + +# define SAVED_TERM_ADDR_STACK_OFFSET (SAVED_INCREMENT_STACK_OFFSET + SAVED_INCREMENT_STACK_SIZE) +# define SAVED_TERM_ADDR_STACK_SIZE (8) + +# define STACK_SPACE \ + (COPIED_HAYSTACK_STACK_SIZE + EXPANDED_NEEDLE_STACK_SIZE + SAVED_HAYSTACK_STACK_SIZE + SAVED_INCREMENT_STACK_SIZE \ + + SAVED_TERM_ADDR_STACK_SIZE) + +// Forward declarations for helper functions +static void broadcast_additional_needles(bool sizeKnown, int size, Register needle, + Register needleLen, Register rTmp, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm); + +static void broadcast_first_and_last_needle(Register needle, Register needle_len, Register rTmp, + StrIntrinsicNode::ArgEncoding ae, + MacroAssembler *_masm); + +static void compare_big_haystack_to_needle(bool sizeKnown, int size, Label &noMatch, + Register haystack, Register needleLen, Register eq_mask, + XMMRegister rxTmp1, XMMRegister rxTmp2, + XMMRegister rxTmp3, StrIntrinsicNode::ArgEncoding ae, + MacroAssembler *_masm); + +static void compare_haystack_to_needle(bool sizeKnown, int size, Label &noMatch, Register haystack, + Register eq_mask, Register needleLen, Register rTmp, + XMMRegister rxTmp1, XMMRegister rxTmp2, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm); + +static void big_case_loop_helper(bool sizeKnown, int size, Label &noMatch, Label &loop_top, + Register eq_mask, Register hsPtrRet, Register needleLen, + Register needle, Register haystack, Register hsLength, + Register rTmp1, Register rTmp2, Register rTmp3, Register rTmp4, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm); + +static void byte_compare_helper(int size, Label &L_noMatch, Label &L_matchFound, Register needle, + Register needleVal, Register haystack, Register mask, + Register foundIndex, Register tmp, StrIntrinsicNode::ArgEncoding ae, + MacroAssembler *_masm); + +static void highly_optimized_short_cases(StrIntrinsicNode::ArgEncoding ae, Register haystack, + Register haystack_len, Register needle, + Register needle_len, XMMRegister XMM0, XMMRegister XMM1, + Register mask, Register tmp, MacroAssembler *_masm); + +static void setup_jump_tables(StrIntrinsicNode::ArgEncoding ae, Label &L_error, Label &L_checkRange, + Label &L_fixup, address *big_jump_table, address *small_jump_table, + MacroAssembler *_masm); + +static void vpcmpeq(XMMRegister dst, XMMRegister src, Address adr, int vector_len, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm) { + if ((ae == StrIntrinsicNode::UL) || (ae == StrIntrinsicNode::UU)) { + __ vpcmpeqw(dst, src, adr, vector_len); + } else { + __ vpcmpeqb(dst, src, adr, vector_len); + } +} + +static void generate_string_indexof_stubs(StubGenerator *stubgen, address *fnptrs, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm); + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +// Start of generator +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +void StubGenerator::generate_string_indexof(address *fnptrs) { + assert((int) StrIntrinsicNode::LL < 4, "Enum out of range"); + assert((int) StrIntrinsicNode::UL < 4, "Enum out of range"); + assert((int) StrIntrinsicNode::UU < 4, "Enum out of range"); + generate_string_indexof_stubs(this, fnptrs, StrIntrinsicNode::LL, _masm); + generate_string_indexof_stubs(this, fnptrs, StrIntrinsicNode::UU, _masm); + generate_string_indexof_stubs(this, fnptrs, StrIntrinsicNode::UL, _masm); + assert(fnptrs[StrIntrinsicNode::LL] != nullptr, "LL not generated."); + assert(fnptrs[StrIntrinsicNode::UL] != nullptr, "UL not generated."); + assert(fnptrs[StrIntrinsicNode::UU] != nullptr, "UU not generated."); +} + +static void generate_string_indexof_stubs(StubGenerator *stubgen, address *fnptrs, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm) { + StubCodeMark mark(stubgen, "StubRoutines", "stringIndexOf"); + bool isLL = (ae == StrIntrinsicNode::LL); + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = isUL || isUU; // At least one is UTF-16 + assert(isLL || isUL || isUU, "Encoding not recognized"); + + // Keep track of isUL since we need to generate UU code in the main body + // for the case where we expand the needle from bytes to words on the stack. + // This is done at L_wcharBegin. The algorithm used is: + // If the encoding is UL and the needle size is <= MAX_NEEDLE_LEN_TO_EXPAND, + // allocate space on the stack and expand the Latin-1 encoded needle. Then + // effectively "recurse" into the mainline using UU encoding (since both the + // haystack and needle are now UTF-16 encoded). + bool isReallyUL = isUL; + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // AVX2 code + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + assert(VM_Version::supports_avx2(), "Needs AVX2"); + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // Code generation explanation: + // + // The generator will generate code for three cases: + // 1. Both needle and haystack are Latin-1 (single byte) encoded (LL) + // 2. Both the needle and haystack are UTF-16 encoded (two bytes per character) (UU) + // 3. The haystack is UTF-16 encoded and the needle is Latin-1 encoded (UL) + // + // The case of the haystack being Latin-1 and the needle being UTF-16 is short-circuited + // so that we never get called in this case. + // + // For the UL case (haystack UTF-16 and needle Latin-1), the needle will be expanded + // onto the stack (for size <= MAX_NEEDLE_LEN_TO_EXPAND) and the UU code will do the work. + // For UL where the needle size is > MAX_NEEDLE_LEN_TO_EXPAND and the haystack size minus + // the needle size is less than 32 bytes, we default to a + // byte-by-byte comparison (this will be rare). + // + // Note that the code assumes MAX_NEEDLE_LEN_TO_EXPAND is >= 32. + // + // The UU and LL cases are identical except for the loop increments and loading + // of the characters into registers. UU loads and compares words, LL - bytes. + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + + const Register haystack_p = c_rarg0; + const Register haystack_len_p = c_rarg1; + const Register needle_p = c_rarg2; + const Register needle_len_p = c_rarg3; + + // Addresses of the two jump tables used for small needle processing + address big_jump_table; + address small_jump_table; + + Label L_begin; + + Label L_returnError, L_bigCaseFixupAndReturn; + Label L_bigSwitchTop, L_bigCaseDefault, L_smallCaseDefault; + Label L_nextCheck, L_checksPassed, L_return; + Label L_wcharBegin, L_continue, L_wideNoExpand, L_returnR11; + + __ align(CodeEntryAlignment); + fnptrs[ae] = __ pc(); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + // Check for trivial cases + // needle length == 0? + __ cmpq(needle_len_p, 0); + __ jg_b(L_nextCheck); + __ xorl(rax, rax); + __ leave(); + __ ret(0); + + __ bind(L_nextCheck); + // haystack length >= needle length? + __ movq(rax, haystack_len_p); + __ subq(rax, needle_len_p); + __ jge_b(L_checksPassed); + + __ movq(rax, -1); + __ leave(); + __ ret(0); + + __ bind(L_checksPassed); + + // Check for highly-optimized ability - haystack <= 32 bytes and needle <= 6 bytes + // haystack_len is in elements, not bytes, for UTF-16 + __ cmpq(haystack_len_p, isU ? 16 : 32); + __ ja(L_begin); + + // needle_len is in elements, not bytes, for UTF-16 <=> UTF-16 + __ cmpq(needle_len_p, isUU ? 3 : 6); + __ ja(L_begin); + + // Handle short haystack and needle specially + // Generated code does not return - either found or not + highly_optimized_short_cases(ae, haystack_p, haystack_len_p, needle_p, needle_len_p, xmm0, xmm1, + r10, r11, _masm); + + // If we're generating UL, we need to "pretend" we're generating UU code + // for the case where the needle can be expanded onto the stack + if (isReallyUL) { + ae = StrIntrinsicNode::UU; + isUL = false; + isUU = true; + } + + // Set up jump tables. Used when needle size <= NUMBER_OF_CASES + setup_jump_tables(ae, L_returnError, L_returnR11, L_bigCaseFixupAndReturn, &big_jump_table, + &small_jump_table, _masm); + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // The above code handles all cases (LL, UL, UU) for haystack size <= 32 bytes + // and needle size <= 6 bytes. + // + // Main processing proceeds as follows: + // Save state and setup stack, etc. + // If UL, jump to code to handle special-case UL situations (see L_wcharBegin below) + // Broadcast the first and last needle elements to XMM_BYTE_0 and XMM_BYTE_K, respectively + // If the length in bytes of the haystack is > 32, dispatch to the big switch handling code + // If the haystack length in bytes is <= 32: + // Copy the haystack to the stack. This is done to prevent possible page faults and + // allows for reading full 32-byte chunks of the haystack. + // Dispatch to the small switch handling code + // + // Here, "big switch" and "small switch" refers to the haystack size: > 32 bytes for big + // and <= 32 bytes for small. The switches implement optimized code for handling 1 to + // NUMBER_OF_CASES (currently 10) needle sizes for both big and small. There are special + // routines for handling needle sizes > NUMBER_OF_CASES (L_{big,small}CaseDefault). These + // cases use C2's arrays_equals() to compare the needle to the haystack. The small cases + // use specialized code for comparing the needle. + // + // The algorithm currently does vector comparisons for the first, last, and second bytes + // of the needle and, where each of these needle elements matches the correct position + // within the haystack, the "in-between" bytes are compared using the most efficient + // instructions possible for short needles, or C2's arrays_equals for longer needles. + + __ align(CodeEntryAlignment); + + __ bind(L_begin); + __ movdq(save_r12, r12); + __ movdq(save_r13, r13); + __ movdq(save_r14, r14); + __ movdq(save_r15, r15); + __ movdq(save_rbx, rbx); +#ifdef _WIN64 + __ push(rsi); + __ push(rdi); + + // Move to Linux-style ABI + __ movq(rdi, rcx); + __ movq(rsi, rdx); + __ movq(rdx, r8); + __ movq(rcx, r9); +#endif + + const Register haystack = rdi; + const Register haystack_len = rsi; + const Register needle = rdx; + const Register needle_len = rcx; + const Register save_ndl_len = r12; + + __ push(rbp); + __ subptr(rsp, STACK_SPACE); + + if (isReallyUL) { + // Branch out if doing UL + __ jmp(L_wcharBegin); + } + + if (!isReallyUL && isUU) { // Adjust sizes of hs and needle + // UU passes lengths in terms of chars - convert to bytes + __ shlq(needle_len, 1); + __ shlq(haystack_len, 1); + } + + // UL processing comes here after expanding needle + __ bind(L_continue); + // nMinusK (haystack length in bytes minus needle length in bytes) is used several + // places to determine whether a compare will read past the end of the haystack. + __ movq(nMinusK, haystack_len); + __ subq(nMinusK, needle_len); + + // Set up expected registers + __ movq(save_ndl_len, needle_len); + __ movq(r14, needle); + __ movq(rbx, haystack); + + // Always need needle broadcast to ymm registers (XMM_BYTE_0 and XMM_BYTE_K) + broadcast_first_and_last_needle(needle, needle_len, rax, ae, _masm); + + // Do "big switch" if haystack size > 32 + __ cmpq(haystack_len, 0x20); + __ ja_b(L_bigSwitchTop); + + // Copy the small (< 32 byte) haystack to the stack. Allows for vector reads without page fault + // Only done for small haystacks + // + // NOTE: This code assumes that the haystack points to a java array type AND there are + // at least 16 bytes of header preceeding the haystack pointer. + // + // This means that we're copying up to 15 bytes of the header onto the stack along + // with the haystack bytes. After the copy completes, we adjust the haystack pointer + // to the valid haystack bytes on the stack. + { + Label L_moreThan16, L_adjustHaystack; + + const Register index = rax; + const Register haystack = rbx; + + // Only a single vector load/store of either 16 or 32 bytes + __ cmpq(haystack_len, 0x10); + __ ja_b(L_moreThan16); + + __ movq(index, COPIED_HAYSTACK_STACK_OFFSET + 0x10); + __ movdqu(XMM_TMP1, Address(haystack, haystack_len, Address::times_1, -0x10)); + __ movdqu(Address(rsp, COPIED_HAYSTACK_STACK_OFFSET), XMM_TMP1); + __ jmpb(L_adjustHaystack); + + __ bind(L_moreThan16); + __ movq(index, COPIED_HAYSTACK_STACK_OFFSET + 0x20); + __ vmovdqu(XMM_TMP1, Address(haystack, haystack_len, Address::times_1, -0x20)); + __ vmovdqu(Address(rsp, COPIED_HAYSTACK_STACK_OFFSET), XMM_TMP1); + + // Point the haystack at the correct location of the first byte of the "real" haystack on the stack + __ bind(L_adjustHaystack); + __ subq(index, haystack_len); + __ leaq(haystack, Address(rsp, index, Address::times_1)); + } + + // Dispatch to handlers for small needle and small haystack + // Note that needle sizes of 1-6 have been handled in highly_optimized_short_cases, + // so the dispatch only has valid entries for 7-10. + __ leaq(r13, Address(save_ndl_len, -1)); + __ cmpq(r13, NUMBER_OF_CASES - 1); + __ ja(L_smallCaseDefault); + __ lea(r15, InternalAddress(small_jump_table)); + __ jmp(Address(r15, r13, Address::times_8)); + + // Dispatch to handlers for small needle and large haystack + // For large haystacks, the jump table is fully populated (1-10) + __ bind(L_bigSwitchTop); + __ leaq(rax, Address(save_ndl_len, -1)); + __ cmpq(rax, NUMBER_OF_CASES - 1); + __ ja(L_bigCaseDefault); + __ lea(r15, InternalAddress(big_jump_table)); + __ jmp(Address(r15, rax, Address::times_8)); + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // Fixup and return routines + + // Return not found + __ bind(L_returnError); + __ movq(rax, -1); + __ jmpb(L_return); + + // At this point, rcx has &haystack where match found, rbx has &haystack, + // and r8 has the index where a match was found + __ bind(L_bigCaseFixupAndReturn); + __ subq(rcx, rbx); + __ addq(rcx, r8); + + __ movq(r11, rcx); + + // r11 will contain the valid index. + __ bind(L_returnR11); + __ movq(rax, r11); + + // Restore stack, vzeroupper and return + __ bind(L_return); + __ addptr(rsp, STACK_SPACE); + __ pop(rbp); +#ifdef _WIN64 + __ pop(rdi); + __ pop(rsi); +#endif + __ movdq(r12, save_r12); + __ movdq(r13, save_r13); + __ movdq(r14, save_r14); + __ movdq(r15, save_r15); + __ movdq(rbx, save_rbx); + + // Need to return elements for UTF-16 encodings + if (isU) { + // Return value for UTF-16 is elements, not bytes + // sar is used to preserve -1 + __ sarq(rax, 1); + } + __ vzeroupper(); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // Big case default: + // + // Handle needle sizes > 10 bytes. Uses C2's arrays_equals to compare the contents + // of the needle to the haystack. + + { + Label L_loopTop, L_innerLoop, L_found; + + const Register hsPtrRet = rax; + const Register mask = r8; + const Register index = r9; + const Register compLen = rbp; + const Register haystackStart = rcx; + const Register rScratch = r13; + const Register needleLen = r12; + const Register needle = r14; + const Register haystack = rbx; + const Register hsLength = rsi; + const Register tmp1 = rdi; + +// #define used for registers that are re-used in the code +#undef retval +#undef firstNeedleCompare +#undef tmp2 +#undef tmp3 +#define tmp2 r15 +#define tmp3 rdx + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // Big case default: registers on entry + // + // rbx: haystack + // rcx: k + // rdx: junk + // rsi: n + // rdi: haystack + // r10: n - k + // r12: k + // r13: junk + // r14: needle + // rbp: junk + // XMM_BYTE_0 - first element of needle broadcast + // XMM_BYTE_K - last element of needle broadcast + // + // Set up in big_case_loop_helper + // XMM_BYTE_1 - second element of needle broadcast + + __ bind(L_bigCaseDefault); + + // Loop construct handling for big haystacks + // The helper binds L_loopTop which should be jumped to if potential matches fail to compare + // equal (thus moving on to the next chunk of haystack). If we run out of haystack, the + // helper jumps to L_returnError. + big_case_loop_helper(false, 0, L_returnError, L_loopTop, mask, hsPtrRet, needleLen, needle, + haystack, hsLength, tmp1, tmp2, tmp3, rScratch, ae, _masm); + + // big_case_loop_helper will fall through to this point if one or more potential matches are found + // The mask will have a bitmask indicating the position of the potential matches within the haystack + __ align(OptoLoopAlignment); + __ bind(L_innerLoop); + __ tzcntl(index, mask); + +// Re-use of r15 and rdx +#undef tmp2 +#undef tmp3 +#define retval r15 +#define firstNeedleCompare rdx + + // Need a lot of registers here to preserve state across arrays_equals call + + // Starting address in the haystack + __ leaq(haystackStart, Address(hsPtrRet, index, Address::times_1, isU ? 4 : 2)); + // Starting address of first byte of needle to compare + __ leaq(firstNeedleCompare, Address(needle, isU ? 4 : 2)); + // Number of bytes to compare + __ leaq(compLen, Address(needleLen, isU ? -6 : -3)); + + // Call arrays_equals for both UU and LL cases as bytes should compare exact + __C2 arrays_equals(false, haystackStart, firstNeedleCompare, compLen, retval, rScratch, + XMM_TMP3, XMM_TMP4, false /* char */, knoreg); + __ testl(retval, retval); + __ jne_b(L_found); + + // If more potential matches, continue at inner loop, otherwise go get another vector + CLEAR_BIT(mask); + __ jne(L_innerLoop); + __ jmp(L_loopTop); + + // Found exact match. Compute offset from beginning of haystack + __ bind(L_found); + __ subq(hsPtrRet, haystack); + __ addq(hsPtrRet, index); + __ movq(r11, hsPtrRet); + __ jmp(L_returnR11); + +#undef retval +#undef firstNeedleCompare + } + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // Small case default: + // + // Handle needle sizes > 10 bytes. Uses C2's arrays_equals to compare the contents + // of the needle to the haystack. + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // Small case default: register on entry + // + // rbx: haystack + // r14: needle + // r13: k - 1 + // r12: k + // r10: n - k + // rbp: junk + // rdi: junk + // rsi: n + // rdx: junk + // rcx: junk + // XMM_BYTE_0 - first element of needle broadcast + // XMM_BYTE_K - last element of needle broadcast + // + // Set up in broadcast_additional_needles + // XMM_BYTE_1 - second element of needle broadcast + // + // Haystack always copied to stack, so 32-byte reads OK + // Haystack length <= 32 + // 10 < needle length <= 32 + + { + __ bind(L_smallCaseDefault); + + Label L_innerLoop; + + const Register firstNeedleCompare = rdx; + const Register compLen = r9; + const Register haystack = rbx; + const Register mask = r8; + const Register rTmp = rdi; + const Register rTmp2 = r13; + const Register rTmp3 = rax; + +// r14 and r12 will be re-used later in this procedure +#undef needle +#define needle r14 +#undef needleLen +#define needleLen r12 + + broadcast_additional_needles(false, 0 /* unknown */, needle, needleLen, rTmp3, ae, _masm); + + // For small haystacks we already know that the 1st, 2nd, and last bytes of the needle + // compare equal, so we can reduce the byte count to arrays_equals + __ leaq(firstNeedleCompare, Address(needle, isU ? 4 : 2)); + __ leaq(compLen, Address(needleLen, isU ? -6 : -3)); + + // firstNeedleCompare has address of third element of needle + // compLen has length of comparison to do (3 elements less than needle size) + + // Helper to compare the 1st, 2nd, and last byte of the needle to the haystack + // in the correct position. Since the haystack is < 32 bytes, not finding matching + // needle bytes can just return failure. Otherwise, we loop through the found + // matches. + compare_haystack_to_needle(false, 0, L_returnError, haystack, mask, needleLen, rTmp3, XMM_TMP1, + XMM_TMP2, ae, _masm); + +// NOTE: REGISTER RE-USE for r12 and r14 +#undef needle +#undef saveCompLen +#define saveCompLen r14 +#undef needleLen +#undef saveNeedleAddress +#define saveNeedleAddress r12 + + // Save registers stomped by arrays_equals + __ movq(saveCompLen, compLen); + __ movq(saveNeedleAddress, firstNeedleCompare); // Save address of 2nd element of needle + + // Find index of a potential match + __ align(OptoLoopAlignment); + __ bind(L_innerLoop); + __ tzcntl(r11, mask); + + __ leaq(rTmp, Address(haystack, r11, Address::times_1, isU ? 4 : 2)); + + // Check for needle equality. Handles UU and LL cases since byte comparison should be exact + __C2 arrays_equals(false, rTmp, firstNeedleCompare, compLen, rTmp3, rTmp2, XMM_TMP3, XMM_TMP4, + false /* char */, knoreg); + __ testl(rTmp3, rTmp3); + __ jne(L_returnR11); + + // Restore saved registers + __ movq(compLen, saveCompLen); + __ movq(firstNeedleCompare, saveNeedleAddress); + + // Jump to inner loop if more matches to check, otherwise return not found + CLEAR_BIT(mask); + __ jne(L_innerLoop); + __ jmp(L_returnError); + +#undef saveCompLen +#undef saveNeedleAddress + } + + if (isReallyUL) { + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // Wide char code + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // Pseudo-code: + // + // If needle length less than MAX_NEEDLE_LEN_TO_EXPAND, read the needle + // bytes from r14 and write them as words onto the stack. Then go to the + // "regular" UU code. This is equavilent to doing a UU comparison, since the + // haystack will be in UTF-16. + // + // If the needle can't be expanded, process the same way as the default + // cases above. + __ bind(L_wcharBegin); + + // Restore argument encoding from UU back to UL for helpers + ae = StrIntrinsicNode::UL; + isUL = true; + isUU = false; + + Label L_top, L_finished; + + const Register haystack = rdi; + const Register hsLen = rsi; + const Register needle = rdx; + const Register nLen = rcx; + + const Register offset = rax; + const Register index = rbx; + const Register wr_index = r13; + + assert(MAX_NEEDLE_LEN_TO_EXPAND >= 32, "Small UL needles not supported"); + + // haystack length to bytes + __ shlq(hsLen, 1); + + // Ensure haystack >= needle + __ leaq(index, Address(nLen, nLen, Address::times_1)); + __ cmpq(index, hsLen); + __ jg(L_returnError); + + // Can't expand large-ish needles + __ cmpq(nLen, MAX_NEEDLE_LEN_TO_EXPAND); + __ ja(L_wideNoExpand); + + // + // Reads of existing needle are 16-byte chunks + // Writes to copied needle are 32-byte chunks + // Don't read past the end of the existing needle + // + // Start first read at [((ndlLen % 16) - 16) & 0xf] + // outndx += 32 + // inndx += 16 + // cmp nndx, ndlLen + // jae done + // + // Final index of start of needle at ((16 - (ndlLen %16)) & 0xf) << 1 + // + // Starting read for needle at -(16 - (nLen % 16)) + // Offset of needle in stack should be (16 - (nLen % 16)) * 2 + + __ movq(index, needle_len); + __ andq(index, 0xf); // nLen % 16 + __ movq(offset, 0x10); + __ subq(offset, index); // 16 - (nLen % 16) + __ movq(index, offset); + __ shlq(offset, 1); // * 2 + __ negq(index); // -(16 - (nLen % 16)) + __ xorq(wr_index, wr_index); + + __ bind(L_top); + // load needle and expand + __ vpmovzxbw(xmm0, Address(needle, index, Address::times_1), Assembler::AVX_256bit); + // store expanded needle to stack + __ vmovdqu(Address(rsp, wr_index, Address::times_1, EXPANDED_NEEDLE_STACK_OFFSET), xmm0); + __ addq(index, 0x10); + __ cmpq(index, needle_len); + __ jae(L_finished); + __ addq(wr_index, 32); + __ jmpb(L_top); + + // adjust pointer and length of needle + __ bind(L_finished); + __ leaq(needle, Address(rsp, offset, Address::times_1, EXPANDED_NEEDLE_STACK_OFFSET)); + __ leaq(needle_len, Address(needle_len, needle_len)); + + // Go handle this the same as UU + __ jmp(L_continue); + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // + // Compare Latin-1 encoded needle against UTF-16 encoded haystack. + // + // The needle is more than MAX_NEEDLE_LEN_TO_EXPAND bytes in length, and the haystack + // is at least as big. + + // Prepare for wchar anysize + __ bind(L_wideNoExpand); + + { + Label L_loopTop, L_temp, L_innerLoop, L_found, L_compareFull; + Label doCompare, topLoop; + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // On entry: + // + // rbx: haystack + // rcx: k + // rdx: junk + // rsi: n + // rdi: haystack + // r10: n - k + // r12: k + // r13: junk + // r14: needle + // rbp: junk + // XMM_BYTE_0 - first element of needle broadcast + // XMM_BYTE_K - last element of needle broadcast + + const Register hsPtrRet = rax; + const Register haystack = rbx; + const Register haystackStart = rcx; + const Register hsLength = rsi; + const Register tmp1 = rdi; + const Register compLen = rbp; + const Register mask = r8; + const Register index = r9; + const Register needleLen = r12; + const Register rScratch = r13; + const Register needle = r14; + + // Move registers into expected registers for rest of this routine + __ movq(rbx, rdi); + __ movq(r12, rcx); + __ movq(r14, rdx); + + // Set up nMinusK + __ movq(tmp1, needleLen); + __ shlq(tmp1, 1); + __ movq(rScratch, hsLength); + __ subq(rScratch, tmp1); + __ movq(nMinusK, rScratch); + + // Check for room for a 32-byte read for the last iteration + __ cmpq(nMinusK, 0x1f); + __ jl(L_compareFull); + + // Always need needle broadcast to ymm registers + broadcast_first_and_last_needle(needle, needleLen, tmp1, ae, _masm); + +// Register redefinition for rbx and r15 +#undef retval +#undef firstNeedleCompare +#undef tmp2 +#undef tmp3 +#define tmp2 r15 +#define tmp3 rdx + + // Loop construct handling for big haystacks + // The helper binds L_loopTop which should be jumped to if potential matches fail to compare + // equal (thus moving on to the next chunk of haystack). If we run out of haystack, the + // helper jumps to L_returnError. + big_case_loop_helper(false, 0, L_returnError, L_loopTop, mask, hsPtrRet, needleLen, needle, + haystack, hsLength, tmp1, tmp2, tmp3, rScratch, ae, _masm); + + // big_case_loop_helper will fall through to this point if one or more potential matches are + // found The mask will have a bitmask indicating the position of the potential matches within + // the haystack + __ align(OptoLoopAlignment); + __ bind(L_innerLoop); + __ tzcntl(index, mask); + +#undef tmp2 +#undef tmp3 +#define retval r15 +#define firstNeedleCompare rdx + + // Note that we're comparing the full needle here even though in some paths + // the 1st, 2nd, and last bytes are already known to be equal. This is necessary + // due to the handling of cases where nMinusK is < 32 + + // Need a lot of registers here to preserve state across arrays_equals call + + // Starting address in the haystack + __ leaq(haystackStart, Address(hsPtrRet, index)); + // Starting address of first byte of needle to compare + __ movq(firstNeedleCompare, needle); + // Number of bytes to compare + __ movq(compLen, needleLen); + + // Passing true as last parameter causes arrays_equals to expand the second array (needle) + // as the comparison is done. + __C2 arrays_equals(false, haystackStart, firstNeedleCompare, compLen, retval, rScratch, + XMM_TMP3, XMM_TMP4, false /* char */, knoreg, true /* expand_ary2 */); + __ testl(retval, retval); + __ jne_b(L_found); + + // If more potential matches, continue at inner loop, otherwise go get another vector + CLEAR_BIT(mask); + __ jne(L_innerLoop); + __ jmp(L_loopTop); + + // Found exact match. Compute offset from beginning of haystack + __ bind(L_found); + __ subq(hsPtrRet, haystack); + __ addq(hsPtrRet, index); + __ movq(r11, hsPtrRet); + __ jmp(L_returnR11); + +#undef retval +#undef firstNeedleCompare + + __ bind(L_compareFull); + + // rScratch has n - k. Compare entire string word-by-word + // Index returned in r11 + __ xorq(r11, r11); + __ movq(nMinusK, rScratch); + __ jmpb(doCompare); + + __ bind(topLoop); + __ addq(r11, 2); + __ cmpq(r11, nMinusK); + __ jg(L_returnError); + + __ bind(doCompare); + __ leaq(r9, Address(haystack, r11)); + __ leaq(r8, Address(needle, 0)); + __ movq(r13, needleLen); + + __C2 arrays_equals(false, r9, r8, r13, rax, rdx, XMM_TMP3, XMM_TMP4, false /* char */, knoreg, + true /* expand_ary2 */); + __ testq(rax, rax); + __ jz(topLoop); + + // Match found + __ jmp(L_returnR11); + } + } + + return; +} + +// Helper for broadcasting needle elements to ymm registers for compares +// Expands into XMM_BYTE_0 and XMM_BYTE_K +// +// For UTF-16 encoded needles, broadcast a word at the proper offset to the ymm +// register (case UU) +// For the UTF-16 encoded haystack with Latin1 encoded needle (case UL) we have +// to read into a temp register to zero-extend the single byte needle value, then +// broadcast words to the ymm register. +// +// Parameters: +// needle - the address of the first byte of the needle +// needle_len - length of needle if !sizeKnown +// rTmp - temp register (for UL only) +// ae - the argument encodings +// _masm - Current MacroAssembler instance pointer +// +// Modifies XMM_BYTE_0 and XMM_BYTE_K +static void broadcast_first_and_last_needle(Register needle, Register needle_len, Register rTmp, + StrIntrinsicNode::ArgEncoding ae, + MacroAssembler *_masm) { + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = (isUU || isUL); + Label L_short; + + // Always need needle broadcast to ymm registers + // Broadcast the beginning of needle into a vector register. + if (isUU) { + __ vpbroadcastw(XMM_BYTE_0, Address(needle, 0), Assembler::AVX_256bit); + } else if (isUL) { + + __ movzbl(rTmp, Address(needle)); + __ movdl(XMM_BYTE_0, rTmp); + // 1st byte of needle in words + __ vpbroadcastw(XMM_BYTE_0, XMM_BYTE_0, Assembler::AVX_256bit); + } else { + __ vpbroadcastb(XMM_BYTE_0, Address(needle, 0), Assembler::AVX_256bit); + } + + // Broadcast the end of needle into a vector register. + // For a single-element needle this is redundant but does no harm and + // reduces code size as opposed to broadcasting only if used. + if (isUU) { + __ vpbroadcastw(XMM_BYTE_K, Address(needle, needle_len, Address::times_1, -2), + Assembler::AVX_256bit); + } else if (isUL) { + __ movzbl(rTmp, Address(needle, needle_len, Address::times_1, -1)); + __ movdl(XMM_BYTE_K, rTmp); + // last byte of needle in words + __ vpbroadcastw(XMM_BYTE_K, XMM_BYTE_K, Assembler::AVX_256bit); + } else { + __ vpbroadcastb(XMM_BYTE_K, Address(needle, needle_len, Address::times_1, -1), + Assembler::AVX_256bit); + } + + __ bind(L_short); +} + +// Helper for broadcasting the 2nd needle element to XMM_BYTE_1 +// +// For UTF-16 encoded needles, broadcast a word at the proper offset to the ymm +// register (case UU) +// For the UTF-16 encoded haystack with Latin1 encoded needle (case UL) we have +// to read into a temp register to zero-extend the single byte needle value, then +// broadcast words to the ymm register. +// +// Parameters: +// sizeKnown - True if needle size known at compile time +// size - the size of the needle. Pass 0 if unknown at compile time +// needle - the address of the first byte of the needle +// needleLen - length of needle if !sizeKnown +// rTmp - temp register (for UL only) +// ae - Argument encoding +// _masm - Current MacroAssembler instance pointer +// +// Modifies XMM_BYTE_1 +static void broadcast_additional_needles(bool sizeKnown, int size, Register needle, + Register needleLen, Register rTmp, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm) { + Label L_done; + + assert_different_registers(needle, needleLen, rTmp); + + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = (isUU || isUL); + + size = sizeKnown ? size : NUMBER_OF_CASES + 1; + + // Need code to determine whether it's valid to use second byte of + // needle if the size isn't known at compile-time + if (!sizeKnown) { + __ cmpq(needleLen, (isU ? 4 : 2)); + __ jl_b(L_done); + } + + if (size > (isU ? 4 : 2)) { + // Add compare for second byte + if (isUU) { + __ vpbroadcastw(XMM_BYTE_1, Address(needle, 2), Assembler::AVX_256bit); + } else if (isUL) { + __ movzbl(rTmp, Address(needle, 1)); + __ movdl(XMM_BYTE_1, rTmp); + // 1st byte of needle in words + __ vpbroadcastw(XMM_BYTE_1, XMM_BYTE_1, Assembler::AVX_256bit); + } else { + __ vpbroadcastb(XMM_BYTE_1, Address(needle, 1), Assembler::AVX_256bit); + } + } + + __ bind(L_done); +} + +// Helper for comparing needle elements to a big haystack +// +// This helper compares bytes or words in the ymm registers to +// the proper positions within the haystack. It will bail out early if +// no match found, otherwise it will progressively and together +// the comparison results, returning the answer at the end. +// +// On return, eq_mask will be set to the comparison mask value. If no match +// is found, this helper will jump to noMatch. +// +// Parameters: +// sizeKnown - True if size known at compile time +// size - the size of the needle in bytes. Pass 0 if unknown at compile time +// noMatch - label bound outside to jump to if there is no match +// haystack - the address of the first byte of the haystack +// hsLen - the sizeof the haystack in bytes +// needleLen - size of the needle in bytes known at runtime +// eq_mask - The bit mask returned that holds the result of the comparison +// rxTmp1 - a temporary xmm register +// rxTmp2 - a temporary xmm register +// rxTmp3 - a temporary xmm register +// ae - Argument encoding +// _masm - Current MacroAssembler instance pointer +// +// (n - k) will always be >= 32 on entry +static void compare_big_haystack_to_needle(bool sizeKnown, int size, Label &noMatch, + Register haystack, Register needleLen, Register eq_mask, + XMMRegister rxTmp1, XMMRegister rxTmp2, + XMMRegister rxTmp3, StrIntrinsicNode::ArgEncoding ae, + MacroAssembler *_masm) { + + assert_different_registers(eq_mask, haystack, needleLen, nMinusK); + + const XMMRegister result = rxTmp1; + const XMMRegister cmp_0 = rxTmp2; + const XMMRegister cmp_k = rxTmp3; + + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = (isUU || isUL); + + int sizeIncr = isU ? 2 : 1; + + Label L_OKtoCompareFull, L_done, L_specialCase_gt2; + + assert(!sizeKnown || (sizeKnown && ((size > 0) && (size <= NUMBER_OF_CASES))), "Incorrect size given"); + + // Address of the kth byte of the needle within the haystack + Address kThByte = sizeKnown ? Address(haystack, size - sizeIncr) + : Address(haystack, needleLen, + isUL ? Address::times_2 : Address::times_1, -(sizeIncr)); + size = sizeKnown ? size : NUMBER_OF_CASES + 1; + + // Compare first byte of needle to haystack + vpcmpeq(cmp_0, XMM_BYTE_0, Address(haystack, 0), Assembler::AVX_256bit, ae, _masm); + + __ vpmovmskb(eq_mask, cmp_0, Assembler::AVX_256bit); + + // If the needle is a single element (at compile time) no need to compare more + if (size != sizeIncr) { + // Compare last byte of needle to haystack at proper position + vpcmpeq(cmp_k, XMM_BYTE_K, kThByte, Assembler::AVX_256bit, ae, _masm); + + __ vpand(result, cmp_k, cmp_0, Assembler::AVX_256bit); + + if (size > sizeIncr * 2) { + vpcmpeq(cmp_k, XMM_BYTE_1, Address(haystack, 1 * sizeIncr), Assembler::AVX_256bit, ae, _masm); + __ vpand(result, cmp_k, result, Assembler::AVX_256bit); + } + + __ vpmovmskb(eq_mask, result, Assembler::AVX_256bit); + } + + __ bind(L_done); + __ testl(eq_mask, eq_mask); + __ je(noMatch); + // At this point, we have at least one "match" where first and last bytes + // of the needle are found the correct distance apart. +} + +// Helper for comparing needle elements to a small haystack +// +// This helper compares bytes or words in the ymm registers to +// the proper positions within the haystack. It will bail out early if +// a match is not found, otherwise it will progressively and together +// the comparison results, returning the answer at the end. +// +// On return, eq_mask will be set to the comparison mask value. If no match +// is found, this helper will jump to noMatch. +// +// Parameters: +// sizeKnown - if true, size is valid and needleLen invalid. +// if false, size invalid and needleLen valid. +// size - the size of the needle. Pass 0 if unknown at compile time +// noMatch - label bound outside to jump to if there is no match +// haystack - the address of the first byte of the haystack +// eq_mask - The bit mask returned that holds the result of the comparison +// needleLen - Length of the needle in bytes. Only used if isUL true +// rTmp - temporary register +// rxTmp1 - temporary xmm register +// rxTmp2 - temporary xmm register +// ae - Argument encoding +// _masm - Current MacroAssembler instance pointer +// +// No need to worry about reading past end of haystack since haystack +// has been copied to the stack +// +// If !sizeKnown, needle is at least 11 bytes long +static void compare_haystack_to_needle(bool sizeKnown, int size, Label &noMatch, Register haystack, + Register eq_mask, Register needleLen, Register rTmp, + XMMRegister rxTmp1, XMMRegister rxTmp2, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm) { + + assert_different_registers(eq_mask, haystack, needleLen, rTmp, nMinusK); + + // NOTE: cmp_0 and result are the same register + const XMMRegister cmp_0 = rxTmp1; + const XMMRegister result = rxTmp1; + const XMMRegister cmp_k = rxTmp2; + + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = isUL || isUU; // At least one is UTF-16 + + int sizeIncr = isU ? 2 : 1; + + assert((!sizeKnown) || (((size > 0) && (size <= NUMBER_OF_CASES))), "Incorrect size given"); + + // Address of the kth byte of the needle within the haystack + Address kThByte = sizeKnown ? Address(haystack, size - sizeIncr) + : Address(haystack, needleLen, Address::times_1, -(sizeIncr)); + size = sizeKnown ? size : NUMBER_OF_CASES + 1; + + // Creates a mask of (n - k + 1) ones. This prevents + // recognizing any false-positives past the end of + // the valid haystack. + __ movq(rTmp, -1); + __ movq(eq_mask, nMinusK); + __ addq(eq_mask, 1); + __ bzhiq(rTmp, rTmp, eq_mask); + + // Compare first byte of needle to haystack + vpcmpeq(cmp_0, XMM_BYTE_0, Address(haystack, 0), Assembler::AVX_256bit, ae, _masm); + if (size != sizeIncr) { + // Compare last byte of needle to haystack at proper position + vpcmpeq(cmp_k, XMM_BYTE_K, kThByte, Assembler::AVX_256bit, ae, _masm); + + __ vpand(result, cmp_k, cmp_0, Assembler::AVX_256bit); + + if (size > (sizeIncr * 2)) { + vpcmpeq(cmp_k, XMM_BYTE_1, Address(haystack, 1 * sizeIncr), Assembler::AVX_256bit, ae, _masm); + __ vpand(result, cmp_k, result, Assembler::AVX_256bit); + } + } + + __ vpmovmskb(eq_mask, result, Assembler::AVX_256bit); + __ andl(eq_mask, rTmp); + + __ testl(eq_mask, eq_mask); + __ je(noMatch); + // At this point, we have at least one "match" where first and last bytes + // of the needle are found the correct distance apart. +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +// Helper for big haystack loop construct +// +// For UTF-16 encoded needles, broadcast a word at the proper offset to the ymm +// register (case UU) +// For the UTF-16 encoded haystack with Latin1 encoded needle (case UL) we have +// to read into a temp register to zero-extend the single byte needle value, then +// broadcast words to the ymm register. +// +// Parameters: +// sizeKnown - if true, size is valid and needleLen invalid. +// size - the size of the needle. Pass 0 if unknown at compile time +// noMatch - label bound outside to jump to if there is no match +// loop_top - label bound inside this helper that should be branched to +// for additional comparisons. +// eq_mask - The bit mask returned that holds the result of the comparison +// hsPtrRet - This will hold the place within the needle where a match is found +// This is modified +// needleLen - The length of the needle +// needle - Address of the needle +// haystack - Address of the haystack +// hsLength - The length of the haystack +// rTmp1 - Temporary +// rTmp2 - Temporary +// rTmp3 - Temporary +// rTmp4 - Temporary +// ae - Argument encoding +// _masm - Current MacroAssembler instance pointer +// +// On entry: +// +// rbx: haystack +// rcx: k +// rdx: junk +// rsi: n +// rdi: haystack +// r10: n - k +// r12: k +// r13: junk +// r14: needle +// rbp: junk +// XMM_BYTE_0 - first element of needle broadcast +// XMM_BYTE_K - last element of needle broadcast + +static void big_case_loop_helper(bool sizeKnown, int size, Label &noMatch, Label &loop_top, + Register eq_mask, Register hsPtrRet, Register needleLen, + Register needle, Register haystack, Register hsLength, + Register rTmp1, Register rTmp2, Register rTmp3, Register rTmp4, + StrIntrinsicNode::ArgEncoding ae, MacroAssembler *_masm) { + Label L_midLoop, L_greaterThan32, L_out; + + assert_different_registers(eq_mask, hsPtrRet, needleLen, rdi, r15, rdx, rsi, rbx, r14, nMinusK); + + const Register last = rTmp1; + const Register temp1 = rTmp2; + const Register temp2 = rTmp3; + const Register temp3 = rTmp4; + + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = isUL || isUU; // At least one is UTF-16 + + // Assume failure + __ movq(r11, -1); + + broadcast_additional_needles(sizeKnown, size, needle, needleLen, temp1, ae, _masm); + + __ cmpq(nMinusK, 31); + __ jae_b(L_greaterThan32); + + // Here the needle is too long, so we can't do a 32-byte read to compare the last element. + // + // Instead we match the first two characters, read from the end of the haystack + // back 32 characters, shift the result, compare and check that way. + // + // Set last to hsPtrRet so the next attempt at loop iteration ends the compare. + __ movq(last, haystack); + __ movq(hsPtrRet, haystack); + + // Compare first element of needle to haystack + vpcmpeq(XMM_TMP3, XMM_BYTE_0, Address(haystack, 0), Assembler::AVX_256bit, ae, _masm); + + __ vpmovmskb(eq_mask, XMM_TMP3, Assembler::AVX_256bit); + + if (!sizeKnown || (sizeKnown && (size > (isU ? 4 : 2)))) { + // Compare second element of needle to haystack and mask result + vpcmpeq(XMM_TMP3, XMM_BYTE_1, Address(haystack, isU ? 2 : 1), Assembler::AVX_256bit, ae, _masm); + + __ vpmovmskb(temp1, XMM_TMP3, Assembler::AVX_256bit); + __ andq(eq_mask, temp1); + } + + // Compare last element of needle to haystack, shift and mask result + vpcmpeq(XMM_TMP3, XMM_BYTE_K, Address(haystack, hsLength, Address::times_1, -32), + Assembler::AVX_256bit, ae, _masm); + + __ vpmovmskb(temp1, XMM_TMP3, Assembler::AVX_256bit); + + // Compute the proper shift value. If we let k be the needle length and n be the haystack + // length, we should be comparing to haystack[k - 1] through haystack[k - 1 + 31]. Since + // (n - k) < 32, (k - 1 + 31) would be past the end of the haystack. So the shift value + // is computed as (k + 31 - n). + // + // Clarification: The BYTE_K compare above compares haystack[(n-32):(n-1)]. We need to + // compare haystack[(k-1):(k-1+31)]. Subtracting either index gives shift value of + // (k + 31 - n): x = (k-1+31)-(n-1) = k-1+31-n+1 = k+31-n. + if (sizeKnown) { + __ movl(temp2, 31 + size); + } else { + __ movl(temp2, 31); + __ addl(temp2, needleLen); + } + __ subl(temp2, hsLength); + __ shrxl(temp1, temp1, temp2); + __ andl(eq_mask, temp1); + + __ testl(eq_mask, eq_mask); + __ je(noMatch); + + __ jmp(L_out); + + __ bind(L_greaterThan32); + + // Read 32-byte chunks at a time until the last 32-byte read would go + // past the end of the haystack. Then, set the final read to read exactly + // the number of bytes in the haystack. + // For example, if haystack length is 45 and needle length is 13, the compares + // will read the following bytes: + // + // First compare Last compare + // [ 0 : 31] [12 : 43] + // Next compare will go past end of haystack ([32:63]) + // Adjust so final read is: + // [ 1 : 32] [13 : 44] + + __ movq(hsPtrRet, haystack); + __ leaq(last, Address(haystack, nMinusK, Address::times_1, isU ? -30 : -31)); + __ jmpb(L_midLoop); + + __ align(OptoLoopAlignment); + __ bind(loop_top); + // An equal comparison indicates completion with no match + __ cmpq(hsPtrRet, last); + __ je(noMatch); + __ addq(hsPtrRet, 32); + + // If next compare will go beyond end of haystack adjust start of read + // back to last valid read position + __ cmpq(hsPtrRet, last); + __ jbe_b(L_midLoop); + __ movq(hsPtrRet, last); + + __ bind(L_midLoop); + + // compare_big_haystack_to_needle will jump to loop_top until a match has been + // found + compare_big_haystack_to_needle(sizeKnown, size, loop_top, hsPtrRet, needleLen, eq_mask, XMM_TMP1, + XMM_TMP2, XMM_TMP3, ae, _masm); + + // At this point, we have at least one "match" where first and last bytes + // of the needle are found the correct distance apart. + // + // NOTE: haystack (rbx) should be preserved; hsPtrRet(rcx) is expected to + // point to the haystack such that hsPtrRet[tzcntl(eq_mask)] points to + // the matched string. + + __ bind(L_out); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +// Helper for comparing small needles to the haystack after a potential match found. +// +// Parameters: +// size - The size of the needle in bytes +// L_noMatch - Label to jump to if needle does not match haystack at this location +// L_matchFound - Label to jump to if needle matches haystack at this location +// needle - the address of the first byte of the needle +// needleVal - The bytes of the needle to compare +// haystack - The address of the first byte of the haystack +// mask - The comparison mask from comparing the first 2 and last elements of the needle +// foundIndex - The index within the haystack of the match +// tmp - A temporary register +// ae - the argument encodings +// _masm - Current MacroAssembler instance pointer +// +// Branches to either L_noMatch or L_matchFound depending on the result of the comparison +// foundIndex will contain the index within the haystack of the match for L_matchFound + +static void byte_compare_helper(int size, Label &L_noMatch, Label &L_matchFound, Register needle, + Register needleVal, Register haystack, Register mask, + Register foundIndex, Register tmp, StrIntrinsicNode::ArgEncoding ae, + MacroAssembler *_masm) { + // Compare size bytes of needle to haystack + // + // At a minimum, the first, second and last bytes of needle already compare equal + // to the haystack, so there is no need to compare them again. + + Label L_loopTop; + + assert_different_registers(needle, needleVal, haystack, mask, foundIndex, tmp); + + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = isUL || isUU; // At least one is UTF-16 + + int bytesAlreadyCompared = 0; + int bytesLeftToCompare = 0; + int offsetOfFirstByteToCompare = 0; + + Label temp; + + // Getting her we already have the first two and last elements of the needle + // comparing equal, so no need to compare them again + bytesAlreadyCompared = isU ? 6 : 3; + offsetOfFirstByteToCompare = isU ? 4 : 2; + + bytesLeftToCompare = size - bytesAlreadyCompared; + assert(bytesLeftToCompare <= 7, "Too many bytes left to compare"); + + // The needle is <= 3 elements long, so the ultimate result comes from the mask + if (bytesLeftToCompare <= 0) { + __ tzcntl(foundIndex, mask); + __ jmp(L_matchFound); + return; + } + + // At this point, there is at least one byte of the needle that needs to be + // compared to the haystack. + + // Pre-load the needle bytes to compare here + switch (bytesLeftToCompare) { + case 1: + case 2: + // Load for needle size of 4 and 5 bytes + __ movl(needleVal, Address(needle, (offsetOfFirstByteToCompare - 2))); + break; + + case 3: + case 4: + // Load for needle size of 6 and 7 bytes + __ movl(needleVal, Address(needle, offsetOfFirstByteToCompare)); + break; + + case 5: + case 6: + // Load for needle size of 8 and 9 bytes + __ movq(needleVal, Address(needle, (offsetOfFirstByteToCompare - 2))); + break; + + case 7: + // Load for needle size of 10 bytes + __ movq(needleVal, Address(needle, offsetOfFirstByteToCompare)); + break; + + default: + break; + } + + __ align(OptoLoopAlignment); + __ bind(L_loopTop); + __ tzcntl(foundIndex, mask); // Index of match within haystack + + switch (bytesLeftToCompare) { + case 1: + case 2: + // Comparison for needle size of 4 and 5 bytes + __ cmpl(Address(haystack, foundIndex, Address::times_1, offsetOfFirstByteToCompare - 2), + needleVal); + __ je(L_matchFound); + break; + + case 3: + case 4: + // Comparison for needle size of 6 and 7 bytes + __ cmpl(Address(haystack, foundIndex, Address::times_1, offsetOfFirstByteToCompare), needleVal); + __ je(L_matchFound); + break; + + case 5: + case 6: + // Comparison for needle size of 8 and 9 bytes + __ cmpq(Address(haystack, foundIndex, Address::times_1, offsetOfFirstByteToCompare - 2), + needleVal); + __ je(L_matchFound); + break; + + case 7: + // Comparison for needle size of 10 bytes + __ cmpq(Address(haystack, foundIndex, Address::times_1, offsetOfFirstByteToCompare), needleVal); + __ je(L_matchFound); + break; + + default: + break; + } + + CLEAR_BIT(mask); // Loop as long as there are other bits set + __ jne(L_loopTop); + __ jmp(L_noMatch); +} + +// highly_optimized_short_cases +// We can handle the cases where haystack size is <= 32 bytes and needle size <= 6 bytes +// as a special case. We first copy the haystack tpo the stack to avoid page faults. A mask is +// generated with (n - k + 1) bits set that ensures matches past the end of the original +// haystack do not get considered during compares. In this equation, n is length of haystack +// and k is length of needle. +// +// A vector compare for the first needle byte is done against the haystack and anded with the mask. +// For needle size == 1, if there's a match we found it, otherwise failure. The 2nd position +// of the needle is compared starting from the 2nd position of the haystack and anded with the +// mask. If needle size == 2 and a match is found, success else failure. This continues for +// all needle sizes up to 6 bytes. +// +// ae - Argument encoding +// haystack - The address of the haystack +// haystack_len - the length of the haystack in elements +// needle - The address of the needle +// needle_len - the length of the needle in elements +// XMM0 - Temporary xmm register +// XMM1 - Temporary xmm register +// mask - Used to hold comparison mask +// tmp - Temporary register +// _masm - Current MacroAssembler instance pointer +static void highly_optimized_short_cases(StrIntrinsicNode::ArgEncoding ae, Register haystack, + Register haystack_len, Register needle, + Register needle_len, XMMRegister XMM0, XMMRegister XMM1, + Register mask, Register tmp, MacroAssembler *_masm) { + // Highly optimized special-cases + Label L_noMatch, L_foundall, L_out; + + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = isUL || isUU; // At least one is UTF-16 + + // Only optimize when haystack can fit on stack with room + // left over for page fault prevention + assert((COPIED_HAYSTACK_STACK_OFFSET == 0), "Must be zero!"); + assert((COPIED_HAYSTACK_STACK_SIZE == 64), "Must be 64!"); + + // Copy incoming haystack onto stack + { + Label L_adjustHaystack, L_moreThan16; + + // Copy haystack to stack (haystack <= 32 bytes) + __ subptr(rsp, COPIED_HAYSTACK_STACK_SIZE); + __ cmpq(haystack_len, isU ? 0x8 : 0x10); + __ ja_b(L_moreThan16); + + __ movq(tmp, COPIED_HAYSTACK_STACK_OFFSET + 0x10); + __ movdqu(XMM0, Address(haystack, haystack_len, isU ? Address::times_2 : Address::times_1, -0x10)); + __ movdqu(Address(rsp, COPIED_HAYSTACK_STACK_OFFSET), XMM0); + __ jmpb(L_adjustHaystack); + + __ bind(L_moreThan16); + __ movq(tmp, COPIED_HAYSTACK_STACK_OFFSET + 0x20); + __ vmovdqu(XMM0, Address(haystack, haystack_len, isU ? Address::times_2 : Address::times_1, -0x20)); + __ vmovdqu(Address(rsp, COPIED_HAYSTACK_STACK_OFFSET), XMM0); + + __ bind(L_adjustHaystack); + __ subptr(tmp, haystack_len); + + if (isU) { + // For UTF-16, lengths are half + __ subptr(tmp, haystack_len); + } + // Point the haystack to the stack + __ leaq(haystack, Address(rsp, tmp, Address::times_1)); + } + + // Creates a mask of (n - k + 1) ones. This prevents recognizing any false-positives + // past the end of the valid haystack. + __ movq(mask, -1); + __ subq(haystack_len, needle_len); + __ incrementq(haystack_len); + if (isU) { + __ shlq(haystack_len, 1); + } + __ bzhiq(mask, mask, haystack_len); + + // Loop for each needle size from 1 to 6 bytes long. For UU, only 3 elements. + for (int size = 1; size <= (isUU ? 3 : 6); size++) { + // Broadcast next needle byte into ymm register + int needle_position = isUU ? (size - 1) * 2 : size - 1; + int haystack_position = isU ? (size - 1) * 2 : size - 1; + if (isUU) { + __ vpbroadcastw(XMM0, Address(needle, needle_position), Assembler::AVX_256bit); + } else if (isUL) { + // Expand needle + __ movzbl(tmp, Address(needle, needle_position)); + __ movdl(XMM0, tmp); + // Byte of needle to words + __ vpbroadcastw(XMM0, XMM0, Assembler::AVX_256bit); + } else { + __ vpbroadcastb(XMM0, Address(needle, needle_position), Assembler::AVX_256bit); + } + + // Compare next byte. Keep the comparison mask in mask, which will + // accumulate + vpcmpeq(XMM1, XMM0, Address(haystack, haystack_position), Assembler::AVX_256bit, ae, _masm); + __ vpmovmskb(tmp, XMM1, Assembler::AVX_256bit); + __ andq(mask, tmp); // Accumulate matched bytes + __ testl(mask, mask); + __ je(L_noMatch); + + if (size != (isUU ? 3 : 6)) { + // Found a match for this needle size + __ cmpq(needle_len, size); + __ je(L_foundall); + } + } + + __ bind(L_foundall); + __ tzcntl(rax, mask); + + if (isU) { + __ shrl(rax, 1); + } + + __ bind(L_out); + __ addptr(rsp, COPIED_HAYSTACK_STACK_SIZE); + __ vzeroupper(); + __ leave(); + __ ret(0); + + __ bind(L_noMatch); + __ movq(rax, -1); + __ jmpb(L_out); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +// +// Set up jump table entries for both small and large haystack switches. +// +// ae - Argument encoding +// L_error - Label to branch to if no match found +// L_checkRange - label to jump to when match found. Checks validity of returned index +// L_fixup - Jump to here for big cases. Return value is pointer to matching haystack byte +// *big_jump_table - Address of pointer to the first element of big jump table +// *small_jump_table - Address of pointer to the first element of small jump table +// _masm - Current MacroAssembler instance pointer + +static void setup_jump_tables(StrIntrinsicNode::ArgEncoding ae, Label &L_error, Label &L_checkRange, + Label &L_fixup, address *big_jump_table, address *small_jump_table, + MacroAssembler *_masm) { + bool isUL = (ae == StrIntrinsicNode::UL); + bool isUU = (ae == StrIntrinsicNode::UU); + bool isU = isUL || isUU; // At least one is UTF-16 + const XMMRegister byte_1 = XMM_BYTE_1; + + address big_hs_jmp_table[NUMBER_OF_CASES]; // Jump table for large haystacks + address small_hs_jmp_table[NUMBER_OF_CASES]; // Jump table for small haystacks + int jmp_ndx = 0; + + //////////////////////////////////////////////// + // On entry to each case, the register state is: + // + // rax = unused + // rbx = &haystack + // rcx = haystack length + // rdx = &needle + // rsi = haystack length + // rdi = &haystack + // rbp = unused + // r8 = unused + // r9 = unused + // r10 = hs_len - needle len + // r11 = unused + // r12 = needle length + // r13 = (needle length - 1) + // r14 = &needle + // r15 = unused + // XMM_BYTE_0 - first element of needle, broadcast + // XMM_BYTE_K - last element of needle, broadcast + + { + //////////////////////////////////////////////////////////////////////////////////////// + // + // Small haystack (<=32 bytes) switch + // + // Handle cases that were not handled in highly_optimized_short_cases, which will be + // haystack size <= 32 bytes with 6 < needle size < NUMBER_OF_CASES bytes. + + //////////////////////////////////////////////// + // The haystack is <= 32 bytes + // + // If a match is not found, branch to L_error (which will always + // return -1). + // + // If a match is found, jump to L_checkRange, which ensures the + // matched needle is not past the end of the haystack. + // + // The index where a match is found is returned in set_bit (r11). + + const Register haystack = rbx; + const Register needle = r14; + const Register needle_val = r8; + const Register set_bit = r11; + const Register eq_mask = rsi; + const Register rTmp = rax; + + for (int i = 6; i < NUMBER_OF_CASES; i++) { + small_hs_jmp_table[i] = __ pc(); + if (isU && ((i + 1) & 1)) { + continue; + } else { + broadcast_additional_needles(true, i + 1, needle, noreg, rTmp, ae, _masm); + + compare_haystack_to_needle(true, i + 1, L_error, haystack, eq_mask, noreg, rTmp, XMM_TMP1, + XMM_TMP2, ae, _masm); + + byte_compare_helper(i + 1, L_error, L_checkRange, needle, needle_val, haystack, eq_mask, + set_bit, rTmp, ae, _masm); + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////// + // + // Large haystack (> 32 bytes) switch + + { + //////////////////////////////////////////////// + // The haystack is > 32 bytes + // + // The value returned on a match is in hs_ptr (rcx) which is the address + // of the first matching byte within the haystack. The L_fixup label + // takes hs_ptr (rcx), haystack (rbx), and set_bit (r8) to compute the + // index as: hs_ptr - haystack + r8. hs_ptr - haystack is the offset + // within the haystack of the 32-byte chunk wherein a match was found, + // and set_bit is the index within that 32-byte chunk of the matching string. + + const Register haystack = rbx; + const Register needle = r14; + const Register needle_len = r12; + const Register needle_val = r15; + const Register set_bit = r8; + const Register eq_mask = r9; + const Register hs_ptr = rcx; + const Register hsLength = rsi; + const Register rTmp1 = rdi; + const Register rTmp2 = r15; + const Register rTmp3 = rdx; + const Register rTmp4 = r13; + + for (int i = 0; i < NUMBER_OF_CASES; i++) { + big_hs_jmp_table[i] = __ pc(); + if (isU && ((i + 1) & 1)) { + continue; + } else { + Label L_loopTop; + + big_case_loop_helper(true, i + 1, L_error, L_loopTop, eq_mask, hs_ptr, needle_len, + needle, haystack, hsLength, rTmp1, rTmp2, rTmp3, rTmp4, ae, _masm); + byte_compare_helper(i + 1, L_loopTop, L_fixup, needle, needle_val, hs_ptr, eq_mask, set_bit, + rTmp4, ae, _masm); + } + } + } + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + // JUMP TABLES + __ align(8); + + *big_jump_table = __ pc(); + + for (jmp_ndx = 0; jmp_ndx < NUMBER_OF_CASES; jmp_ndx++) { + __ emit_address(big_hs_jmp_table[jmp_ndx]); + } + + *small_jump_table = __ pc(); + + for (jmp_ndx = 0; jmp_ndx < NUMBER_OF_CASES; jmp_ndx++) { + __ emit_address(small_hs_jmp_table[jmp_ndx]); + } +} + +#undef STACK_SPACE +#undef MAX_NEEDLE_LEN_TO_EXPAND +#undef CLEAR_BIT +#undef XMM_BYTE_0 +#undef XMM_BYTE_K +#undef XMM_BYTE_1 +#undef XMM_TMP1 +#undef XMM_TMP2 +#undef XMM_TMP3 +#undef XMM_TMP4 + +#undef __ diff --git a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp index 2e82453b380..12ac26aff21 100644 --- a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp +++ b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,11 +52,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE #endif -#if defined(COMPILER2) -// Include Restricted Transactional Memory lock eliding optimization -#define INCLUDE_RTM_OPT 1 -#endif - #if defined(LINUX) || defined(__APPLE__) #define SUPPORT_RESERVED_STACK_AREA #endif diff --git a/src/hotspot/cpu/x86/globals_x86.hpp b/src/hotspot/cpu/x86/globals_x86.hpp index d73a8d03171..03fd26195c0 100644 --- a/src/hotspot/cpu/x86/globals_x86.hpp +++ b/src/hotspot/cpu/x86/globals_x86.hpp @@ -115,6 +115,10 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); "Highest supported AVX instructions set on x86/x64") \ range(0, 3) \ \ + \ + product(bool, UseAPX, false, EXPERIMENTAL, \ + "Use Intel Advanced Performance Extensions") \ + \ product(bool, UseKNLSetting, false, DIAGNOSTIC, \ "Control whether Knights platform setting should be used") \ \ @@ -151,51 +155,6 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseFastStosb, false, \ "Use fast-string operation for zeroing: rep stosb") \ \ - /* Use Restricted Transactional Memory for lock eliding */ \ - product(bool, UseRTMLocking, false, \ - "(Deprecated) Enable RTM lock eliding for inflated locks " \ - "in compiled code") \ - \ - product(bool, UseRTMForStackLocks, false, EXPERIMENTAL, \ - "Enable RTM lock eliding for stack locks in compiled code") \ - \ - product(bool, UseRTMDeopt, false, \ - "(Deprecated) Perform deopt and recompilation based on " \ - "RTM abort ratio") \ - \ - product(int, RTMRetryCount, 5, \ - "(Deprecated) Number of RTM retries on lock abort or busy") \ - range(0, max_jint) \ - \ - product(int, RTMSpinLoopCount, 100, EXPERIMENTAL, \ - "Spin count for lock to become free before RTM retry") \ - range(0, max_jint) \ - \ - product(int, RTMAbortThreshold, 1000, EXPERIMENTAL, \ - "Calculate abort ratio after this number of aborts") \ - range(0, max_jint) \ - \ - product(int, RTMLockingThreshold, 10000, EXPERIMENTAL, \ - "Lock count at which to do RTM lock eliding without " \ - "abort ratio calculation") \ - range(0, max_jint) \ - \ - product(int, RTMAbortRatio, 50, EXPERIMENTAL, \ - "Lock abort ratio at which to stop use RTM lock eliding") \ - range(0, 100) /* natural range */ \ - \ - product(int, RTMTotalCountIncrRate, 64, EXPERIMENTAL, \ - "Increment total RTM attempted lock count once every n times") \ - range(1, max_jint) \ - constraint(RTMTotalCountIncrRateConstraintFunc,AfterErgo) \ - \ - product(intx, RTMLockingCalculationDelay, 0, EXPERIMENTAL, \ - "Number of milliseconds to wait before start calculating aborts " \ - "for RTM locking") \ - \ - product(bool, UseRTMXendForLockBusy, true, EXPERIMENTAL, \ - "Use RTM Xend instead of Xabort when lock busy") \ - \ /* assembler */ \ product(bool, UseCountLeadingZerosInstruction, false, \ "Use count leading zeros instruction") \ @@ -234,8 +193,6 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); "Turn off JVM mitigations related to Intel micro code " \ "mitigations for the Intel JCC erratum") \ \ - product(bool, UseAPX, false, EXPERIMENTAL, \ - "Use Advanced Performance Extensions on x86") \ // end of ARCH_FLAGS #endif // CPU_X86_GLOBALS_X86_HPP diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index fd989c7bd22..492ea99e045 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -30,7 +30,6 @@ #include "code/vmreg.inline.hpp" #include "compiler/oopMap.hpp" #include "utilities/macros.hpp" -#include "runtime/rtmLocking.hpp" #include "runtime/vm_version.hpp" #include "utilities/checkedCast.hpp" diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp index f8cbf70f189..70cb6179366 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.hpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp @@ -160,6 +160,7 @@ class NativeCall: public NativeInstruction { return_address_offset = 5 }; + static int byte_size() { return instruction_size; } address instruction_address() const { return addr_at(instruction_offset); } address next_instruction_address() const { return addr_at(return_address_offset); } int displacement() const { return (jint) int_at(displacement_offset); } diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index febc1b2c3b1..79a573763dc 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -1476,13 +1476,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Frame is now completed as far as size and linkage. int frame_complete = ((intptr_t)__ pc()) - start; - if (UseRTMLocking) { - // Abort RTM transaction before calling JNI - // because critical section will be large and will be - // aborted anyway. Also nmethod could be deoptimized. - __ xabort(0); - } - // Calculate the difference between rsp and rbp,. We need to know it // after the native call because on windows Java Natives will pop // the arguments and it is painful to do rsp relative addressing @@ -2422,11 +2415,6 @@ void SharedRuntime::generate_uncommon_trap_blob() { address start = __ pc(); - if (UseRTMLocking) { - // Abort RTM transaction before possible nmethod deoptimization. - __ xabort(0); - } - // Push self-frame. __ subptr(rsp, return_off*wordSize); // Epilog! @@ -2609,13 +2597,6 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t bool cause_return = (poll_type == POLL_AT_RETURN); bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); - if (UseRTMLocking) { - // Abort RTM transaction before calling runtime - // because critical section will be large and will be - // aborted anyway. Also nmethod could be deoptimized. - __ xabort(0); - } - // If cause_return is true we are at a poll_return and there is // the return address on the stack to the caller on the nmethod // that is safepoint. We can leave this return on the stack and diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 31bbfb747f8..ac7baeaf74f 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1959,13 +1959,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Frame is now completed as far as size and linkage. int frame_complete = ((intptr_t)__ pc()) - start; - if (UseRTMLocking) { - // Abort RTM transaction before calling JNI - // because critical section will be large and will be - // aborted anyway. Also nmethod could be deoptimized. - __ xabort(0); - } - #ifdef ASSERT __ check_stack_alignment(rsp, "improperly aligned stack"); #endif /* ASSERT */ @@ -2921,11 +2914,6 @@ void SharedRuntime::generate_uncommon_trap_blob() { address start = __ pc(); - if (UseRTMLocking) { - // Abort RTM transaction before possible nmethod deoptimization. - __ xabort(0); - } - // Push self-frame. We get here with a return address on the // stack, so rsp is 8-byte aligned until we allocate our frame. __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog! @@ -3112,13 +3100,6 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t bool cause_return = (poll_type == POLL_AT_RETURN); bool save_wide_vectors = (poll_type == POLL_AT_VECTOR_LOOP); - if (UseRTMLocking) { - // Abort RTM transaction before calling runtime - // because critical section will be large and will be - // aborted anyway. Also nmethod could be deoptimized. - __ xabort(0); - } - // Make room for return address (or push it again) if (!cause_return) { __ push(rbx); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 577c56cb7a2..c9c4b056eb5 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4241,6 +4241,12 @@ void StubGenerator::generate_compiler_stubs() { generate_chacha_stubs(); +#ifdef COMPILER2 + if ((UseAVX == 2) && EnableX86ECoreOpts) { + generate_string_indexof(StubRoutines::_string_indexof_array); + } +#endif + if (UseAdler32Intrinsics) { StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32(); } diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 02435bd172c..374679750a4 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -575,6 +575,9 @@ class StubGenerator: public StubCodeGenerator { void generate_libm_stubs(); +#ifdef COMPILER2 + void generate_string_indexof(address *fnptrs); +#endif address generate_cont_thaw(const char* label, Continuation::thaw_kind kind); address generate_cont_thaw(); diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index cfb91c5c083..b5ed3719897 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -37,7 +37,7 @@ enum platform_dependent_constants { _continuation_stubs_code_size = 1000 LP64_ONLY(+1000), // AVX512 intrinsics add more code in 64-bit VM, // Windows have more code to save/restore registers - _compiler_stubs_code_size = 20000 LP64_ONLY(+39000) WINDOWS_ONLY(+2000), + _compiler_stubs_code_size = 20000 LP64_ONLY(+46000) WINDOWS_ONLY(+2000), _final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+2000) ZGC_ONLY(+20000) }; diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index f5389d0ef90..103a7726276 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -56,6 +56,10 @@ const char* VM_Version::_features_names[] = { CPU_FEATURE_FLAGS(DECLARE_CPU_FEAT address VM_Version::_cpuinfo_segv_addr = 0; // Address of instruction after the one which causes SEGV address VM_Version::_cpuinfo_cont_addr = 0; +// Address of instruction which causes APX specific SEGV +address VM_Version::_cpuinfo_segv_addr_apx = 0; +// Address of instruction after the one which causes APX specific SEGV +address VM_Version::_cpuinfo_cont_addr_apx = 0; static BufferBlob* stub_blob; static const int stub_size = 2000; @@ -63,9 +67,11 @@ static const int stub_size = 2000; extern "C" { typedef void (*get_cpu_info_stub_t)(void*); typedef void (*detect_virt_stub_t)(uint32_t, uint32_t*); + typedef void (*clear_apx_test_state_t)(void); } static get_cpu_info_stub_t get_cpu_info_stub = nullptr; static detect_virt_stub_t detect_virt_stub = nullptr; +static clear_apx_test_state_t clear_apx_test_state_stub = nullptr; #ifdef _LP64 @@ -102,6 +108,27 @@ class VM_Version_StubGenerator: public StubCodeGenerator { VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {} + address clear_apx_test_state() { +# define __ _masm-> + address start = __ pc(); + // EGPRs are call clobbered registers, Explicit clearing of r16 and r31 during signal + // handling guarantees that preserved register values post signal handling were + // re-instantiated by operating system and not because they were not modified externally. + + /* FIXME Uncomment following code after OS enablement of + bool save_apx = UseAPX; + VM_Version::set_apx_cpuFeatures(); + UseAPX = true; + // EGPR state save/restoration. + __ mov64(r16, 0L); + __ mov64(r31, 0L); + UseAPX = save_apx; + VM_Version::clean_cpuFeatures(); + */ + __ ret(0); + return start; + } + address generate_get_cpu_info() { // Flags to test CPU type. const uint32_t HS_EFL_AC = 0x40000; @@ -113,7 +140,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator { bool use_evex = FLAG_IS_DEFAULT(UseAVX) || (UseAVX > 2); Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; - Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, ext_cpuid8, done, wrapup; + Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7; + Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning; Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check; StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub"); @@ -288,7 +316,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(Address(rsi, 4), rdx); // - // cpuid(0x7) Structured Extended Features + // cpuid(0x7) Structured Extended Features Enumeration Leaf. // __ bind(sef_cpuid); __ movl(rax, 7); @@ -303,12 +331,16 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi, 12), rdx); - // ECX = 1 + // + // cpuid(0x7) Structured Extended Features Enumeration Sub-Leaf 1. + // + __ bind(sefsl1_cpuid); __ movl(rax, 7); __ movl(rcx, 1); __ cpuid(); - __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_ecx1_offset()))); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset()))); __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rdx); // // Extended cpuid(0x80000000) @@ -387,6 +419,46 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); +#ifndef PRODUCT + // + // Check if OS has enabled XGETBV instruction to access XCR0 + // (OSXSAVE feature flag) and CPU supports APX + // + // To enable APX, check CPUID.EAX=7.ECX=1.EDX[21] bit for HW support + // and XCRO[19] bit for OS support to save/restore extended GPR state. + __ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset()))); + __ movl(rax, 0x200000); + __ andl(rax, Address(rsi, 4)); + __ cmpl(rax, 0x200000); + __ jcc(Assembler::notEqual, vector_save_restore); + // check _cpuid_info.xem_xcr0_eax.bits.apx_f + __ movl(rax, 0x80000); + __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits apx_f + __ cmpl(rax, 0x80000); + __ jcc(Assembler::notEqual, vector_save_restore); + + /* FIXME: Uncomment while integrating JDK-8329032 + bool save_apx = UseAPX; + VM_Version::set_apx_cpuFeatures(); + UseAPX = true; + __ mov64(r16, VM_Version::egpr_test_value()); + __ mov64(r31, VM_Version::egpr_test_value()); + */ + __ xorl(rsi, rsi); + VM_Version::set_cpuinfo_segv_addr_apx(__ pc()); + // Generate SEGV + __ movl(rax, Address(rsi, 0)); + + VM_Version::set_cpuinfo_cont_addr_apx(__ pc()); + /* FIXME: Uncomment after integration of JDK-8329032 + __ lea(rsi, Address(rbp, in_bytes(VM_Version::apx_save_offset()))); + __ movq(Address(rsi, 0), r16); + __ movq(Address(rsi, 8), r31); + + UseAPX = save_apx; + */ +#endif + __ bind(vector_save_restore); // // Check if OS has enabled XGETBV instruction to access XCR0 // (OSXSAVE feature flag) and CPU supports AVX @@ -580,6 +652,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ vmovdqu(xmm7, Address(rsp, 0)); __ addptr(rsp, 32); #endif // _WINDOWS + generate_vzeroupper(wrapup); VM_Version::clean_cpuFeatures(); UseAVX = saved_useavx; @@ -940,6 +1013,7 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseAVX, use_avx_limit); } } + if (UseAVX > use_avx_limit) { if (UseSSE < 4) { warning("UseAVX=%d requires UseSSE=4, setting it to UseAVX=0", UseAVX); @@ -963,6 +1037,16 @@ void VM_Version::get_processor_features() { _features &= ~CPU_AVX512_VBMI2; _features &= ~CPU_AVX512_BITALG; _features &= ~CPU_AVX512_IFMA; + _features &= ~CPU_APX_F; + } + + // Currently APX support is only enabled for targets supporting AVX512VL feature. + bool apx_supported = os_supports_apx_egprs() && supports_apx_f() && supports_avx512vl(); + if (UseAPX && !apx_supported) { + warning("UseAPX is not supported on this CPU, setting it to false"); + FLAG_SET_DEFAULT(UseAPX, false); + } else if (FLAG_IS_DEFAULT(UseAPX)) { + FLAG_SET_DEFAULT(UseAPX, apx_supported ? true : false); } if (UseAVX < 2) { @@ -1002,14 +1086,6 @@ void VM_Version::get_processor_features() { } } - // APX support not enabled yet - if (UseAPX) { - if (!FLAG_IS_DEFAULT(UseAPX)) { - warning("APX is not supported on this CPU."); - } - FLAG_SET_DEFAULT(UseAPX, false); - } - if (FLAG_IS_DEFAULT(IntelJccErratumMitigation)) { _has_intel_jcc_erratum = compute_has_intel_jcc_erratum(); } else { @@ -1246,55 +1322,6 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA, false); } - if (!supports_rtm() && UseRTMLocking) { - vm_exit_during_initialization("RTM instructions are not available on this CPU"); - } - -#if INCLUDE_RTM_OPT - if (UseRTMLocking) { - if (!CompilerConfig::is_c2_enabled()) { - // Only C2 does RTM locking optimization. - vm_exit_during_initialization("RTM locking optimization is not supported in this VM"); - } - if (is_intel_family_core()) { - if ((_model == CPU_MODEL_HASWELL_E3) || - (_model == CPU_MODEL_HASWELL_E7 && _stepping < 3) || - (_model == CPU_MODEL_BROADWELL && _stepping < 4)) { - // currently a collision between SKL and HSW_E3 - if (!UnlockExperimentalVMOptions && UseAVX < 3) { - vm_exit_during_initialization("UseRTMLocking is only available as experimental option on this " - "platform. It must be enabled via -XX:+UnlockExperimentalVMOptions flag."); - } else { - warning("UseRTMLocking is only available as experimental option on this platform."); - } - } - } - if (!FLAG_IS_CMDLINE(UseRTMLocking)) { - // RTM locking should be used only for applications with - // high lock contention. For now we do not use it by default. - vm_exit_during_initialization("UseRTMLocking flag should be only set on command line"); - } - } else { // !UseRTMLocking - if (UseRTMForStackLocks) { - if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) { - warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off"); - } - FLAG_SET_DEFAULT(UseRTMForStackLocks, false); - } - if (UseRTMDeopt) { - FLAG_SET_DEFAULT(UseRTMDeopt, false); - } - if (PrintPreciseRTMLockingStatistics) { - FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false); - } - } -#else - if (UseRTMLocking) { - // Only C2 does RTM locking optimization. - vm_exit_during_initialization("RTM locking optimization is not supported in this VM"); - } -#endif - #ifdef COMPILER2 if (UseFPUForSpilling) { if (UseSSE < 2) { @@ -2143,6 +2170,10 @@ int VM_Version::avx3_threshold() { FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold; } +void VM_Version::clear_apx_test_state() { + clear_apx_test_state_stub(); +} + static bool _vm_version_initialized = false; void VM_Version::initialize() { @@ -2160,6 +2191,8 @@ void VM_Version::initialize() { detect_virt_stub = CAST_TO_FN_PTR(detect_virt_stub_t, g.generate_detect_virt()); + clear_apx_test_state_stub = CAST_TO_FN_PTR(clear_apx_test_state_t, + g.clear_apx_test_state()); get_processor_features(); LP64_ONLY(Assembler::precompute_instructions();) @@ -2958,6 +2991,10 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { result |= CPU_SSE4_2; if (std_cpuid1_ecx.bits.popcnt != 0) result |= CPU_POPCNT; + if (sefsl1_cpuid7_edx.bits.apx_f != 0 && + xem_xcr0_eax.bits.apx_f != 0) { + result |= CPU_APX_F; + } if (std_cpuid1_ecx.bits.avx != 0 && std_cpuid1_ecx.bits.osxsave != 0 && xem_xcr0_eax.bits.sse != 0 && @@ -2968,7 +3005,7 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { result |= CPU_F16C; if (sef_cpuid7_ebx.bits.avx2 != 0) { result |= CPU_AVX2; - if (sef_cpuid7_ecx1_eax.bits.avx_ifma != 0) + if (sefsl1_cpuid7_eax.bits.avx_ifma != 0) result |= CPU_AVX_IFMA; } if (sef_cpuid7_ecx.bits.gfni != 0) @@ -3142,6 +3179,17 @@ bool VM_Version::os_supports_avx_vectors() { return retVal; } +bool VM_Version::os_supports_apx_egprs() { + if (!supports_apx_f()) { + return false; + } + if (_cpuid_info.apx_save[0] != egpr_test_value() || + _cpuid_info.apx_save[1] != egpr_test_value()) { + return false; + } + return true; +} + uint VM_Version::cores_per_cpu() { uint result = 1; if (is_intel()) { diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 18b272ab58b..dc5fb960060 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -26,6 +26,7 @@ #define CPU_X86_VM_VERSION_X86_HPP #include "runtime/abstract_vm_version.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" #include "utilities/sizes.hpp" @@ -279,7 +280,7 @@ class VM_Version : public Abstract_VM_Version { } bits; }; - union SefCpuid7Ecx1Eax { + union SefCpuid7SubLeaf1Eax { uint32_t value; struct { uint32_t : 23, @@ -288,6 +289,15 @@ class VM_Version : public Abstract_VM_Version { } bits; }; + union SefCpuid7SubLeaf1Edx { + uint32_t value; + struct { + uint32_t : 21, + apx_f : 1, + : 10; + } bits; + }; + union ExtCpuid1EEbx { uint32_t value; struct { @@ -308,7 +318,9 @@ class VM_Version : public Abstract_VM_Version { opmask : 1, zmm512 : 1, zmm32 : 1, - : 24; + : 11, + apx_f : 1, + : 12; } bits; }; @@ -319,8 +331,10 @@ class VM_Version : public Abstract_VM_Version { static bool _has_intel_jcc_erratum; - static address _cpuinfo_segv_addr; // address of instruction which causes SEGV - static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV + static address _cpuinfo_segv_addr; // address of instruction which causes SEGV + static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV + static address _cpuinfo_segv_addr_apx; // address of instruction which causes APX specific SEGV + static address _cpuinfo_cont_addr_apx; // address of instruction after the one which causes APX specific SEGV /* * Update following files when declaring new flags: @@ -400,7 +414,8 @@ class VM_Version : public Abstract_VM_Version { decl(CET_IBT, "cet_ibt", 56) /* Control Flow Enforcement - Indirect Branch Tracking */ \ decl(CET_SS, "cet_ss", 57) /* Control Flow Enforcement - Shadow Stack */ \ decl(AVX512_IFMA, "avx512_ifma", 58) /* Integer Vector FMA instructions*/ \ - decl(AVX_IFMA, "avx_ifma", 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ + decl(AVX_IFMA, "avx_ifma", 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ \ + decl(APX_F, "apx_f", 60) /* Intel Advanced Performance Extensions*/ #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1ULL << bit), CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) @@ -458,14 +473,17 @@ class VM_Version : public Abstract_VM_Version { uint32_t dcp_cpuid4_ecx; // unused currently uint32_t dcp_cpuid4_edx; // unused currently - // cpuid function 7 (structured extended features) - // ECX = 0 before calling cpuid() + // cpuid function 7 (structured extended features enumeration leaf) + // eax = 7, ecx = 0 SefCpuid7Eax sef_cpuid7_eax; SefCpuid7Ebx sef_cpuid7_ebx; SefCpuid7Ecx sef_cpuid7_ecx; SefCpuid7Edx sef_cpuid7_edx; - // ECX = 1 before calling cpuid() - SefCpuid7Ecx1Eax sef_cpuid7_ecx1_eax; + + // cpuid function 7 (structured extended features enumeration sub-leaf 1) + // eax = 7, ecx = 1 + SefCpuid7SubLeaf1Eax sefsl1_cpuid7_eax; + SefCpuid7SubLeaf1Edx sefsl1_cpuid7_edx; // cpuid function 0xB (processor topology) // ecx = 0 @@ -537,6 +555,9 @@ class VM_Version : public Abstract_VM_Version { // Space to save zmm registers after signal handle int zmm_save[16*4]; // Save zmm0, zmm7, zmm8, zmm31 + // Space to save apx registers after signal handle + jlong apx_save[2]; // Save r16 and r31 + uint64_t feature_flags() const; // Asserts @@ -576,6 +597,7 @@ class VM_Version : public Abstract_VM_Version { static bool compute_has_intel_jcc_erratum(); static bool os_supports_avx_vectors(); + static bool os_supports_apx_egprs(); static void get_processor_features(); public: @@ -584,7 +606,7 @@ class VM_Version : public Abstract_VM_Version { static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); } static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); } - static ByteSize sef_cpuid7_ecx1_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_ecx1_eax); } + static ByteSize sefsl1_cpuid7_offset() { return byte_offset_of(CpuidInfo, sefsl1_cpuid7_eax); } static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); } static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); } static ByteSize ext_cpuid7_offset() { return byte_offset_of(CpuidInfo, ext_cpuid7_eax); } @@ -596,9 +618,11 @@ class VM_Version : public Abstract_VM_Version { static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); } static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); } static ByteSize zmm_save_offset() { return byte_offset_of(CpuidInfo, zmm_save); } + static ByteSize apx_save_offset() { return byte_offset_of(CpuidInfo, apx_save); } // The value used to check ymm register after signal handle static int ymm_test_value() { return 0xCAFEBABE; } + static jlong egpr_test_value() { return 0xCAFEBABECAFEBABELL; } static void get_cpu_info_wrapper(); static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; } @@ -606,9 +630,17 @@ class VM_Version : public Abstract_VM_Version { static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; } static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } + static void set_cpuinfo_segv_addr_apx(address pc) { _cpuinfo_segv_addr_apx = pc; } + static bool is_cpuinfo_segv_addr_apx(address pc) { return _cpuinfo_segv_addr_apx == pc; } + static void set_cpuinfo_cont_addr_apx(address pc) { _cpuinfo_cont_addr_apx = pc; } + static address cpuinfo_cont_addr_apx() { return _cpuinfo_cont_addr_apx; } + + static void clear_apx_test_state(); + static void clean_cpuFeatures() { _features = 0; } static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } + static void set_apx_cpuFeatures() { _features |= CPU_APX_F; } // Initialization static void initialize(); @@ -705,6 +737,7 @@ class VM_Version : public Abstract_VM_Version { static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } + static bool supports_apx_f() { return (_features & CPU_APX_F) != 0; } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } static bool supports_sha() { return (_features & CPU_SHA) != 0; } static bool supports_fma() { return (_features & CPU_FMA) != 0 && supports_avx(); } diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 240e9b10323..49a3cad37df 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -13613,25 +13613,8 @@ instruct RethrowException() // inlined locking and unlocking -instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eDXRegI scr, rRegI cx1, rRegI cx2, eRegP thread) %{ - predicate(Compile::current()->use_rtm()); - match(Set cr (FastLock object box)); - effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box, TEMP thread); - ins_cost(300); - format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %} - ins_encode %{ - __ get_thread($thread$$Register); - __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, - $scr$$Register, $cx1$$Register, $cx2$$Register, $thread$$Register, - _rtm_counters, _stack_rtm_counters, - ((Method*)(ra_->C->method()->constant_encoding()))->method_data(), - true, ra_->C->profile_rtm()); - %} - ins_pipe(pipe_slow); -%} - instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr, eRegP thread) %{ - predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm()); + predicate(LockingMode != LM_LIGHTWEIGHT); match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box, TEMP thread); ins_cost(300); @@ -13639,7 +13622,7 @@ instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP ins_encode %{ __ get_thread($thread$$Register); __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, - $scr$$Register, noreg, noreg, $thread$$Register, nullptr, nullptr, nullptr, false, false); + $scr$$Register, noreg, noreg, $thread$$Register, nullptr); %} ins_pipe(pipe_slow); %} @@ -13651,7 +13634,7 @@ instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{ ins_cost(300); format %{ "FASTUNLOCK $object,$box\t! kills $box,$tmp" %} ins_encode %{ - __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm()); + __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index f3ad721dfcb..34eb9903401 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -12260,31 +12260,15 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ // ============================================================================ // inlined locking and unlocking -instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rdx_RegI scr, rRegI cx1, rRegI cx2) %{ - predicate(Compile::current()->use_rtm()); - match(Set cr (FastLock object box)); - effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box); - ins_cost(300); - format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %} - ins_encode %{ - __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, - $scr$$Register, $cx1$$Register, $cx2$$Register, r15_thread, - _rtm_counters, _stack_rtm_counters, - ((Method*)(ra_->C->method()->constant_encoding()))->method_data(), - true, ra_->C->profile_rtm()); - %} - ins_pipe(pipe_slow); -%} - instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{ - predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm()); + predicate(LockingMode != LM_LIGHTWEIGHT); match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box); ins_cost(300); format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %} ins_encode %{ __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, - $scr$$Register, noreg, noreg, r15_thread, nullptr, nullptr, nullptr, false, false); + $scr$$Register, noreg, noreg, r15_thread, nullptr); %} ins_pipe(pipe_slow); %} @@ -12296,7 +12280,7 @@ instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{ ins_cost(300); format %{ "fastunlock $object,$box\t! kills $box,$tmp" %} ins_encode %{ - __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm()); + __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/zero/nativeInst_zero.hpp b/src/hotspot/cpu/zero/nativeInst_zero.hpp index 77a7d511ac5..2f3d9b80617 100644 --- a/src/hotspot/cpu/zero/nativeInst_zero.hpp +++ b/src/hotspot/cpu/zero/nativeInst_zero.hpp @@ -70,6 +70,8 @@ class NativeCall : public NativeInstruction { instruction_size = 0 // not used within the interpreter }; + static int byte_size() { return instruction_size; } + address instruction_address() const { ShouldNotCallThis(); return nullptr; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 20d3c99cd3e..00ee3519301 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -314,7 +314,10 @@ static jlong host_free_swap() { } jlong os::free_swap_space() { - jlong host_free_swap_val = host_free_swap(); + // os::total_swap_space() might return the containerized limit which might be + // less than host_free_swap(). The upper bound of free swap needs to be the lower of the two. + jlong host_free_swap_val = MIN2(os::total_swap_space(), host_free_swap()); + assert(host_free_swap_val >= 0, "sysinfo failed?"); if (OSContainer::is_containerized()) { jlong mem_swap_limit = OSContainer::memory_and_swap_limit_in_bytes(); jlong mem_limit = OSContainer::memory_limit_in_bytes(); diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 30783c809f9..773bda647e1 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2744,6 +2744,15 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { // Verify that OS save/restore AVX registers. return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr()); } + +#ifndef PRODUCT + if ((exception_code == EXCEPTION_ACCESS_VIOLATION) && + VM_Version::is_cpuinfo_segv_addr_apx(pc)) { + // Verify that OS save/restore APX registers. + VM_Version::clear_apx_test_state(); + return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr_apx()); + } +#endif #endif if (t != nullptr && t->is_Java_thread()) { diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index 4e7316e0661..17f256eadb7 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -416,6 +416,14 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, stub = VM_Version::cpuinfo_cont_addr(); } +#ifndef PRODUCT + if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) { + // Verify that OS save/restore APX registers. + stub = VM_Version::cpuinfo_cont_addr_apx(); + VM_Version::clear_apx_test_state(); + } +#endif + // We test if stub is already set (by the stack overflow code // above) so it is not overwritten by the code that follows. This // check is not required on other platforms, because on other diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 6cdb2a5e3f6..35e9321a2a7 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -248,6 +248,14 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, stub = VM_Version::cpuinfo_cont_addr(); } +#ifndef PRODUCT + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) { + // Verify that OS save/restore APX registers. + stub = VM_Version::cpuinfo_cont_addr_apx(); + VM_Version::clear_apx_test_state(); + } +#endif + if (thread->thread_state() == _thread_in_Java) { // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 77332b21c01..804e8f1a4e6 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1614,11 +1614,6 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { fprintf(fp, " ((MachIfNode*)n%d)->_fcnt = _fcnt;\n", cnt); } - if (node->is_ideal_fastlock() && new_inst->is_ideal_fastlock()) { - fprintf(fp, " ((MachFastLockNode*)n%d)->_rtm_counters = _rtm_counters;\n", cnt); - fprintf(fp, " ((MachFastLockNode*)n%d)->_stack_rtm_counters = _stack_rtm_counters;\n", cnt); - } - // Fill in the bottom_type where requested if (node->captures_bottom_type(_globalNames) && new_inst->captures_bottom_type(_globalNames)) { @@ -4008,10 +4003,6 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden if (inst->is_ideal_jump()) { fprintf(fp_cpp, "%s node->_probs = _leaf->as_Jump()->_probs;\n", indent); } - if( inst->is_ideal_fastlock() ) { - fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent); - fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent); - } } diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index d0c8feda24a..ea47e435c0b 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -928,6 +928,10 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { // Move all the code and relocations to the new blob: relocate_code_to(&cb); + // some internal addresses, _last_insn _last_label, are used during code emission, + // adjust them in expansion + adjust_internal_address(insts_begin(), cb.insts_begin()); + // Copy the temporary code buffer into the current code buffer. // Basically, do {*this = cb}, except for some control information. this->take_over_code_from(&cb); @@ -949,6 +953,15 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { #endif //PRODUCT } +void CodeBuffer::adjust_internal_address(address from, address to) { + if (_last_insn != nullptr) { + _last_insn += to - from; + } + if (_last_label != nullptr) { + _last_label += to - from; + } +} + void CodeBuffer::take_over_code_from(CodeBuffer* cb) { // Must already have disposed of the old blob somehow. assert(blob() == nullptr, "must be empty"); diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index 48476bedfe2..343981e1a7b 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -433,6 +433,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { Arena* _overflow_arena; address _last_insn; // used to merge consecutive memory barriers, loads or stores. + address _last_label; // record last bind label address, it's also the start of current bb. SharedStubToInterpRequests* _shared_stub_to_interp_requests; // used to collect requests for shared iterpreter stubs SharedTrampolineRequests* _shared_trampoline_requests; // used to collect requests for shared trampolines @@ -457,6 +458,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { _oop_recorder = nullptr; _overflow_arena = nullptr; _last_insn = nullptr; + _last_label = nullptr; _finalize_stubs = false; _shared_stub_to_interp_requests = nullptr; _shared_trampoline_requests = nullptr; @@ -510,6 +512,9 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { // moves code sections to new buffer (assumes relocs are already in there) void relocate_code_to(CodeBuffer* cb) const; + // adjust some internal address during expand + void adjust_internal_address(address from, address to); + // set up a model of the final layout of my contents void compute_final_layout(CodeBuffer* dest) const; @@ -679,6 +684,9 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { void set_last_insn(address a) { _last_insn = a; } void clear_last_insn() { set_last_insn(nullptr); } + address last_label() const { return _last_label; } + void set_last_label(address a) { _last_label = a; } + #ifndef PRODUCT AsmRemarks &asm_remarks() { return _asm_remarks; } DbgStrings &dbg_strings() { return _dbg_strings; } diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index 897e2b6470d..e1c4e90d063 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -235,7 +235,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_getObjectSize: -#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) +#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) case vmIntrinsics::_clone: #endif break; diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index 6ca5b1bd136..3f53011024b 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -351,7 +351,7 @@ LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_ , _tmp(tmp) , _expected_type(expected_type) , _flags(flags) { -#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) +#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) if (expected_type != nullptr && flags == 0) { _stub = nullptr; } else { diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index 6d11a436f65..565300f43b4 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -1032,8 +1032,7 @@ void ciEnv::register_method(ciMethod* target, bool has_unsafe_access, bool has_wide_vectors, bool has_monitors, - int immediate_oops_patched, - RTMState rtm_state) { + int immediate_oops_patched) { VM_ENTRY_MARK; nmethod* nm = nullptr; { @@ -1090,14 +1089,6 @@ void ciEnv::register_method(ciMethod* target, // Check for {class loads, evolution, breakpoints, ...} during compilation validate_compile_task_dependencies(target); } -#if INCLUDE_RTM_OPT - if (!failing() && (rtm_state != NoRTM) && - (method()->method_data() != nullptr) && - (method()->method_data()->rtm_state() != rtm_state)) { - // Preemptive decompile if rtm state was changed. - record_failure("RTM state change invalidated rtm code"); - } -#endif if (failing()) { // While not a true deoptimization, it is a preemptive decompile. @@ -1134,9 +1125,6 @@ void ciEnv::register_method(ciMethod* target, nm->set_has_wide_vectors(has_wide_vectors); nm->set_has_monitors(has_monitors); assert(!method->is_synchronized() || nm->has_monitors(), ""); -#if INCLUDE_RTM_OPT - nm->set_rtm_state(rtm_state); -#endif if (entry_bci == InvocationEntryBci) { if (TieredCompilation) { diff --git a/src/hotspot/share/ci/ciEnv.hpp b/src/hotspot/share/ci/ciEnv.hpp index 5d3a61f809e..be63632ba4e 100644 --- a/src/hotspot/share/ci/ciEnv.hpp +++ b/src/hotspot/share/ci/ciEnv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -383,8 +383,7 @@ class ciEnv : StackObj { bool has_unsafe_access, bool has_wide_vectors, bool has_monitors, - int immediate_oops_patched, - RTMState rtm_state = NoRTM); + int immediate_oops_patched); // Access to certain well known ciObjects. #define VM_CLASS_FUNC(name, ignore_s) \ diff --git a/src/hotspot/share/ci/ciMethodData.hpp b/src/hotspot/share/ci/ciMethodData.hpp index dedbfc9f4d6..a43d011b77e 100644 --- a/src/hotspot/share/ci/ciMethodData.hpp +++ b/src/hotspot/share/ci/ciMethodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -479,17 +479,6 @@ class ciMethodData : public ciMetadata { int invocation_count() { return _invocation_counter; } -#if INCLUDE_RTM_OPT - // return cached value - int rtm_state() { - if (is_empty()) { - return NoRTM; - } else { - return get_MethodData()->rtm_state(); - } - } -#endif - // Transfer information about the method to MethodData*. // would_profile means we would like to profile this method, // meaning it's not trivial. diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index 1fbc49947bf..f680939682a 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -172,7 +172,7 @@ class SymbolTableConfig : public AllStatic { // Deleting permanent symbol should not occur very often (insert race condition), // so log it. log_trace_symboltable_helper(&value, "Freeing permanent symbol"); - size_t alloc_size = _local_table->get_node_size() + value.byte_size() + value.effective_length(); + size_t alloc_size = SymbolTableHash::get_dynamic_node_size(value.byte_size()); if (!SymbolTable::arena()->Afree(memory, alloc_size)) { log_trace_symboltable_helper(&value, "Leaked permanent symbol"); } @@ -182,7 +182,7 @@ class SymbolTableConfig : public AllStatic { private: static void* allocate_node_impl(size_t size, Value const& value) { - size_t alloc_size = size + value.byte_size() + value.effective_length(); + size_t alloc_size = SymbolTableHash::get_dynamic_node_size(value.byte_size()); #if INCLUDE_CDS if (CDSConfig::is_dumping_static_archive()) { MutexLocker ml(DumpRegion_lock, Mutex::_no_safepoint_check_flag); diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index fab77fbbdb2..bcfbae49fd9 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1229,9 +1229,6 @@ void nmethod::init_defaults(CodeBuffer *code_buffer, CodeOffsets* offsets) { _oops_do_mark_link = nullptr; _compiled_ic_data = nullptr; -#if INCLUDE_RTM_OPT - _rtm_state = NoRTM; -#endif _is_unloading_state = 0; _state = not_installed; diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 9972b89ae40..e3ac422ca70 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -260,12 +260,6 @@ class nmethod : public CodeBlob { CompLevel _comp_level; // compilation level (s1) CompilerType _compiler_type; // which compiler made this nmethod (u1) -#if INCLUDE_RTM_OPT - // RTM state at compile time. Used during deoptimization to decide - // whether to restart collecting RTM locking abort statistic again. - RTMState _rtm_state; -#endif - // Local state used to keep track of whether unloading is happening or not volatile uint8_t _is_unloading_state; @@ -629,12 +623,6 @@ class nmethod : public CodeBlob { bool is_unloading(); void do_unloading(bool unloading_occurred); -#if INCLUDE_RTM_OPT - // rtm state accessing and manipulating - RTMState rtm_state() const { return _rtm_state; } - void set_rtm_state(RTMState state) { _rtm_state = state; } -#endif - bool make_in_use() { return try_transition(in_use); } diff --git a/src/hotspot/share/code/nmethod.inline.hpp b/src/hotspot/share/code/nmethod.inline.hpp index 4af4d3ffaed..49af1e0b95f 100644 --- a/src/hotspot/share/code/nmethod.inline.hpp +++ b/src/hotspot/share/code/nmethod.inline.hpp @@ -37,7 +37,7 @@ inline bool nmethod::is_deopt_pc(address pc) { return is_deopt_entry(pc) || is_d inline bool nmethod::is_deopt_entry(address pc) { return pc == deopt_handler_begin() #if INCLUDE_JVMCI - || (is_compiled_by_jvmci() && pc == (deopt_handler_begin() + NativeCall::instruction_size)) + || (is_compiled_by_jvmci() && pc == (deopt_handler_begin() + NativeCall::byte_size())) #endif ; } @@ -45,7 +45,7 @@ inline bool nmethod::is_deopt_entry(address pc) { inline bool nmethod::is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin() #if INCLUDE_JVMCI - || (is_compiled_by_jvmci() && pc == (deopt_mh_handler_begin() + NativeCall::instruction_size)) + || (is_compiled_by_jvmci() && pc == (deopt_mh_handler_begin() + NativeCall::byte_size())) #endif ; } diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index 9b69501a598..03b7d446b1a 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -98,23 +98,6 @@ inline bool is_compile(int comp_level) { return is_c1_compile(comp_level) || is_c2_compile(comp_level); } - -// States of Restricted Transactional Memory usage. -enum RTMState: u1 { - NoRTM = 0x2, // Don't use RTM - UseRTM = 0x1, // Use RTM - ProfileRTM = 0x0 // Use RTM with abort ratio calculation -}; - -#ifndef INCLUDE_RTM_OPT -#define INCLUDE_RTM_OPT 0 -#endif -#if INCLUDE_RTM_OPT -#define RTM_OPT_ONLY(code) code -#else -#define RTM_OPT_ONLY(code) -#endif - class CompilerConfig : public AllStatic { public: // Scale compile thresholds diff --git a/src/hotspot/share/compiler/compilerDirectives.cpp b/src/hotspot/share/compiler/compilerDirectives.cpp index b48eb4fb817..74259c8e5d4 100644 --- a/src/hotspot/share/compiler/compilerDirectives.cpp +++ b/src/hotspot/share/compiler/compilerDirectives.cpp @@ -761,7 +761,7 @@ DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, if (dir->is_default_directive() || dir->match(method)) { match = dir->get_for(comp); assert(match != nullptr, "Consistency"); - if (match->EnableOption) { + if (match->EnableOption || dir->is_default_directive()) { // The directiveSet for this compile is also enabled -> success dir->inc_refcount(); break; diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index 1a85e0629f9..5864ca5dc0d 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -77,8 +77,6 @@ class methodHandle; option(CompileThresholdScaling, "CompileThresholdScaling", Double) \ option(ControlIntrinsic, "ControlIntrinsic", Ccstrlist) \ option(DisableIntrinsic, "DisableIntrinsic", Ccstrlist) \ - option(NoRTMLockEliding, "NoRTMLockEliding", Bool) \ - option(UseRTMLockEliding, "UseRTMLockEliding", Bool) \ option(BlockLayoutByFrequency, "BlockLayoutByFrequency", Bool) \ option(TraceOptoPipelining, "TraceOptoPipelining", Bool) \ option(TraceOptoOutput, "TraceOptoOutput", Bool) \ diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp index ed594d72d06..49f1c82a98a 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp @@ -227,7 +227,7 @@ void G1CollectedHeap::register_region_with_region_attr(G1HeapRegion* r) { void G1CollectedHeap::register_old_region_with_region_attr(G1HeapRegion* r) { assert(!r->has_pinned_objects(), "must be"); assert(r->rem_set()->is_complete(), "must be"); - _region_attr.set_in_old(r->hrm_index(), r->rem_set()->is_tracked()); + _region_attr.set_in_old(r->hrm_index(), true); _rem_set->exclude_region_from_scan(r->hrm_index()); } diff --git a/src/hotspot/share/gc/parallel/psOldGen.hpp b/src/hotspot/share/gc/parallel/psOldGen.hpp index 35cefec8a0a..68cac7128da 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.hpp +++ b/src/hotspot/share/gc/parallel/psOldGen.hpp @@ -108,11 +108,6 @@ class PSOldGen : public CHeapObj { // Size info size_t capacity_in_bytes() const { return object_space()->capacity_in_bytes(); } size_t used_in_bytes() const { return object_space()->used_in_bytes(); } - size_t free_in_bytes() const { return object_space()->free_in_bytes(); } - - size_t capacity_in_words() const { return object_space()->capacity_in_words(); } - size_t used_in_words() const { return object_space()->used_in_words(); } - size_t free_in_words() const { return object_space()->free_in_words(); } bool is_maximal_no_gc() const { return virtual_space()->uncommitted_size() == 0; diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 7b8ae42aaa4..e0d174dcc6a 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -200,188 +200,6 @@ void PSParallelCompact::print_on_error(outputStream* st) { _mark_bitmap.print_on_error(st); } -#ifndef PRODUCT -const char* PSParallelCompact::space_names[] = { - "old ", "eden", "from", "to " -}; - -void PSParallelCompact::print_region_ranges() { - if (!log_develop_is_enabled(Trace, gc, compaction)) { - return; - } - Log(gc, compaction) log; - ResourceMark rm; - LogStream ls(log.trace()); - Universe::print_on(&ls); - log.trace("space bottom top end new_top"); - log.trace("------ ---------- ---------- ---------- ----------"); - - for (unsigned int id = 0; id < last_space_id; ++id) { - const MutableSpace* space = _space_info[id].space(); - log.trace("%u %s " - SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) " " - SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) " ", - id, space_names[id], - summary_data().addr_to_region_idx(space->bottom()), - summary_data().addr_to_region_idx(space->top()), - summary_data().addr_to_region_idx(space->end()), - summary_data().addr_to_region_idx(_space_info[id].new_top())); - } -} - -static void -print_generic_summary_region(size_t i, const ParallelCompactData::RegionData* c) -{ -#define REGION_IDX_FORMAT SIZE_FORMAT_W(7) -#define REGION_DATA_FORMAT SIZE_FORMAT_W(5) - - ParallelCompactData& sd = PSParallelCompact::summary_data(); - size_t dci = c->destination() ? sd.addr_to_region_idx(c->destination()) : 0; - log_develop_trace(gc, compaction)( - REGION_IDX_FORMAT " " - REGION_IDX_FORMAT " " PTR_FORMAT " " - REGION_DATA_FORMAT " " REGION_DATA_FORMAT " " - REGION_DATA_FORMAT " " REGION_IDX_FORMAT " %d", - i, dci, p2i(c->destination()), - c->partial_obj_size(), c->live_obj_size(), - c->data_size(), c->source_region(), c->destination_count()); - -#undef REGION_IDX_FORMAT -#undef REGION_DATA_FORMAT -} - -void -print_generic_summary_data(ParallelCompactData& summary_data, - HeapWord* const beg_addr, - HeapWord* const end_addr) -{ - size_t total_words = 0; - size_t i = summary_data.addr_to_region_idx(beg_addr); - const size_t last = summary_data.addr_to_region_idx(end_addr); - HeapWord* pdest = 0; - - while (i < last) { - ParallelCompactData::RegionData* c = summary_data.region(i); - if (c->data_size() != 0 || c->destination() != pdest) { - print_generic_summary_region(i, c); - total_words += c->data_size(); - pdest = c->destination(); - } - ++i; - } - - log_develop_trace(gc, compaction)("summary_data_bytes=" SIZE_FORMAT, total_words * HeapWordSize); -} - -void -PSParallelCompact::print_generic_summary_data(ParallelCompactData& summary_data, - HeapWord* const beg_addr, - HeapWord* const end_addr) { - ::print_generic_summary_data(summary_data,beg_addr, end_addr); -} - -static void -print_initial_summary_data(ParallelCompactData& summary_data, - const MutableSpace* space) { - if (space->top() == space->bottom()) { - return; - } - - const size_t region_size = ParallelCompactData::RegionSize; - typedef ParallelCompactData::RegionData RegionData; - HeapWord* const top_aligned_up = summary_data.region_align_up(space->top()); - const size_t end_region = summary_data.addr_to_region_idx(top_aligned_up); - const RegionData* c = summary_data.region(end_region - 1); - HeapWord* end_addr = c->destination() + c->data_size(); - const size_t live_in_space = pointer_delta(end_addr, space->bottom()); - - // Print (and count) the full regions at the beginning of the space. - size_t full_region_count = 0; - size_t i = summary_data.addr_to_region_idx(space->bottom()); - while (i < end_region && summary_data.region(i)->data_size() == region_size) { - ParallelCompactData::RegionData* c = summary_data.region(i); - log_develop_trace(gc, compaction)( - SIZE_FORMAT_W(5) " " PTR_FORMAT " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d", - i, p2i(c->destination()), - c->partial_obj_size(), c->live_obj_size(), - c->data_size(), c->source_region(), c->destination_count()); - ++full_region_count; - ++i; - } - - size_t live_to_right = live_in_space - full_region_count * region_size; - - double max_reclaimed_ratio = 0.0; - size_t max_reclaimed_ratio_region = 0; - size_t max_dead_to_right = 0; - size_t max_live_to_right = 0; - - // Print the 'reclaimed ratio' for regions while there is something live in - // the region or to the right of it. The remaining regions are empty (and - // uninteresting), and computing the ratio will result in division by 0. - while (i < end_region && live_to_right > 0) { - c = summary_data.region(i); - HeapWord* const region_addr = summary_data.region_to_addr(i); - const size_t used_to_right = pointer_delta(space->top(), region_addr); - const size_t dead_to_right = used_to_right - live_to_right; - const double reclaimed_ratio = double(dead_to_right) / live_to_right; - - if (reclaimed_ratio > max_reclaimed_ratio) { - max_reclaimed_ratio = reclaimed_ratio; - max_reclaimed_ratio_region = i; - max_dead_to_right = dead_to_right; - max_live_to_right = live_to_right; - } - - ParallelCompactData::RegionData* c = summary_data.region(i); - log_develop_trace(gc, compaction)( - SIZE_FORMAT_W(5) " " PTR_FORMAT " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d" - "%12.10f " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10), - i, p2i(c->destination()), - c->partial_obj_size(), c->live_obj_size(), - c->data_size(), c->source_region(), c->destination_count(), - reclaimed_ratio, dead_to_right, live_to_right); - - - live_to_right -= c->data_size(); - ++i; - } - - // Any remaining regions are empty. Print one more if there is one. - if (i < end_region) { - ParallelCompactData::RegionData* c = summary_data.region(i); - log_develop_trace(gc, compaction)( - SIZE_FORMAT_W(5) " " PTR_FORMAT " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d", - i, p2i(c->destination()), - c->partial_obj_size(), c->live_obj_size(), - c->data_size(), c->source_region(), c->destination_count()); - } - - log_develop_trace(gc, compaction)("max: " SIZE_FORMAT_W(4) " d2r=" SIZE_FORMAT_W(10) " l2r=" SIZE_FORMAT_W(10) " max_ratio=%14.12f", - max_reclaimed_ratio_region, max_dead_to_right, max_live_to_right, max_reclaimed_ratio); -} - -static void -print_initial_summary_data(ParallelCompactData& summary_data, - SpaceInfo* space_info) { - if (!log_develop_is_enabled(Trace, gc, compaction)) { - return; - } - - unsigned int id = PSParallelCompact::old_space_id; - const MutableSpace* space; - do { - space = space_info[id].space(); - print_initial_summary_data(summary_data, space); - } while (++id < PSParallelCompact::eden_space_id); - - do { - space = space_info[id].space(); - print_generic_summary_data(summary_data, space->bottom(), space->top()); - } while (++id < PSParallelCompact::last_space_id); -} -#endif // #ifndef PRODUCT - ParallelCompactData::ParallelCompactData() : _heap_start(nullptr), DEBUG_ONLY(_heap_end(nullptr) COMMA) @@ -1008,29 +826,6 @@ void PSParallelCompact::fill_dense_prefix_end(SpaceId id) { } } -#ifndef PRODUCT -void PSParallelCompact::summary_phase_msg(SpaceId dst_space_id, - HeapWord* dst_beg, HeapWord* dst_end, - SpaceId src_space_id, - HeapWord* src_beg, HeapWord* src_end) -{ - log_develop_trace(gc, compaction)( - "Summarizing %d [%s] into %d [%s]: " - "src=" PTR_FORMAT "-" PTR_FORMAT " " - SIZE_FORMAT "-" SIZE_FORMAT " " - "dst=" PTR_FORMAT "-" PTR_FORMAT " " - SIZE_FORMAT "-" SIZE_FORMAT, - src_space_id, space_names[src_space_id], - dst_space_id, space_names[dst_space_id], - p2i(src_beg), p2i(src_end), - _summary_data.addr_to_region_idx(src_beg), - _summary_data.addr_to_region_idx(src_end), - p2i(dst_beg), p2i(dst_end), - _summary_data.addr_to_region_idx(dst_beg), - _summary_data.addr_to_region_idx(dst_end)); -} -#endif // #ifndef PRODUCT - bool PSParallelCompact::reassess_maximum_compaction(bool maximum_compaction, size_t total_live_words, MutableSpace* const old_space, @@ -1114,8 +909,6 @@ void PSParallelCompact::summary_phase(bool maximum_compaction) space->bottom()); const size_t available = pointer_delta(dst_space_end, *new_top_addr); - NOT_PRODUCT(summary_phase_msg(dst_space_id, *new_top_addr, dst_space_end, - SpaceId(id), space->bottom(), space->top());) if (live > 0 && live <= available) { // All the live data will fit. bool done = _summary_data.summarize(_space_info[id].split_info(), @@ -1143,9 +936,6 @@ void PSParallelCompact::summary_phase(bool maximum_compaction) dst_space_id = SpaceId(id); dst_space_end = space->end(); new_top_addr = _space_info[id].new_top_addr(); - NOT_PRODUCT(summary_phase_msg(dst_space_id, - space->bottom(), dst_space_end, - SpaceId(id), next_src_addr, space->top());) done = _summary_data.summarize(_space_info[id].split_info(), next_src_addr, space->top(), nullptr, @@ -1155,10 +945,6 @@ void PSParallelCompact::summary_phase(bool maximum_compaction) assert(*new_top_addr <= space->top(), "usage should not grow"); } } - - log_develop_trace(gc, compaction)("Summary_phase: after final summarization"); - NOT_PRODUCT(print_region_ranges()); - NOT_PRODUCT(print_initial_summary_data(_summary_data, _space_info)); } // This method should contain all heap-specific policy for invoking a full @@ -2126,15 +1912,12 @@ void PSParallelCompact::verify_complete(SpaceId space_id) { const size_t new_top_region = sd.addr_to_region_idx(new_top_addr); const size_t old_top_region = sd.addr_to_region_idx(old_top_addr); - bool issued_a_warning = false; - size_t cur_region; for (cur_region = beg_region; cur_region < new_top_region; ++cur_region) { const RegionData* const c = sd.region(cur_region); if (!c->completed()) { log_warning(gc)("region " SIZE_FORMAT " not filled: destination_count=%u", cur_region, c->destination_count()); - issued_a_warning = true; } } @@ -2143,13 +1926,8 @@ void PSParallelCompact::verify_complete(SpaceId space_id) { if (!c->available()) { log_warning(gc)("region " SIZE_FORMAT " not empty: destination_count=%u", cur_region, c->destination_count()); - issued_a_warning = true; } } - - if (issued_a_warning) { - print_region_ranges(); - } } #endif // #ifdef ASSERT @@ -2450,7 +2228,7 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, MoveAndUpdateClosu if (closure.is_full()) { decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source()); - closure.complete_region(cm, dest_addr, region_ptr); + closure.complete_region(dest_addr, region_ptr); return; } @@ -2493,7 +2271,7 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, MoveAndUpdateClosu if (closure.is_full()) { decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source()); - closure.complete_region(cm, dest_addr, region_ptr); + closure.complete_region(dest_addr, region_ptr); return; } @@ -2526,7 +2304,7 @@ void PSParallelCompact::fill_and_update_shadow_region(ParCompactionManager* cm, region_ptr->shadow_to_normal(); return fill_region(cm, cl, region_idx); } else { - MoveAndUpdateShadowClosure cl(mark_bitmap(), cm, region_idx, shadow_region); + MoveAndUpdateShadowClosure cl(mark_bitmap(), region_idx, shadow_region); return fill_region(cm, cl, region_idx); } } @@ -2603,8 +2381,7 @@ void MoveAndUpdateClosure::copy_partial_obj(size_t partial_obj_size) update_state(words); } -void MoveAndUpdateClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr, - PSParallelCompact::RegionData *region_ptr) { +void MoveAndUpdateClosure::complete_region(HeapWord* dest_addr, PSParallelCompact::RegionData* region_ptr) { assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::NormalRegion, "Region should be finished"); region_ptr->set_completed(); } @@ -2634,8 +2411,7 @@ void MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) { update_state(words); } -void MoveAndUpdateShadowClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr, - PSParallelCompact::RegionData *region_ptr) { +void MoveAndUpdateShadowClosure::complete_region(HeapWord* dest_addr, PSParallelCompact::RegionData* region_ptr) { assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::ShadowRegion, "Region should be shadow"); // Record the shadow region index region_ptr->set_shadow_region(_shadow); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index b30ed0ab98a..93ea7aed78e 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -695,8 +695,6 @@ class PSParallelCompact : AllStatic { virtual bool do_object_b(oop p); }; - friend class PSParallelCompactTest; - private: static STWGCTimer _gc_timer; static ParallelOldTracer _gc_tracer; @@ -755,13 +753,6 @@ class PSParallelCompact : AllStatic { // Add available regions to the stack and draining tasks to the task queue. static void prepare_region_draining_tasks(uint parallel_gc_threads); -#ifndef PRODUCT - // Print generic summary data - static void print_generic_summary_data(ParallelCompactData& summary_data, - HeapWord* const beg_addr, - HeapWord* const end_addr); -#endif // #ifndef PRODUCT - static void fill_range_in_dense_prefix(HeapWord* start, HeapWord* end); public: @@ -857,16 +848,6 @@ class PSParallelCompact : AllStatic { static void print_on_error(outputStream* st); -#ifndef PRODUCT - // Debugging support. - static const char* space_names[last_space_id]; - static void print_region_ranges(); - static void summary_phase_msg(SpaceId dst_space_id, - HeapWord* dst_beg, HeapWord* dst_end, - SpaceId src_space_id, - HeapWord* src_beg, HeapWord* src_end); -#endif // #ifndef PRODUCT - #ifdef ASSERT // Sanity check the new location of a word in the heap. static inline void check_new_location(HeapWord* old_addr, HeapWord* new_addr); @@ -914,8 +895,7 @@ class MoveAndUpdateClosure: public StackObj { // updated. void copy_partial_obj(size_t partial_obj_size); - virtual void complete_region(ParCompactionManager* cm, HeapWord* dest_addr, - PSParallelCompact::RegionData* region_ptr); + virtual void complete_region(HeapWord* dest_addr, PSParallelCompact::RegionData* region_ptr); }; inline void MoveAndUpdateClosure::decrement_words_remaining(size_t words) { @@ -951,11 +931,9 @@ inline void MoveAndUpdateClosure::update_state(size_t words) class MoveAndUpdateShadowClosure: public MoveAndUpdateClosure { inline size_t calculate_shadow_offset(size_t region_idx, size_t shadow_idx); public: - inline MoveAndUpdateShadowClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm, - size_t region, size_t shadow); + inline MoveAndUpdateShadowClosure(ParMarkBitMap* bitmap, size_t region, size_t shadow); - virtual void complete_region(ParCompactionManager* cm, HeapWord* dest_addr, - PSParallelCompact::RegionData* region_ptr); + virtual void complete_region(HeapWord* dest_addr, PSParallelCompact::RegionData* region_ptr); private: size_t _shadow; @@ -969,10 +947,7 @@ inline size_t MoveAndUpdateShadowClosure::calculate_shadow_offset(size_t region_ } inline -MoveAndUpdateShadowClosure::MoveAndUpdateShadowClosure(ParMarkBitMap *bitmap, - ParCompactionManager *cm, - size_t region, - size_t shadow) : +MoveAndUpdateShadowClosure::MoveAndUpdateShadowClosure(ParMarkBitMap* bitmap, size_t region, size_t shadow) : MoveAndUpdateClosure(bitmap, region), _shadow(shadow) { _offset = calculate_shadow_offset(region, shadow); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 65ee52cf4ea..baf565e2862 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -191,7 +191,6 @@ class DefNewGeneration: public Generation { size_t max_survivor_size() const { return _max_survivor_size; } // Thread-local allocation buffers - bool supports_tlab_allocation() const { return true; } size_t tlab_capacity() const; size_t tlab_used() const; size_t unsafe_max_tlab_alloc() const; diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp index 9f73caacb19..5e5aad5d0c1 100644 --- a/src/hotspot/share/gc/serial/generation.hpp +++ b/src/hotspot/share/gc/serial/generation.hpp @@ -114,9 +114,6 @@ class Generation: public CHeapObj { // Like "allocate", but performs any necessary locking internally. virtual HeapWord* par_allocate(size_t word_size, bool is_tlab) = 0; - // Thread-local allocation buffers - virtual bool supports_tlab_allocation() const { return false; } - // Perform a heap collection, attempting to create (at least) enough // space to support an allocation of the given "word_size". If // successful, perform the allocation and return the resulting diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index f4e9e5c6f2e..8dd8a9c0e67 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -468,7 +468,10 @@ bool SerialHeap::do_young_collection(bool clear_soft_refs) { COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers()); - update_gc_stats(_young_gen, false); + // Only update stats for successful young-gc + if (result) { + _old_gen->update_promote_stats(); + } if (should_verify && VerifyAfterGC) { Universe::verify("After GC"); @@ -761,6 +764,8 @@ void SerialHeap::do_full_collection_no_gc_locker(bool clear_all_soft_refs) { // Need to clear claim bits for the next mark. ClassLoaderDataGraph::clear_claimed_marks(); + _old_gen->update_promote_stats(); + // Resize the metaspace capacity after full collections MetaspaceGC::compute_new_size(); @@ -828,20 +833,15 @@ bool SerialHeap::block_is_obj(const HeapWord* addr) const { } size_t SerialHeap::tlab_capacity(Thread* thr) const { - assert(!_old_gen->supports_tlab_allocation(), "Old gen supports TLAB allocation?!"); - assert(_young_gen->supports_tlab_allocation(), "Young gen doesn't support TLAB allocation?!"); + // Only young-gen supports tlab allocation. return _young_gen->tlab_capacity(); } size_t SerialHeap::tlab_used(Thread* thr) const { - assert(!_old_gen->supports_tlab_allocation(), "Old gen supports TLAB allocation?!"); - assert(_young_gen->supports_tlab_allocation(), "Young gen doesn't support TLAB allocation?!"); return _young_gen->tlab_used(); } size_t SerialHeap::unsafe_max_tlab_alloc(Thread* thr) const { - assert(!_old_gen->supports_tlab_allocation(), "Old gen supports TLAB allocation?!"); - assert(_young_gen->supports_tlab_allocation(), "Young gen doesn't support TLAB allocation?!"); return _young_gen->unsafe_max_tlab_alloc(); } diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 4b606099bf3..0817c6e9eb3 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -208,11 +208,6 @@ class SerialHeap : public CollectedHeap { size_t requested_size, size_t* actual_size) override; - // Update the gc statistics for each generation. - void update_gc_stats(Generation* current_generation, bool full) { - _old_gen->update_gc_stats(current_generation, full); - } - void prepare_for_verify() override; void verify(VerifyOption option) override; diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 9602553a6f3..fedded6de08 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -357,25 +357,15 @@ void TenuredGeneration::compute_new_size() { " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity()); } -void TenuredGeneration::update_gc_stats(Generation* current_generation, - bool full) { - // If the young generation has been collected, gather any statistics - // that are of interest at this point. - bool current_is_young = SerialHeap::heap()->is_young_gen(current_generation); - if (!full && current_is_young) { - // Calculate size of data promoted from the young generation - // before doing the collection. - size_t used_before_gc = used(); - - // If the young gen collection was skipped, then the - // number of promoted bytes will be 0 and adding it to the - // average will incorrectly lessen the average. It is, however, - // also possible that no promotion was needed. - if (used_before_gc >= _used_at_prologue) { - size_t promoted_in_bytes = used_before_gc - _used_at_prologue; - _avg_promoted->sample(promoted_in_bytes); - } +void TenuredGeneration::update_promote_stats() { + size_t used_after_gc = used(); + size_t promoted_in_bytes; + if (used_after_gc > _used_at_prologue) { + promoted_in_bytes = used_after_gc - _used_at_prologue; + } else { + promoted_in_bytes = 0; } + _avg_promoted->sample(promoted_in_bytes); } void TenuredGeneration::update_counters() { diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index cfc18b92f2a..dc2730eaf41 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -143,7 +143,7 @@ class TenuredGeneration: public Generation { bool should_allocate(size_t word_size, bool is_tlab) { bool result = false; size_t overflow_limit = (size_t)1 << (BitsPerSize_t - LogHeapWordSize); - if (!is_tlab || supports_tlab_allocation()) { + if (!is_tlab) { result = (word_size > 0) && (word_size < overflow_limit); } return result; @@ -154,7 +154,7 @@ class TenuredGeneration: public Generation { // Statistics - void update_gc_stats(Generation* current_generation, bool full); + void update_promote_stats(); // Returns true if promotions of the specified amount are // likely to succeed without a promotion failure. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp index 20954156b9e..7b30e1ecbac 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetNMethod.cpp @@ -36,13 +36,19 @@ #include "runtime/threadWXSetters.inline.hpp" bool ShenandoahBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { + if (!is_armed(nm)) { + // Some other thread got here first and healed the oops + // and disarmed the nmethod. No need to continue. + return true; + } + ShenandoahReentrantLock* lock = ShenandoahNMethod::lock_for_nmethod(nm); assert(lock != nullptr, "Must be"); ShenandoahReentrantLocker locker(lock); if (!is_armed(nm)) { - // Some other thread got here first and healed the oops - // and disarmed the nmethod. + // Some other thread managed to complete while we were + // waiting for lock. No need to continue. return true; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index e514d41369f..b8baf6b3ebf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -114,7 +114,7 @@ "to learn application and GC performance.") \ range(0,100) \ \ - product(uintx, ShenandoahImmediateThreshold, 90, EXPERIMENTAL, \ + product(uintx, ShenandoahImmediateThreshold, 70, EXPERIMENTAL, \ "The cycle may shortcut when enough garbage can be reclaimed " \ "from the immediate garbage (completely garbage regions). " \ "In percents of total garbage found. Setting this threshold " \ diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index 4c95d656e25..ed441eca851 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -87,7 +87,7 @@ class Chunk { class Arena : public CHeapObjBase { public: - enum class Tag { + enum class Tag : uint8_t { tag_other = 0, tag_ra, // resource area tag_ha, // handle area @@ -101,6 +101,7 @@ class Arena : public CHeapObjBase { MEMFLAGS _flags; // Memory tracking flags const Tag _tag; + uint32_t _init_size; Chunk* _first; // First chunk Chunk* _chunk; // current chunk char* _hwm; // High water mark diff --git a/src/hotspot/share/nmt/mallocHeader.cpp b/src/hotspot/share/nmt/mallocHeader.cpp index a125ba416b1..d5a7b689c2a 100644 --- a/src/hotspot/share/nmt/mallocHeader.cpp +++ b/src/hotspot/share/nmt/mallocHeader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -64,7 +64,3 @@ void MallocHeader::print_block_on_error(outputStream* st, address bad_address) c os::print_hex_dump(st, from1, to2, 1); } } - -bool MallocHeader::get_stack(NativeCallStack& stack) const { - return MallocSiteTable::access_stack(stack, _mst_marker); -} diff --git a/src/hotspot/share/nmt/mallocHeader.hpp b/src/hotspot/share/nmt/mallocHeader.hpp index 6d847a22de3..9f9f7f97ea7 100644 --- a/src/hotspot/share/nmt/mallocHeader.hpp +++ b/src/hotspot/share/nmt/mallocHeader.hpp @@ -130,7 +130,6 @@ class MallocHeader { inline size_t size() const { return _size; } inline MEMFLAGS flags() const { return _flags; } inline uint32_t mst_marker() const { return _mst_marker; } - bool get_stack(NativeCallStack& stack) const; // Return the necessary data to deaccount the block with NMT. FreeInfo free_info() { diff --git a/src/hotspot/share/nmt/mallocSiteTable.hpp b/src/hotspot/share/nmt/mallocSiteTable.hpp index 47fe82b590a..ae9266f5369 100644 --- a/src/hotspot/share/nmt/mallocSiteTable.hpp +++ b/src/hotspot/share/nmt/mallocSiteTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,8 +131,8 @@ class MallocSiteTable : AllStatic { // Access and copy a call stack from this table. Shared lock should be // acquired before access the entry. - static inline bool access_stack(NativeCallStack& stack, uint32_t marker) { - MallocSite* site = malloc_site(marker); + static inline bool access_stack(NativeCallStack& stack, const MallocHeader& header) { + MallocSite* site = malloc_site(header.mst_marker()); if (site != nullptr) { stack = *site->call_stack(); return true; diff --git a/src/hotspot/share/nmt/mallocTracker.cpp b/src/hotspot/share/nmt/mallocTracker.cpp index ab323b3bae6..021ce5d1332 100644 --- a/src/hotspot/share/nmt/mallocTracker.cpp +++ b/src/hotspot/share/nmt/mallocTracker.cpp @@ -299,7 +299,7 @@ bool MallocTracker::print_pointer_information(const void* p, outputStream* st) { block->size(), NMTUtil::flag_to_enum_name(block->flags())); if (MemTracker::tracking_level() == NMT_detail) { NativeCallStack ncs; - if (block->get_stack(ncs)) { + if (MallocSiteTable::access_stack(ncs, *block)) { ncs.print_on(st); st->cr(); } diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp index 1dc4e58169d..bd2f38acdd0 100644 --- a/src/hotspot/share/nmt/memReporter.cpp +++ b/src/hotspot/share/nmt/memReporter.cpp @@ -31,7 +31,14 @@ #include "nmt/memoryFileTracker.hpp" #include "nmt/threadStackTracker.hpp" #include "nmt/virtualMemoryTracker.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +#define INDENT_BY(num_chars, CODE) { \ + streamIndentor si(out, num_chars); \ + { CODE } \ +} // Diff two counters, express them as signed, with range checks static ssize_t counter_diff(size_t c1, size_t c2) { @@ -43,6 +50,9 @@ static ssize_t counter_diff(size_t c1, size_t c2) { return c1 - c2; } +MemReporterBase::MemReporterBase(outputStream* out, size_t scale) : + _scale(scale), _output(out), _auto_indentor(out) {} + size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) { return malloc->malloc_size() + malloc->arena_size() + vm->reserved(); } @@ -105,27 +115,15 @@ void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed, si } } -void MemReporterBase::print_malloc_line(const MemoryCounter* c) const { - output()->print("%28s", " "); - print_malloc(c); - output()->print_cr(" "); -} - -void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committed, size_t peak) const { - output()->print("%28s", " "); - print_virtual_memory(reserved, committed, peak); - output()->print_cr(" "); -} - -void MemReporterBase::print_arena_line(const MemoryCounter* c) const { +void MemReporterBase::print_arena(const MemoryCounter* c) const { const char* scale = current_scale(); outputStream* out = output(); const size_t amount = c->size(); const size_t count = c->count(); - out->print("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", "", - amount_in_current_scale(amount), scale, count); + out->print("(arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", + amount_in_current_scale(amount), scale, count); size_t pk_amount = c->peak_size(); if (pk_amount == amount) { @@ -135,8 +133,6 @@ void MemReporterBase::print_arena_line(const MemoryCounter* c) const { out->print(" (peak=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", amount_in_current_scale(pk_amount), scale, pk_count); } - - out->cr(); } void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const { @@ -156,7 +152,9 @@ void MemSummaryReporter::report() { size_t total_committed_amount = total_malloced_bytes + total_mmap_committed_bytes; // Overall total - out->print_cr("\nNative Memory Tracking:\n"); + out->cr(); + out->print_cr("Native Memory Tracking:"); + out->cr(); if (scale() > 1) { out->print_cr("(Omitting categories weighting less than 1%s)", current_scale()); @@ -166,13 +164,15 @@ void MemSummaryReporter::report() { out->print("Total: "); print_total(total_reserved_amount, total_committed_amount); out->cr(); - out->print_cr(" malloc: " SIZE_FORMAT "%s #" SIZE_FORMAT ", peak=" SIZE_FORMAT "%s #" SIZE_FORMAT, - amount_in_current_scale(total_malloced_bytes), current_scale(), - _malloc_snapshot->total_count(), - amount_in_current_scale(_malloc_snapshot->total_peak()), - current_scale(), _malloc_snapshot->total_peak_count()); - out->print(" mmap: "); - print_total(total_mmap_reserved_bytes, total_mmap_committed_bytes); + INDENT_BY(7, + out->print_cr("malloc: " SIZE_FORMAT "%s #" SIZE_FORMAT ", peak=" SIZE_FORMAT "%s #" SIZE_FORMAT, + amount_in_current_scale(total_malloced_bytes), current_scale(), + _malloc_snapshot->total_count(), + amount_in_current_scale(_malloc_snapshot->total_peak()), + current_scale(), _malloc_snapshot->total_peak_count()); + out->print("mmap: "); + print_total(total_mmap_reserved_bytes, total_mmap_committed_bytes); + ) out->cr(); out->cr(); @@ -218,7 +218,8 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, outputStream* out = output(); const char* scale = current_scale(); - out->print("-%26s (", NMTUtil::flag_to_name(flag)); + constexpr int indent = 28; + out->print("-%*s (", indent - 2, NMTUtil::flag_to_name(flag)); print_total(reserved_amount, committed_amount); #if INCLUDE_CDS if (flag == mtClassShared) { @@ -229,39 +230,43 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, #endif out->print_cr(")"); + streamIndentor si(out, indent); + if (flag == mtClass) { // report class count - out->print_cr("%27s (classes #" SIZE_FORMAT ")", - " ", (_instance_class_count + _array_class_count)); - out->print_cr("%27s ( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")", - " ", _instance_class_count, _array_class_count); + out->print_cr("(classes #" SIZE_FORMAT ")", (_instance_class_count + _array_class_count)); + out->print_cr("( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")", + _instance_class_count, _array_class_count); } else if (flag == mtThread) { const VirtualMemory* thread_stack_usage = _vm_snapshot->by_type(mtThreadStack); // report thread count - out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count()); - out->print("%27s (stack: ", " "); + out->print_cr("(threads #" SIZE_FORMAT ")", ThreadStackTracker::thread_count()); + out->print("(stack: "); print_total(thread_stack_usage->reserved(), thread_stack_usage->committed(), thread_stack_usage->peak_size()); out->print_cr(")"); } // report malloc'd memory if (amount_in_current_scale(MAX2(malloc_memory->malloc_size(), pk_malloc)) > 0) { - print_malloc_line(malloc_memory->malloc_counter()); + print_malloc(malloc_memory->malloc_counter()); + out->cr(); } if (amount_in_current_scale(MAX2(virtual_memory->reserved(), pk_vm)) > 0) { - print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed(), virtual_memory->peak_size()); + print_virtual_memory(virtual_memory->reserved(), virtual_memory->committed(), virtual_memory->peak_size()); + out->cr(); } if (amount_in_current_scale(MAX2(malloc_memory->arena_size(), pk_arena)) > 0) { - print_arena_line(malloc_memory->arena_counter()); + print_arena(malloc_memory->arena_counter()); + out->cr(); } if (flag == mtNMT && amount_in_current_scale(_malloc_snapshot->malloc_overhead()) > 0) { - out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ", - amount_in_current_scale(_malloc_snapshot->malloc_overhead()), scale); + out->print_cr("(tracking overhead=" SIZE_FORMAT "%s)", + amount_in_current_scale(_malloc_snapshot->malloc_overhead()), scale); } else if (flag == mtClass) { // Metadata information report_metadata(Metaspace::NonClassType); @@ -269,7 +274,7 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, report_metadata(Metaspace::ClassType); } } - out->print_cr(" "); + out->cr(); } void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const { @@ -292,13 +297,13 @@ void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const { size_t waste = stats.committed() - stats.used(); float waste_percentage = stats.committed() > 0 ? (((float)waste * 100)/(float)stats.committed()) : 0.0f; - out->print_cr("%27s ( %s)", " ", name); - out->print("%27s ( ", " "); + out->print_cr("( %s)", name); + out->print("( "); print_total(stats.reserved(), stats.committed()); out->print_cr(")"); - out->print_cr("%27s ( used=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(stats.used()), scale); - out->print_cr("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%)", " ", amount_in_current_scale(waste), - scale, waste_percentage); + out->print_cr("( used=" SIZE_FORMAT "%s)", amount_in_current_scale(stats.used()), scale); + out->print_cr("( waste=" SIZE_FORMAT "%s =%2.2f%%)", amount_in_current_scale(waste), + scale, waste_percentage); } void MemDetailReporter::report_detail() { @@ -333,12 +338,15 @@ int MemDetailReporter::report_malloc_sites() { } const NativeCallStack* stack = malloc_site->call_stack(); stack->print_on(out); - out->print("%29s", " "); MEMFLAGS flag = malloc_site->flag(); assert(NMTUtil::flag_is_valid(flag) && flag != mtNone, "Must have a valid memory type"); - print_malloc(malloc_site->counter(), flag); - out->print_cr("\n"); + INDENT_BY(29, + out->print("("); + print_malloc(malloc_site->counter(), flag); + out->print_cr(")"); + ) + out->cr(); } return num_omitted; } @@ -350,6 +358,7 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() { if (virtual_memory_itr.is_empty()) return 0; outputStream* out = output(); + const VirtualMemoryAllocationSite* virtual_memory_site; int num_omitted = 0; while ((virtual_memory_site = virtual_memory_itr.next()) != nullptr) { @@ -366,13 +375,16 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() { } const NativeCallStack* stack = virtual_memory_site->call_stack(); stack->print_on(out); - out->print("%28s (", " "); - print_total(virtual_memory_site->reserved(), virtual_memory_site->committed()); - MEMFLAGS flag = virtual_memory_site->flag(); - if (flag != mtNone) { - out->print(" Type=%s", NMTUtil::flag_to_name(flag)); - } - out->print_cr(")\n"); + INDENT_BY(29, + out->print("("); + print_total(virtual_memory_site->reserved(), virtual_memory_site->committed()); + const MEMFLAGS flag = virtual_memory_site->flag(); + if (flag != mtNone) { + out->print(" Type=%s", NMTUtil::flag_to_name(flag)); + } + out->print_cr(")"); + ) + out->cr(); } return num_omitted; } @@ -409,14 +421,14 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* const NativeCallStack* stack = reserved_rgn->call_stack(); bool all_committed = reserved_rgn->size() == reserved_rgn->committed_size(); const char* region_type = (all_committed ? "reserved and committed" : "reserved"); - out->print_cr(" "); + out->cr(); print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size()); out->print(" for %s", NMTUtil::flag_to_name(reserved_rgn->flag())); if (stack->is_empty()) { - out->print_cr(" "); + out->cr(); } else { out->print_cr(" from"); - stack->print_on(out, 4); + INDENT_BY(4, stack->print_on(out);) } if (all_committed) { @@ -437,20 +449,33 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* // Don't report if size is too small if (amount_in_current_scale(committed_rgn->size()) == 0) continue; stack = committed_rgn->call_stack(); - out->print("\n\t"); - print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size()); - if (stack->is_empty()) { - out->print_cr(" "); - } else { - out->print_cr(" from"); - stack->print_on(out, 12); - } + out->cr(); + INDENT_BY(8, + print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size()); + if (stack->is_empty()) { + out->cr(); + } else { + out->print_cr(" from"); + INDENT_BY(4, stack->print_on(out);) + } + ) + } +} + +void MemDetailReporter::report_memory_file_allocations() { + stringStream st; + { + MemoryFileTracker::Instance::Locker lock; + MemoryFileTracker::Instance::print_all_reports_on(&st, scale()); } + output()->print_raw(st.freeze()); } void MemSummaryDiffReporter::report_diff() { outputStream* out = output(); - out->print_cr("\nNative Memory Tracking:\n"); + out->cr(); + out->print_cr("Native Memory Tracking:"); + out->cr(); if (scale() > 1) { out->print_cr("(Omitting categories weighting less than 1%s)", current_scale()); @@ -463,7 +488,8 @@ void MemSummaryDiffReporter::report_diff() { _current_baseline.total_committed_memory(), _early_baseline.total_reserved_memory(), _early_baseline.total_committed_memory()); - out->print_cr("\n"); + out->cr(); + out->cr(); // Summary diff by memory type for (int index = 0; index < mt_number_of_types; index ++) { @@ -548,6 +574,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, outputStream* out = output(); const char* scale = current_scale(); + constexpr int indent = 28; // Total reserved and committed memory in current baseline size_t current_reserved_amount = reserved_total (current_malloc, current_vm); @@ -581,15 +608,17 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, diff_in_current_scale(current_reserved_amount, early_reserved_amount) != 0) { // print summary line - out->print("-%26s (", NMTUtil::flag_to_name(flag)); + out->print("-%*s (", indent - 2, NMTUtil::flag_to_name(flag)); print_virtual_memory_diff(current_reserved_amount, current_committed_amount, early_reserved_amount, early_committed_amount); out->print_cr(")"); + streamIndentor si(out, indent); + // detail lines if (flag == mtClass) { // report class count - out->print("%27s (classes #" SIZE_FORMAT "", " ", _current_baseline.class_count()); + out->print("(classes #" SIZE_FORMAT, _current_baseline.class_count()); const ssize_t class_count_diff = counter_diff(_current_baseline.class_count(), _early_baseline.class_count()); if (class_count_diff != 0) { @@ -597,7 +626,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, } out->print_cr(")"); - out->print("%27s ( instance classes #" SIZE_FORMAT, " ", _current_baseline.instance_class_count()); + out->print("( instance classes #" SIZE_FORMAT, _current_baseline.instance_class_count()); const ssize_t instance_class_count_diff = counter_diff(_current_baseline.instance_class_count(), _early_baseline.instance_class_count()); if (instance_class_count_diff != 0) { @@ -613,14 +642,14 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, } else if (flag == mtThread) { // report thread count - out->print("%27s (threads #" SIZE_FORMAT "", " ", _current_baseline.thread_count()); + out->print("(threads #" SIZE_FORMAT, _current_baseline.thread_count()); const ssize_t thread_count_diff = counter_diff(_current_baseline.thread_count(), _early_baseline.thread_count()); if (thread_count_diff != 0) { out->print(" " SSIZE_PLUS_FORMAT, thread_count_diff); } out->print_cr(")"); - out->print("%27s (stack: ", " "); + out->print("(stack: "); // report thread stack const VirtualMemory* current_thread_stack = _current_baseline.virtual_memory(mtThreadStack); @@ -638,7 +667,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, size_t early_malloc_amount = early_malloc->malloc_size(); if (amount_in_current_scale(current_malloc_amount) > 0 || diff_in_current_scale(current_malloc_amount, early_malloc_amount) != 0) { - out->print("%28s(", " "); + out->print("("); print_malloc_diff(current_malloc_amount, (flag == mtChunk) ? 0 : current_malloc->malloc_count(), early_malloc_amount, early_malloc->malloc_count(), mtNone); out->print_cr(")"); @@ -647,7 +676,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, // Report virtual memory if (amount_in_current_scale(current_vm->reserved()) > 0 || diff_in_current_scale(current_vm->reserved(), early_vm->reserved()) != 0) { - out->print("%27s (mmap: ", " "); + out->print("(mmap: "); print_virtual_memory_diff(current_vm->reserved(), current_vm->committed(), early_vm->reserved(), early_vm->committed()); out->print_cr(")"); @@ -656,7 +685,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, // Report arena memory if (amount_in_current_scale(current_malloc->arena_size()) > 0 || diff_in_current_scale(current_malloc->arena_size(), early_malloc->arena_size()) != 0) { - out->print("%28s(", " "); + out->print("("); print_arena_diff(current_malloc->arena_size(), current_malloc->arena_count(), early_malloc->arena_size(), early_malloc->arena_count()); out->print_cr(")"); @@ -667,8 +696,8 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, size_t current_tracking_overhead = amount_in_current_scale(_current_baseline.malloc_tracking_overhead()); size_t early_tracking_overhead = amount_in_current_scale(_early_baseline.malloc_tracking_overhead()); - out->print("%27s (tracking overhead=" SIZE_FORMAT "%s", " ", - amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale); + out->print("(tracking overhead=" SIZE_FORMAT "%s", + amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale); int64_t overhead_diff = diff_in_current_scale(_current_baseline.malloc_tracking_overhead(), _early_baseline.malloc_tracking_overhead()); @@ -679,7 +708,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, } else if (flag == mtClass) { print_metaspace_diff(current_ms, early_ms); } - out->print_cr(" "); + out->cr(); } } @@ -697,8 +726,8 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header, outputStream* out = output(); const char* scale = current_scale(); - out->print_cr("%27s: ( %s)", " ", header); - out->print("%27s ( ", " "); + out->print_cr("( %s)", header); + out->print("( "); print_virtual_memory_diff(current_stats.reserved(), current_stats.committed(), early_stats.reserved(), @@ -713,8 +742,8 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header, int64_t diff_waste = diff_in_current_scale(current_waste, early_waste); // Diff used - out->print("%27s ( used=" SIZE_FORMAT "%s", " ", - amount_in_current_scale(current_stats.used()), scale); + out->print("( used=" SIZE_FORMAT "%s", + amount_in_current_scale(current_stats.used()), scale); if (diff_used != 0) { out->print(" " INT64_PLUS_FORMAT "%s", diff_used, scale); } @@ -723,8 +752,8 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header, // Diff waste const float waste_percentage = current_stats.committed() == 0 ? 0.0f : ((float)current_waste * 100.0f) / (float)current_stats.committed(); - out->print("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%", " ", - amount_in_current_scale(current_waste), scale, waste_percentage); + out->print("( waste=" SIZE_FORMAT "%s =%2.2f%%", + amount_in_current_scale(current_waste), scale, waste_percentage); if (diff_waste != 0) { out->print(" " INT64_PLUS_FORMAT "%s", diff_waste, scale); } @@ -841,11 +870,13 @@ void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_ } stack->print_on(out); - out->print("%28s (", " "); - print_malloc_diff(current_size, current_count, - early_size, early_count, flags); + INDENT_BY(28, + out->print("("); + print_malloc_diff(current_size, current_count, early_size, early_count, flags); + out->print_cr(")"); + ) + out->cr(); - out->print_cr(")\n"); } @@ -874,22 +905,14 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac } stack->print_on(out); - out->print("%28s (mmap: ", " "); - print_virtual_memory_diff(current_reserved, current_committed, - early_reserved, early_committed); - - if (flag != mtNone) { - out->print(" Type=%s", NMTUtil::flag_to_name(flag)); - } - - out->print_cr(")\n"); + INDENT_BY(28, + out->print("(mmap: "); + print_virtual_memory_diff(current_reserved, current_committed, early_reserved, early_committed); + if (flag != mtNone) { + out->print(" Type=%s", NMTUtil::flag_to_name(flag)); + } + out->print_cr(")"); + ) + out->cr(); } -void MemDetailReporter::report_memory_file_allocations() { - stringStream st; - { - MemoryFileTracker::Instance::Locker lock; - MemoryFileTracker::Instance::print_all_reports_on(&st, scale()); - } - output()->print_raw(st.freeze()); -} diff --git a/src/hotspot/share/nmt/memReporter.hpp b/src/hotspot/share/nmt/memReporter.hpp index 9355704531c..c10a9979508 100644 --- a/src/hotspot/share/nmt/memReporter.hpp +++ b/src/hotspot/share/nmt/memReporter.hpp @@ -38,15 +38,14 @@ class MemReporterBase : public StackObj { private: const size_t _scale; // report in this scale outputStream* const _output; // destination + StreamAutoIndentor _auto_indentor; public: // Default scale to use if no scale given. static const size_t default_scale = K; - MemReporterBase(outputStream* out, size_t scale = default_scale) : - _scale(scale), _output(out) - {} + MemReporterBase(outputStream* out, size_t scale = default_scale); // Helper functions // Calculate total reserved and committed amount @@ -109,10 +108,7 @@ class MemReporterBase : public StackObj { void print_total(size_t reserved, size_t committed, size_t peak = 0) const; void print_malloc(const MemoryCounter* c, MEMFLAGS flag = mtNone) const; void print_virtual_memory(size_t reserved, size_t committed, size_t peak) const; - - void print_malloc_line(const MemoryCounter* c) const; - void print_virtual_memory_line(size_t reserved, size_t committed, size_t peak) const; - void print_arena_line(const MemoryCounter* c) const; + void print_arena(const MemoryCounter* c) const; void print_virtual_memory_region(const char* type, address base, size_t size) const; }; diff --git a/src/hotspot/share/nmt/memoryFileTracker.cpp b/src/hotspot/share/nmt/memoryFileTracker.cpp index a92f8e9f538..25f2667e5c3 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.cpp +++ b/src/hotspot/share/nmt/memoryFileTracker.cpp @@ -92,7 +92,10 @@ void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* st NMTUtil::amount_in_scale(end_addr - start_addr, scale), NMTUtil::scale_name(scale), NMTUtil::flag_to_name(prev->val().out.flag())); - _stack_storage.get(prev->val().out.stack()).print_on(stream, 4); + { + streamIndentor si(stream, 4); + _stack_storage.get(prev->val().out.stack()).print_on(stream); + } stream->cr(); } prev = current; diff --git a/src/hotspot/share/oops/klassVtable.hpp b/src/hotspot/share/oops/klassVtable.hpp index f986139d3f4..349a859a17f 100644 --- a/src/hotspot/share/oops/klassVtable.hpp +++ b/src/hotspot/share/oops/klassVtable.hpp @@ -54,6 +54,9 @@ class klassVtable { klassVtable(Klass* klass, void* base, int length) : _klass(klass) { _tableOffset = int((address)base - (address)klass); _length = length; +#ifndef PRODUCT + _verify_count = 0; +#endif } // accessors diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index 08dfc1fe95a..af19d59f281 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1333,21 +1333,6 @@ void MethodData::init() { _failed_speculations = nullptr; #endif -#if INCLUDE_RTM_OPT - _rtm_state = NoRTM; // No RTM lock eliding by default - if (UseRTMLocking && - !CompilerOracle::has_option(mh, CompileCommandEnum::NoRTMLockEliding)) { - if (CompilerOracle::has_option(mh, CompileCommandEnum::UseRTMLockEliding) || !UseRTMDeopt) { - // Generate RTM lock eliding code without abort ratio calculation code. - _rtm_state = UseRTM; - } else if (UseRTMDeopt) { - // Generate RTM lock eliding code and include abort ratio calculation - // code if UseRTMDeopt is on. - _rtm_state = ProfileRTM; - } - } -#endif - // Initialize escape flags. clear_escape_info(); } diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index 4fa42eec960..b6e2a1c9652 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -2070,11 +2070,6 @@ class MethodData : public Metadata { int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog -#if INCLUDE_RTM_OPT - // State of RTM code generation during compilation of the method - int _rtm_state; -#endif - // Number of loops and blocks is computed when compiling the first // time with C1. It is used to determine if method is trivial. short _num_loops; @@ -2270,22 +2265,6 @@ class MethodData : public Metadata { } #endif -#if INCLUDE_RTM_OPT - int rtm_state() const { - return _rtm_state; - } - void set_rtm_state(RTMState rstate) { - _rtm_state = (int)rstate; - } - void atomic_set_rtm_state(RTMState rstate) { - Atomic::store(&_rtm_state, (int)rstate); - } - - static ByteSize rtm_state_offset() { - return byte_offset_of(MethodData, _rtm_state); - } -#endif - void set_would_profile(bool p) { _would_profile = p ? profile : no_profile; } bool would_profile() const { return _would_profile != no_profile; } diff --git a/src/hotspot/share/oops/symbol.hpp b/src/hotspot/share/oops/symbol.hpp index 008b979492d..3b3f1366203 100644 --- a/src/hotspot/share/oops/symbol.hpp +++ b/src/hotspot/share/oops/symbol.hpp @@ -122,7 +122,7 @@ class Symbol : public MetaspaceObj { }; static int byte_size(int length) { - // minimum number of natural words needed to hold these bits (no non-heap version) + // minimum number of bytes needed to hold these bits (no non-heap version) return (int)(sizeof(Symbol) + (length > 2 ? length - 2 : 0)); } static int size(int length) { @@ -146,8 +146,6 @@ class Symbol : public MetaspaceObj { int size() const { return size(utf8_length()); } int byte_size() const { return byte_size(utf8_length()); }; - // length without the _body - size_t effective_length() const { return (size_t)byte_size() - sizeof(Symbol); } // Symbols should be stored in the read-only region of CDS archive. static bool is_read_only_by_default() { return true; } diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index f2445e4f136..7288533cd33 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -457,9 +457,6 @@ develop(bool, PrintLockStatistics, false, \ "Print precise statistics on the dynamic lock usage") \ \ - product(bool, PrintPreciseRTMLockingStatistics, false, DIAGNOSTIC, \ - "Print per-lock-site statistics of rtm locking in JVM") \ - \ develop(bool, PrintEliminateLocks, false, \ "Print out when locks are eliminated") \ \ diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index db6cb817d77..7908f21de10 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -269,7 +269,6 @@ macro(Opaque1) macro(OpaqueLoopInit) macro(OpaqueLoopStride) macro(OpaqueZeroTripGuard) -macro(Opaque3) macro(Opaque4) macro(OpaqueInitializedAssertionPredicate) macro(ProfileBoolean) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 25c7ced8aeb..3687bc70efd 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -713,10 +713,9 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, set_print_intrinsics(directive->PrintIntrinsicsOption); set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it - if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) { + if (ProfileTraps) { // Make sure the method being compiled gets its own MDO, // so we can at least track the decompile_count(). - // Need MDO to record RTM code generation state. method()->ensure_method_data(); } @@ -1075,25 +1074,8 @@ void Compile::Init(bool aliasing) { set_use_cmove(UseCMoveUnconditionally /* || do_vector_loop()*/); //TODO: consider do_vector_loop() mandate use_cmove unconditionally NOT_PRODUCT(if (use_cmove() && Verbose && has_method()) {tty->print("Compile::Init: use CMove without profitability tests for method %s\n", method()->name()->as_quoted_ascii());}) - set_rtm_state(NoRTM); // No RTM lock eliding by default _max_node_limit = _directive->MaxNodeLimitOption; -#if INCLUDE_RTM_OPT - if (UseRTMLocking && has_method() && (method()->method_data_or_null() != nullptr)) { - int rtm_state = method()->method_data()->rtm_state(); - if (method_has_option(CompileCommandEnum::NoRTMLockEliding) || ((rtm_state & NoRTM) != 0)) { - // Don't generate RTM lock eliding code. - set_rtm_state(NoRTM); - } else if (method_has_option(CompileCommandEnum::UseRTMLockEliding) || ((rtm_state & UseRTM) != 0) || !UseRTMDeopt) { - // Generate RTM lock eliding code without abort ratio calculation code. - set_rtm_state(UseRTM); - } else if (UseRTMDeopt) { - // Generate RTM lock eliding code and include abort ratio calculation - // code if UseRTMDeopt is on. - set_rtm_state(ProfileRTM); - } - } -#endif if (VM_Version::supports_fast_class_init_checks() && has_method() && !is_osr_compilation() && method()->needs_clinit_barrier()) { set_clinit_barrier_on_entry(true); } @@ -3222,7 +3204,6 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f frc.inc_double_count(); break; case Op_Opaque1: // Remove Opaque Nodes before matching - case Op_Opaque3: n->subsume_by(n->in(1), this); break; case Op_CallStaticJava: diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index e1d9b61f7f8..7c998d59d37 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -355,7 +355,6 @@ class Compile : public Phase { bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. bool _has_monitors; // Metadata transfered to nmethod to enable Continuations lock-detection fastpath bool _clinit_barrier_on_entry; // True if clinit barrier is needed on nmethod entry - RTMState _rtm_state; // State of Restricted Transactional Memory usage int _loop_opts_cnt; // loop opts round uint _stress_seed; // Seed for stress testing @@ -667,10 +666,6 @@ class Compile : public Phase { void set_print_inlining(bool z) { _print_inlining = z; } bool print_intrinsics() const { return _print_intrinsics; } void set_print_intrinsics(bool z) { _print_intrinsics = z; } - RTMState rtm_state() const { return _rtm_state; } - void set_rtm_state(RTMState s) { _rtm_state = s; } - bool use_rtm() const { return (_rtm_state & NoRTM) == 0; } - bool profile_rtm() const { return _rtm_state == ProfileRTM; } uint max_node_limit() const { return (uint)_max_node_limit; } void set_max_node_limit(uint n) { _max_node_limit = n; } bool clinit_barrier_on_entry() { return _clinit_barrier_on_entry; } diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 5630ee0228d..8a80392d5c7 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2197,6 +2197,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "bigIntegerRightShiftWorker") == 0 || strcmp(call->as_CallLeaf()->_name, "bigIntegerLeftShiftWorker") == 0 || strcmp(call->as_CallLeaf()->_name, "vectorizedMismatch") == 0 || + strcmp(call->as_CallLeaf()->_name, "stringIndexOf") == 0 || strcmp(call->as_CallLeaf()->_name, "arraysort_stub") == 0 || strcmp(call->as_CallLeaf()->_name, "array_partition_stub") == 0 || strcmp(call->as_CallLeaf()->_name, "get_class_id_intrinsic") == 0 || diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 614a4123c0d..134d21e5bad 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -3491,9 +3491,6 @@ FastLockNode* GraphKit::shared_lock(Node* obj) { FastLockNode * flock = _gvn.transform(new FastLockNode(0, obj, box) )->as_FastLock(); - // Create the rtm counters for this fast lock if needed. - flock->create_rtm_lock_counter(sync_jvms()); // sync_jvms used to get current bci - // Add monitor to debug info for the slow path. If we block inside the // slow path and de-opt, we need the monitor hanging around map()->push_monitor( flock ); diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 33c2d7309d0..b3253a817a4 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1205,6 +1205,9 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) { Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE); Node* tgt_count = load_array_length(tgt); + Node* result = nullptr; + bool call_opt_stub = (StubRoutines::_string_indexof_array[ae] != nullptr); + if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) { // Divide src size by 2 if String is UTF16 encoded src_count = _gvn.transform(new RShiftINode(src_count, intcon(1))); @@ -1214,7 +1217,16 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) { tgt_count = _gvn.transform(new RShiftINode(tgt_count, intcon(1))); } - Node* result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, result_rgn, result_phi, ae); + if (call_opt_stub) { + Node* call = make_runtime_call(RC_LEAF, OptoRuntime::string_IndexOf_Type(), + StubRoutines::_string_indexof_array[ae], + "stringIndexOf", TypePtr::BOTTOM, src_start, + src_count, tgt_start, tgt_count); + result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + } else { + result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, + result_rgn, result_phi, ae); + } if (result != nullptr) { result_phi->init_req(3, result); result_rgn->init_req(3, control()); @@ -1226,7 +1238,7 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) { return true; } -//-----------------------------inline_string_indexOf----------------------- +//-----------------------------inline_string_indexOfI----------------------- bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) { if (too_many_traps(Deoptimization::Reason_intrinsic)) { return false; @@ -1234,6 +1246,7 @@ bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) { if (!Matcher::match_rule_supported(Op_StrIndexOf)) { return false; } + assert(callee()->signature()->size() == 5, "String.indexOf() has 5 arguments"); Node* src = argument(0); // byte[] Node* src_count = argument(1); // char count @@ -1259,8 +1272,21 @@ bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) { RegionNode* region = new RegionNode(5); Node* phi = new PhiNode(region, TypeInt::INT); + Node* result = nullptr; + + bool call_opt_stub = (StubRoutines::_string_indexof_array[ae] != nullptr); - Node* result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, region, phi, ae); + if (call_opt_stub) { + assert(arrayOopDesc::base_offset_in_bytes(T_BYTE) >= 16, "Needed for indexOf"); + Node* call = make_runtime_call(RC_LEAF, OptoRuntime::string_IndexOf_Type(), + StubRoutines::_string_indexof_array[ae], + "stringIndexOf", TypePtr::BOTTOM, src_start, + src_count, tgt_start, tgt_count); + result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + } else { + result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, + region, phi, ae); + } if (result != nullptr) { // The result is index relative to from_index if substring was found, -1 otherwise. // Generate code which will fold into cmove. diff --git a/src/hotspot/share/opto/locknode.cpp b/src/hotspot/share/opto/locknode.cpp index 17d26d620e5..917d9d2bada 100644 --- a/src/hotspot/share/opto/locknode.cpp +++ b/src/hotspot/share/opto/locknode.cpp @@ -194,22 +194,6 @@ bool FastUnlockNode::cmp( const Node &n ) const { return (&n == this); // Always fail except on self } -void FastLockNode::create_rtm_lock_counter(JVMState* state) { -#if INCLUDE_RTM_OPT - Compile* C = Compile::current(); - if (C->profile_rtm() || (PrintPreciseRTMLockingStatistics && C->use_rtm())) { - RTMLockingNamedCounter* rlnc = (RTMLockingNamedCounter*) - OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter); - _rtm_counters = rlnc->counters(); - if (UseRTMForStackLocks) { - rlnc = (RTMLockingNamedCounter*) - OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter); - _stack_rtm_counters = rlnc->counters(); - } - } -#endif -} - //============================================================================= //------------------------------do_monitor_enter------------------------------- void Parse::do_monitor_enter() { diff --git a/src/hotspot/share/opto/locknode.hpp b/src/hotspot/share/opto/locknode.hpp index fcc8da0eb34..0a7e4bd4905 100644 --- a/src/hotspot/share/opto/locknode.hpp +++ b/src/hotspot/share/opto/locknode.hpp @@ -29,8 +29,6 @@ #include "opto/opcodes.hpp" #include "opto/subnode.hpp" -class RTMLockingCounters; - //------------------------------BoxLockNode------------------------------------ class BoxLockNode : public Node { private: @@ -130,16 +128,10 @@ class BoxLockNode : public Node { //------------------------------FastLockNode----------------------------------- class FastLockNode: public CmpNode { -private: - RTMLockingCounters* _rtm_counters; // RTM lock counters for inflated locks - RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks - public: FastLockNode(Node *ctrl, Node *oop, Node *box) : CmpNode(oop,box) { init_req(0,ctrl); init_class_id(Class_FastLock); - _rtm_counters = nullptr; - _stack_rtm_counters = nullptr; } Node* obj_node() const { return in(1); } Node* box_node() const { return in(2); } @@ -153,10 +145,6 @@ class FastLockNode: public CmpNode { virtual int Opcode() const; virtual const Type* Value(PhaseGVN* phase) const { return TypeInt::CC; } const Type *sub(const Type *t1, const Type *t2) const { return TypeInt::CC;} - - void create_rtm_lock_counter(JVMState* state); - RTMLockingCounters* rtm_counters() const { return _rtm_counters; } - RTMLockingCounters* stack_rtm_counters() const { return _stack_rtm_counters; } }; diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index b4faced574d..a02690778a0 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -901,15 +901,6 @@ bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop* phase) const { case Op_CountPositives: { return false; } -#if INCLUDE_RTM_OPT - case Op_FastLock: - case Op_FastUnlock: { - // Don't unroll RTM locking code because it is large. - if (UseRTMLocking) { - return false; - } - } -#endif } // switch } @@ -1074,15 +1065,6 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { // String intrinsics are large and have loops. return false; } -#if INCLUDE_RTM_OPT - case Op_FastLock: - case Op_FastUnlock: { - // Don't unroll RTM locking code because it is large. - if (UseRTMLocking) { - return false; - } - } -#endif } // switch } diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index ad603439e59..90ef4da4f1e 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1460,7 +1460,7 @@ class PhaseIdealLoop : public PhaseTransform { }; AutoVectorizeStatus auto_vectorize(IdealLoopTree* lpt, VSharedData &vshared); - // Move UnorderedReduction out of loop if possible + // Move an unordered Reduction out of loop if possible void move_unordered_reduction_out_of_loop(IdealLoopTree* loop); // Create a scheduled list of nodes control dependent on ctrl set. diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index a3227d47832..b19c71fdd86 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -2987,52 +2987,101 @@ RegionNode* PhaseIdealLoop::insert_region_before_proj(ProjNode* proj) { return reg; } -//------------------------------ insert_cmpi_loop_exit ------------------------------------- -// Clone a signed compare loop exit from an unsigned compare and -// insert it before the unsigned cmp on the stay-in-loop path. -// All new nodes inserted in the dominator tree between the original -// if and it's projections. The original if test is replaced with -// a constant to force the stay-in-loop path. +// Idea +// ---- +// Partial Peeling tries to rotate the loop in such a way that it can later be turned into a counted loop. Counted loops +// require a signed loop exit test. When calling this method, we've only found a suitable unsigned test to partial peel +// with. Therefore, we try to split off a signed loop exit test from the unsigned test such that it can be used as new +// loop exit while keeping the unsigned test unchanged and preserving the same behavior as if we've used the unsigned +// test alone instead: // -// This is done to make sure that the original if and it's projections -// still dominate the same set of control nodes, that the ctrl() relation -// from data nodes to them is preserved, and that their loop nesting is -// preserved. +// Before Partial Peeling: +// Loop: +// +// Split off signed loop exit test +// <-- CUT HERE --> +// Unchanged unsigned loop exit test +// +// goto Loop // -// before -// if(i +// Cloned split off signed loop exit test +// Loop: +// Unchanged unsigned loop exit test +// +// +// Split off signed loop exit test +// goto Loop +// +// Details +// ------- +// Before: +// if (i in(1)->as_Bool(); - if (bol->_test._test != BoolTest::lt) return nullptr; + if (bol->_test._test != BoolTest::lt) { + return nullptr; + } CmpNode* cmpu = bol->in(1)->as_Cmp(); - if (cmpu->Opcode() != Op_CmpU) return nullptr; + assert(cmpu->Opcode() == Op_CmpU, "must be unsigned comparison"); + int stride = stride_of_possible_iv(if_cmpu); - if (stride == 0) return nullptr; + if (stride == 0) { + return nullptr; + } Node* lp_proj = stay_in_loop(if_cmpu, loop); guarantee(lp_proj != nullptr, "null loop node"); @@ -3044,14 +3093,93 @@ IfNode* PhaseIdealLoop::insert_cmpi_loop_exit(IfNode* if_cmpu, IdealLoopTree *lo // We therefore can't add a single exit condition. return nullptr; } - // The loop exit condition is !(i (i < 0 || i >= limit). - // Split out the exit condition (i < 0) for stride < 0 or (i >= limit) for stride > 0. - Node* limit = nullptr; + // The unsigned loop exit condition is + // !(i =u limit + // + // First, we note that for any x for which + // 0 <= x <= INT_MAX + // we can convert x to an unsigned int and still get the same guarantee: + // 0 <= (uint) x <= INT_MAX = (uint) INT_MAX + // 0 <=u (uint) x <=u INT_MAX = (uint) INT_MAX (LEMMA) + // + // With that in mind, if + // limit >= 0 (COND) + // then the unsigned loop exit condition + // i >=u limit (ULE) + // is equivalent to + // i < 0 || i >= limit (SLE-full) + // because either i is negative and therefore always greater than MAX_INT when converting to unsigned + // (uint) i >=u MAX_INT >= limit >= 0 + // or otherwise + // i >= limit >= 0 + // holds due to (LEMMA). + // + // For completeness, a counterexample with limit < 0: + // Assume i = -3 and limit = -2: + // i < 0 + // -2 < 0 + // is true and thus also "i < 0 || i >= limit". But + // i >=u limit + // -3 >=u -2 + // is false. + Node* limit = cmpu->in(2); + const TypeInt* type_limit = _igvn.type(limit)->is_int(); + if (type_limit->_lo < 0) { + return nullptr; + } + + // We prove below that we can extract a single signed loop exit condition from (SLE-full), depending on the stride: + // stride < 0: + // i < 0 (SLE = SLE-negative) + // stride > 0: + // i >= limit (SLE = SLE-positive) + // such that we have the following graph before Partial Peeling with stride > 0 (similar for stride < 0): + // + // Loop: + // + // i >= limit (SLE-positive) + // <-- CUT HERE --> + // i >=u limit (ULE) + // + // goto Loop + // + // We exit the loop if: + // (SLE) is true OR (ULE) is true + // However, if (SLE) is true then (ULE) also needs to be true to ensure the exact same behavior. Otherwise, we wrongly + // exit a loop that should not have been exited if we did not apply Partial Peeling. More formally, we need to ensure: + // (SLE) IMPLIES (ULE) + // This indeed holds when (COND) is given: + // - stride > 0: + // i >= limit // (SLE = SLE-positive) + // i >= limit >= 0 // (COND) + // i >=u limit >= 0 // (LEMMA) + // which is the unsigned loop exit condition (ULE). + // - stride < 0: + // i < 0 // (SLE = SLE-negative) + // (uint) i >u MAX_INT // (NEG) all negative values are greater than MAX_INT when converted to unsigned + // MAX_INT >= limit >= 0 // (COND) + // MAX_INT >=u limit >= 0 // (LEMMA) + // and thus from (NEG) and (LEMMA): + // i >=u limit + // which is the unsigned loop exit condition (ULE). + // + // + // After Partial Peeling, we have the following structure for stride > 0 (similar for stride < 0): + // + // i >= limit (SLE-positive) + // Loop: + // i >=u limit (ULE) + // + // + // i >= limit (SLE-positive) + // goto Loop + Node* rhs_cmpi; if (stride > 0) { - limit = cmpu->in(2); + rhs_cmpi = limit; // For i >= limit } else { - limit = _igvn.makecon(TypeInt::ZERO); - set_ctrl(limit, C->root()); + rhs_cmpi = _igvn.makecon(TypeInt::ZERO); // For i < 0 + set_ctrl(rhs_cmpi, C->root()); } // Create a new region on the exit path RegionNode* reg = insert_region_before_proj(lp_exit); @@ -3059,7 +3187,7 @@ IfNode* PhaseIdealLoop::insert_cmpi_loop_exit(IfNode* if_cmpu, IdealLoopTree *lo // Clone the if-cmpu-true-false using a signed compare BoolTest::mask rel_i = stride > 0 ? bol->_test._test : BoolTest::ge; - ProjNode* cmpi_exit = insert_if_before_proj(cmpu->in(1), Signed, rel_i, limit, lp_continue); + ProjNode* cmpi_exit = insert_if_before_proj(cmpu->in(1), Signed, rel_i, rhs_cmpi, lp_continue); reg->add_req(cmpi_exit); // Clone the if-cmpu-true-false @@ -4310,11 +4438,19 @@ PhaseIdealLoop::auto_vectorize(IdealLoopTree* lpt, VSharedData &vshared) { return AutoVectorizeStatus::Success; } +// Returns true if the Reduction node is unordered. +static bool is_unordered_reduction(Node* n) { + return n->is_Reduction() && !n->as_Reduction()->requires_strict_order(); +} + // Having ReductionNodes in the loop is expensive. They need to recursively // fold together the vector values, for every vectorized loop iteration. If // we encounter the following pattern, we can vector accumulate the values // inside the loop, and only have a single UnorderedReduction after the loop. // +// Note: UnorderedReduction represents a ReductionNode which does not require +// calculating in strict order. +// // CountedLoop init // | | // +------+ | +-----------------------+ @@ -4354,21 +4490,24 @@ PhaseIdealLoop::auto_vectorize(IdealLoopTree* lpt, VSharedData &vshared) { // wise. This is a single operation per vector_accumulator, rather than many // for a UnorderedReduction. We can then reduce the last vector_accumulator // after the loop, and also reduce the init value into it. +// // We can not do this with all reductions. Some reductions do not allow the -// reordering of operations (for example float addition). +// reordering of operations (for example float addition/multiplication require +// strict order). void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { assert(!C->major_progress() && loop->is_counted() && loop->is_innermost(), "sanity"); - // Find all Phi nodes with UnorderedReduction on backedge. + // Find all Phi nodes with an unordered Reduction on backedge. CountedLoopNode* cl = loop->_head->as_CountedLoop(); for (DUIterator_Fast jmax, j = cl->fast_outs(jmax); j < jmax; j++) { Node* phi = cl->fast_out(j); - // We have a phi with a single use, and a UnorderedReduction on the backedge. - if (!phi->is_Phi() || phi->outcnt() != 1 || !phi->in(2)->is_UnorderedReduction()) { + // We have a phi with a single use, and an unordered Reduction on the backedge. + if (!phi->is_Phi() || phi->outcnt() != 1 || !is_unordered_reduction(phi->in(2))) { continue; } - UnorderedReductionNode* last_ur = phi->in(2)->as_UnorderedReduction(); + ReductionNode* last_ur = phi->in(2)->as_Reduction(); + assert(!last_ur->requires_strict_order(), "must be"); // Determine types const TypeVect* vec_t = last_ur->vect_type(); @@ -4385,14 +4524,14 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { continue; // not implemented -> fails } - // Traverse up the chain of UnorderedReductions, checking that it loops back to - // the phi. Check that all UnorderedReductions only have a single use, except for + // Traverse up the chain of unordered Reductions, checking that it loops back to + // the phi. Check that all unordered Reductions only have a single use, except for // the last (last_ur), which only has phi as a use in the loop, and all other uses // are outside the loop. - UnorderedReductionNode* current = last_ur; - UnorderedReductionNode* first_ur = nullptr; + ReductionNode* current = last_ur; + ReductionNode* first_ur = nullptr; while (true) { - assert(current->is_UnorderedReduction(), "sanity"); + assert(!current->requires_strict_order(), "sanity"); // Expect no ctrl and a vector_input from within the loop. Node* ctrl = current->in(0); @@ -4409,7 +4548,7 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { break; // Chain traversal fails. } - // Expect single use of UnorderedReduction, except for last_ur. + // Expect single use of an unordered Reduction, except for last_ur. if (current == last_ur) { // Expect all uses to be outside the loop, except phi. for (DUIterator_Fast kmax, k = current->fast_outs(kmax); k < kmax; k++) { @@ -4427,12 +4566,13 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { } } - // Expect another UnorderedReduction or phi as the scalar input. + // Expect another unordered Reduction or phi as the scalar input. Node* scalar_input = current->in(1); - if (scalar_input->is_UnorderedReduction() && + if (is_unordered_reduction(scalar_input) && scalar_input->Opcode() == current->Opcode()) { - // Move up the UnorderedReduction chain. - current = scalar_input->as_UnorderedReduction(); + // Move up the unordered Reduction chain. + current = scalar_input->as_Reduction(); + assert(!current->requires_strict_order(), "must be"); } else if (scalar_input == phi) { // Chain terminates at phi. first_ur = current; @@ -4456,7 +4596,7 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { VectorNode* identity_vector = VectorNode::scalar2vector(identity_scalar, vector_length, bt_t); register_new_node(identity_vector, C->root()); assert(vec_t == identity_vector->vect_type(), "matching vector type"); - VectorNode::trace_new_vector(identity_vector, "UnorderedReduction"); + VectorNode::trace_new_vector(identity_vector, "Unordered Reduction"); // Turn the scalar phi into a vector phi. _igvn.rehash_node_delayed(phi); @@ -4465,7 +4605,7 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { phi->as_Type()->set_type(vec_t); _igvn.set_type(phi, vec_t); - // Traverse down the chain of UnorderedReductions, and replace them with vector_accumulators. + // Traverse down the chain of unordered Reductions, and replace them with vector_accumulators. current = first_ur; while (true) { // Create vector_accumulator to replace current. @@ -4474,11 +4614,12 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { VectorNode* vector_accumulator = VectorNode::make(vopc, last_vector_accumulator, vector_input, vec_t); register_new_node(vector_accumulator, cl); _igvn.replace_node(current, vector_accumulator); - VectorNode::trace_new_vector(vector_accumulator, "UnorderedReduction"); + VectorNode::trace_new_vector(vector_accumulator, "Unordered Reduction"); if (current == last_ur) { break; } - current = vector_accumulator->unique_out()->as_UnorderedReduction(); + current = vector_accumulator->unique_out()->as_Reduction(); + assert(!current->requires_strict_order(), "must be"); } // Create post-loop reduction. @@ -4495,7 +4636,7 @@ void PhaseIdealLoop::move_unordered_reduction_out_of_loop(IdealLoopTree* loop) { } } register_new_node(post_loop_reduction, get_late_ctrl(post_loop_reduction, cl)); - VectorNode::trace_new_vector(post_loop_reduction, "UnorderedReduction"); + VectorNode::trace_new_vector(post_loop_reduction, "Unordered Reduction"); assert(last_accumulator->outcnt() == 2, "last_accumulator has 2 uses: phi and post_loop_reduction"); assert(post_loop_reduction->outcnt() > 0, "should have taken over all non loop uses of last_accumulator"); diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index 677e1bcd1d1..6dbaa8a1396 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,6 @@ class MachSpillCopyNode; class Matcher; class PhaseRegAlloc; class RegMask; -class RTMLockingCounters; class State; //---------------------------MachOper------------------------------------------ @@ -802,8 +801,6 @@ class MachGotoNode : public MachBranchNode { class MachFastLockNode : public MachNode { virtual uint size_of() const { return sizeof(*this); } // Size is bigger public: - RTMLockingCounters* _rtm_counters; // RTM lock counters for inflated locks - RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks MachFastLockNode() : MachNode() {} }; diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index ce1a8a61134..21dfacf9fe1 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -2428,7 +2428,6 @@ void PhaseMacroExpand::eliminate_macro_nodes() { break; default: assert(n->Opcode() == Op_LoopLimit || - n->Opcode() == Op_Opaque3 || n->is_Opaque4() || n->is_OpaqueInitializedAssertionPredicate() || n->Opcode() == Op_MaxL || @@ -2481,30 +2480,6 @@ bool PhaseMacroExpand::expand_macro_nodes() { } else if (n->is_Opaque1()) { _igvn.replace_node(n, n->in(1)); success = true; -#if INCLUDE_RTM_OPT - } else if ((n->Opcode() == Op_Opaque3) && ((Opaque3Node*)n)->rtm_opt()) { - assert(C->profile_rtm(), "should be used only in rtm deoptimization code"); - assert((n->outcnt() == 1) && n->unique_out()->is_Cmp(), ""); - Node* cmp = n->unique_out(); -#ifdef ASSERT - // Validate graph. - assert((cmp->outcnt() == 1) && cmp->unique_out()->is_Bool(), ""); - BoolNode* bol = cmp->unique_out()->as_Bool(); - assert((bol->outcnt() == 1) && bol->unique_out()->is_If() && - (bol->_test._test == BoolTest::ne), ""); - IfNode* ifn = bol->unique_out()->as_If(); - assert((ifn->outcnt() == 2) && - ifn->proj_out(1)->is_uncommon_trap_proj(Deoptimization::Reason_rtm_state_change) != nullptr, ""); -#endif - Node* repl = n->in(1); - if (!_has_locks) { - // Remove RTM state check if there are no locks in the code. - // Replace input to compare the same value. - repl = (cmp->in(1) == n) ? cmp->in(2) : cmp->in(1); - } - _igvn.replace_node(n, repl); - success = true; -#endif } else if (n->is_Opaque4()) { // With Opaque4 nodes, the expectation is that the test of input 1 // is always equal to the constant value of input 2. So we can diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index b8da06af5d6..d0b6c59637f 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2881,14 +2881,14 @@ class ArrayPointer { // // RangeCheck[i+0] RangeCheck[i+0] // StoreB[i+0] -// RangeCheck[i+1] RangeCheck[i+1] +// RangeCheck[i+3] RangeCheck[i+3] // StoreB[i+1] --> pass: fail: // StoreB[i+2] StoreI[i+0] StoreB[i+0] // StoreB[i+3] // // The 4 StoreB are merged into a single StoreI node. We have to be careful with RangeCheck[i+1]: before // the optimization, if this RangeCheck[i+1] fails, then we execute only StoreB[i+0], and then trap. After -// the optimization, the new StoreI[i+0] is on the passing path of RangeCheck[i+1], and StoreB[i+0] on the +// the optimization, the new StoreI[i+0] is on the passing path of RangeCheck[i+3], and StoreB[i+0] on the // failing path. // // Note: For normal array stores, every store at first has a RangeCheck. But they can be removed with: @@ -2900,11 +2900,11 @@ class ArrayPointer { // RangeCheck[i+0] RangeCheck[i+0] <- before first store // StoreB[i+0] StoreB[i+0] <- first store // RangeCheck[i+1] --> smeared --> RangeCheck[i+3] <- only RC between first and last store -// StoreB[i+0] StoreB[i+1] <- second store +// StoreB[i+1] StoreB[i+1] <- second store // RangeCheck[i+2] --> removed -// StoreB[i+0] StoreB[i+2] +// StoreB[i+2] StoreB[i+2] // RangeCheck[i+3] --> removed -// StoreB[i+0] StoreB[i+3] <- last store +// StoreB[i+3] StoreB[i+3] <- last store // // Thus, it is a common pattern that between the first and last store in a chain // of adjacent stores there remains exactly one RangeCheck, located between the @@ -3067,6 +3067,11 @@ bool MergePrimitiveArrayStores::is_adjacent_input_pair(const Node* n1, const Nod } // Pattern: [n1 = base >> shift, n2 = base >> (shift + memory_size)] +#ifndef VM_LITTLE_ENDIAN + // Pattern: [n1 = base >> (shift + memory_size), n2 = base >> shift] + // Swapping n1 with n2 gives same pattern as on little endian platforms. + swap(n1, n2); +#endif // !VM_LITTLE_ENDIAN Node const* base_n2; jint shift_n2; if (!is_con_RShift(n2, base_n2, shift_n2)) { @@ -3281,8 +3286,13 @@ Node* MergePrimitiveArrayStores::make_merged_input_value(const Node_List& merge_ jlong mask = (((jlong)1) << bits_per_store) - 1; for (uint i = 0; i < merge_list.size(); i++) { jlong con_i = merge_list.at(i)->in(MemNode::ValueIn)->get_int(); +#ifdef VM_LITTLE_ENDIAN con = con << bits_per_store; con = con | (mask & con_i); +#else // VM_LITTLE_ENDIAN + con_i = (mask & con_i) << (i * bits_per_store); + con = con | con_i; +#endif // VM_LITTLE_ENDIAN } merged_input_value = _phase->longcon(con); } else { @@ -3290,16 +3300,22 @@ Node* MergePrimitiveArrayStores::make_merged_input_value(const Node_List& merge_ // | | // _store first // - merged_input_value = first->in(MemNode::ValueIn); - Node const* base_last; - jint shift_last; - bool is_true = is_con_RShift(_store->in(MemNode::ValueIn), base_last, shift_last); + Node* hi = _store->in(MemNode::ValueIn); + Node* lo = first->in(MemNode::ValueIn); +#ifndef VM_LITTLE_ENDIAN + // `_store` and `first` are swapped in the diagram above + swap(hi, lo); +#endif // !VM_LITTLE_ENDIAN + Node const* hi_base; + jint hi_shift; + merged_input_value = lo; + bool is_true = is_con_RShift(hi, hi_base, hi_shift); assert(is_true, "must detect con RShift"); - if (merged_input_value != base_last && merged_input_value->Opcode() == Op_ConvL2I) { + if (merged_input_value != hi_base && merged_input_value->Opcode() == Op_ConvL2I) { // look through merged_input_value = merged_input_value->in(1); } - if (merged_input_value != base_last) { + if (merged_input_value != hi_base) { // merged_input_value is not the base return nullptr; } @@ -3473,7 +3489,6 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) { } } -#ifdef VM_LITTLE_ENDIAN if (MergeStores && UseUnalignedAccesses) { if (phase->C->post_loop_opts_phase()) { MergePrimitiveArrayStores merge(phase, this); @@ -3483,7 +3498,6 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) { phase->C->record_for_post_loop_opts_igvn(this); } } -#endif return nullptr; // No further progress } diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index dc9dc6654b5..ae379c4833a 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -175,7 +175,6 @@ class SubTypeCheckNode; class Type; class TypeNode; class UnlockNode; -class UnorderedReductionNode; class VectorNode; class LoadVectorNode; class LoadVectorMaskedNode; @@ -739,7 +738,6 @@ class Node { DEFINE_CLASS_ID(ExpandV, Vector, 5) DEFINE_CLASS_ID(CompressM, Vector, 6) DEFINE_CLASS_ID(Reduction, Vector, 7) - DEFINE_CLASS_ID(UnorderedReduction, Reduction, 0) DEFINE_CLASS_ID(NegV, Vector, 8) DEFINE_CLASS_ID(Con, Type, 8) DEFINE_CLASS_ID(ConI, Con, 0) @@ -991,7 +989,6 @@ class Node { DEFINE_CLASS_QUERY(Sub) DEFINE_CLASS_QUERY(SubTypeCheck) DEFINE_CLASS_QUERY(Type) - DEFINE_CLASS_QUERY(UnorderedReduction) DEFINE_CLASS_QUERY(Vector) DEFINE_CLASS_QUERY(VectorMaskCmp) DEFINE_CLASS_QUERY(VectorUnbox) diff --git a/src/hotspot/share/opto/opaquenode.cpp b/src/hotspot/share/opto/opaquenode.cpp index 0abc6f86ed0..14fd0d5f1a7 100644 --- a/src/hotspot/share/opto/opaquenode.cpp +++ b/src/hotspot/share/opto/opaquenode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,16 +45,6 @@ Node* Opaque1Node::Identity(PhaseGVN* phase) { return this; } -// Do NOT remove the opaque node until no more loop opts can happen. -Node* Opaque3Node::Identity(PhaseGVN* phase) { - if (phase->C->post_loop_opts_phase()) { - return in(1); - } else { - phase->C->record_for_post_loop_opts_igvn(this); - } - return this; -} - #ifdef ASSERT CountedLoopNode* OpaqueZeroTripGuardNode::guarded_loop() const { Node* iff = if_node(); @@ -92,12 +82,6 @@ IfNode* OpaqueZeroTripGuardNode::if_node() const { return iff->as_If(); } -// Do not allow value-numbering -uint Opaque3Node::hash() const { return NO_HASH; } -bool Opaque3Node::cmp(const Node &n) const { - return (&n == this); // Always fail except on self -} - const Type* Opaque4Node::Value(PhaseGVN* phase) const { return phase->type(in(1)); } diff --git a/src/hotspot/share/opto/opaquenode.hpp b/src/hotspot/share/opto/opaquenode.hpp index 2337989e974..4617979c2e4 100644 --- a/src/hotspot/share/opto/opaquenode.hpp +++ b/src/hotspot/share/opto/opaquenode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,26 +91,6 @@ class OpaqueZeroTripGuardNode : public Opaque1Node { IfNode* if_node() const; }; -//------------------------------Opaque3Node------------------------------------ -// A node to prevent unwanted optimizations. Will be optimized only during -// macro nodes expansion. -class Opaque3Node : public Node { - int _opt; // what optimization it was used for - virtual uint hash() const; - virtual bool cmp(const Node &n) const; - public: - enum { RTM_OPT }; - Opaque3Node(Compile* C, Node* n, int opt) : Node(0, n), _opt(opt) { - // Put it on the Macro nodes list to removed during macro nodes expansion. - init_flags(Flag_is_macro); - C->add_macro_node(this); - } - virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::INT; } - virtual Node* Identity(PhaseGVN* phase); - bool rtm_opt() const { return (_opt == RTM_OPT); } -}; - // Input 1 is a check that we know implicitly is always true or false // but the compiler has no way to prove. If during optimizations, that // check becomes true or false, the Opaque4 node is replaced by that diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 0ad56184d4d..8ea456d3417 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1321,7 +1321,7 @@ CodeBuffer* PhaseOutput::init_buffer() { int code_req = _buf_sizes._code; int const_req = _buf_sizes._const; - int pad_req = NativeCall::instruction_size; + int pad_req = NativeCall::byte_size(); BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); stub_req += bs->estimate_stub_size(); @@ -3388,8 +3388,7 @@ void PhaseOutput::install() { C->entry_bci(), CompileBroker::compiler2(), C->has_unsafe_access(), - SharedRuntime::is_wide_vector(C->max_vector_size()), - C->rtm_state()); + SharedRuntime::is_wide_vector(C->max_vector_size())); } } @@ -3397,8 +3396,7 @@ void PhaseOutput::install_code(ciMethod* target, int entry_bci, AbstractCompiler* compiler, bool has_unsafe_access, - bool has_wide_vectors, - RTMState rtm_state) { + bool has_wide_vectors) { // Check if we want to skip execution of all compiled code. { #ifndef PRODUCT @@ -3436,8 +3434,7 @@ void PhaseOutput::install_code(ciMethod* target, has_unsafe_access, SharedRuntime::is_wide_vector(C->max_vector_size()), C->has_monitors(), - 0, - C->rtm_state()); + 0); if (C->log() != nullptr) { // Print code cache state into compiler log C->log()->code_cache_state(); diff --git a/src/hotspot/share/opto/output.hpp b/src/hotspot/share/opto/output.hpp index 17179553602..9431ef3d508 100644 --- a/src/hotspot/share/opto/output.hpp +++ b/src/hotspot/share/opto/output.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,8 +121,7 @@ class PhaseOutput : public Phase { int entry_bci, AbstractCompiler* compiler, bool has_unsafe_access, - bool has_wide_vectors, - RTMState rtm_state); + bool has_wide_vectors); void install_stub(const char* stub_name); diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp index d5f12c8bc81..a55c9cb0cb1 100644 --- a/src/hotspot/share/opto/parse.hpp +++ b/src/hotspot/share/opto/parse.hpp @@ -501,8 +501,6 @@ class Parse : public GraphKit { void clinit_deopt(); - void rtm_deopt(); - // Pass current map to exits void return_current(Node* value); diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index 80cb6721fce..4dc3ac37042 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -597,12 +597,9 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) // Add check to deoptimize the nmethod once the holder class is fully initialized clinit_deopt(); } - - // Add check to deoptimize the nmethod if RTM state was changed - rtm_deopt(); } - // Check for bailouts during method entry or RTM state check setup. + // Check for bailouts during method entry. if (failing()) { if (log) log->done("parse"); C->set_default_node_notes(caller_nn); @@ -2201,42 +2198,6 @@ void Parse::clinit_deopt() { guard_klass_being_initialized(holder); } -// Add check to deoptimize if RTM state is not ProfileRTM -void Parse::rtm_deopt() { -#if INCLUDE_RTM_OPT - if (C->profile_rtm()) { - assert(C->has_method(), "only for normal compilations"); - assert(!C->method()->method_data()->is_empty(), "MDO is needed to record RTM state"); - assert(depth() == 1, "generate check only for main compiled method"); - - // Set starting bci for uncommon trap. - set_parse_bci(is_osr_parse() ? osr_bci() : 0); - - // Load the rtm_state from the MethodData. - const TypePtr* adr_type = TypeMetadataPtr::make(C->method()->method_data()); - Node* mdo = makecon(adr_type); - int offset = in_bytes(MethodData::rtm_state_offset()); - Node* adr_node = basic_plus_adr(mdo, mdo, offset); - Node* rtm_state = make_load(control(), adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); - - // Separate Load from Cmp by Opaque. - // In expand_macro_nodes() it will be replaced either - // with this load when there are locks in the code - // or with ProfileRTM (cmp->in(2)) otherwise so that - // the check will fold. - Node* profile_state = makecon(TypeInt::make(ProfileRTM)); - Node* opq = _gvn.transform( new Opaque3Node(C, rtm_state, Opaque3Node::RTM_OPT) ); - Node* chk = _gvn.transform( new CmpINode(opq, profile_state) ); - Node* tst = _gvn.transform( new BoolNode(chk, BoolTest::eq) ); - // Branch to failure if state was changed - { BuildCutout unless(this, tst, PROB_ALWAYS); - uncommon_trap(Deoptimization::Reason_rtm_state_change, - Deoptimization::Action_make_not_entrant); - } - } -#endif -} - //------------------------------return_current--------------------------------- // Append current _map to _exit_return void Parse::return_current(Node* value) { diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index d8e5cdbab04..2953a1f7b72 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1357,6 +1357,27 @@ const TypeFunc* OptoRuntime::base64_encodeBlock_Type() { const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); return TypeFunc::make(domain, range); } + +// String IndexOf function +const TypeFunc* OptoRuntime::string_IndexOf_Type() { + int argcnt = 4; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // haystack array + fields[argp++] = TypeInt::INT; // haystack length + fields[argp++] = TypePtr::NOTNULL; // needle array + fields[argp++] = TypeInt::INT; // needle length + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; // Index of needle in haystack + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + // Base64 decode function const TypeFunc* OptoRuntime::base64_decodeBlock_Type() { int argcnt = 7; @@ -1835,14 +1856,6 @@ void OptoRuntime::print_named_counters() { eliminated_lock_count += count; } } -#if INCLUDE_RTM_OPT - } else if (c->tag() == NamedCounter::RTMLockingCounter) { - RTMLockingCounters* rlc = ((RTMLockingNamedCounter*)c)->counters(); - if (rlc->nonzero()) { - tty->print_cr("%s", c->name()); - rlc->print_on(tty); - } -#endif } c = c->next(); } @@ -1884,12 +1897,7 @@ NamedCounter* OptoRuntime::new_named_counter(JVMState* youngest_jvms, NamedCount st.print("@%d", bci); // To print linenumbers instead of bci use: m->line_number_from_bci(bci) } - NamedCounter* c; - if (tag == NamedCounter::RTMLockingCounter) { - c = new RTMLockingNamedCounter(st.freeze()); - } else { - c = new NamedCounter(st.freeze(), tag); - } + NamedCounter* c = new NamedCounter(st.freeze(), tag); // atomically add the new counter to the head of the list. We only // add counters so this is safe. diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index e4cbdf2f0d0..6aadab97122 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -29,7 +29,6 @@ #include "opto/machnode.hpp" #include "opto/optoreg.hpp" #include "opto/type.hpp" -#include "runtime/rtmLocking.hpp" #include "runtime/deoptimization.hpp" #include "runtime/vframe.hpp" @@ -61,8 +60,7 @@ class NamedCounter : public CHeapObj { enum CounterTag { NoTag, LockCounter, - EliminatedLockCounter, - RTMLockingCounter + EliminatedLockCounter }; private: @@ -98,17 +96,6 @@ class NamedCounter : public CHeapObj { }; -class RTMLockingNamedCounter : public NamedCounter { - private: - RTMLockingCounters _counters; - - public: - RTMLockingNamedCounter(const char *n) : - NamedCounter(n, RTMLockingCounter), _counters() {} - - RTMLockingCounters* counters() { return &_counters; } -}; - typedef const TypeFunc*(*TypeFunc_generator)(); class OptoRuntime : public AllStatic { @@ -297,6 +284,7 @@ class OptoRuntime : public AllStatic { static const TypeFunc* chacha20Block_Type(); static const TypeFunc* base64_encodeBlock_Type(); static const TypeFunc* base64_decodeBlock_Type(); + static const TypeFunc* string_IndexOf_Type(); static const TypeFunc* poly1305_processBlocks_Type(); static const TypeFunc* intpoly_montgomeryMult_P256_Type(); static const TypeFunc* intpoly_assign_Type(); diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 0b940a13c54..d36e306a1e9 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -43,7 +43,6 @@ SuperWord::SuperWord(const VLoopAnalyzer &vloop_analyzer) : _vloop_analyzer(vloop_analyzer), _vloop(vloop_analyzer.vloop()), _arena(mtCompiler), - _node_info(arena(), _vloop.estimated_body_length(), 0, SWNodeInfo::initial), // info needed per node _clone_map(phase()->C->clone_map()), // map of nodes created in cloning _pairset(&_arena, _vloop_analyzer), _packset(&_arena, _vloop_analyzer @@ -453,11 +452,8 @@ bool SuperWord::transform_loop() { bool SuperWord::SLP_extract() { assert(cl()->is_main_loop(), "SLP should only work on main loops"); - // Ensure extra info is allocated. - initialize_node_info(); - - // Attempt vectorization - find_adjacent_refs(); + // Find "seed" pairs. + create_adjacent_memop_pairs(); if (_pairset.is_empty()) { #ifndef PRODUCT @@ -491,245 +487,133 @@ bool SuperWord::SLP_extract() { return output(); } -//------------------------------find_adjacent_refs--------------------------- -// Find the adjacent memory references and create pack pairs for them. -// We can find adjacent memory references by comparing their relative -// alignment. Whether the final vectors can be aligned is determined later -// once all vectors are extended and combined. -void SuperWord::find_adjacent_refs() { - // Get list of memory operations - Node_List memops; - for (int i = 0; i < body().length(); i++) { - Node* n = body().at(i); - if (n->is_Mem() && !n->is_LoadStore() && in_bb(n) && - is_java_primitive(n->as_Mem()->memory_type())) { - int align = memory_alignment(n->as_Mem(), 0); - if (align != bottom_align) { - memops.push(n); - } - } - } +// Find the "seed" memops pairs. These are pairs that we strongly suspect would lead to vectorization. +void SuperWord::create_adjacent_memop_pairs() { + ResourceMark rm; + GrowableArray vpointers; + + collect_valid_vpointers(vpointers); + + // Sort the VPointers. This does 2 things: + // - Separate the VPointer into groups: all memops that have the same opcode and the same + // VPointer, except for the offset. Adjacent memops must have the same opcode and the + // same VPointer, except for a shift in the offset. Thus, two memops can only be adjacent + // if they are in the same group. This decreases the work. + // - Sort by offset inside the groups. This decreases the work needed to determine adjacent + // memops inside a group. + vpointers.sort(VPointer::cmp_for_sort); + #ifndef PRODUCT if (is_trace_superword_adjacent_memops()) { - tty->print_cr("\nfind_adjacent_refs found %d memops", memops.size()); + tty->print_cr("\nSuperWord::create_adjacent_memop_pairs:"); } #endif - int max_idx; - - while (memops.size() != 0) { - // Find a memory reference to align to. - MemNode* mem_ref = find_align_to_ref(memops, max_idx); - if (mem_ref == nullptr) break; - int iv_adjustment = get_iv_adjustment(mem_ref); - - const VPointer& align_to_ref_p = vpointer(mem_ref); - // Set alignment relative to "align_to_ref" for all related memory operations. - for (int i = memops.size() - 1; i >= 0; i--) { - MemNode* s = memops.at(i)->as_Mem(); - if (isomorphic(s, mem_ref) && - (!_do_vector_loop || same_origin_idx(s, mem_ref))) { - const VPointer& p2 = vpointer(s); - if (p2.comparable(align_to_ref_p)) { - int align = memory_alignment(s, iv_adjustment); - set_alignment(s, align); - } - } - } - - // Create initial pack pairs of memory operations for which alignment was set. - for (uint i = 0; i < memops.size(); i++) { - Node* s1 = memops.at(i); - int align = alignment(s1); - if (align == top_align) continue; - for (uint j = 0; j < memops.size(); j++) { - Node* s2 = memops.at(j); - if (alignment(s2) == top_align) continue; - if (s1 != s2 && are_adjacent_refs(s1, s2)) { - if (stmts_can_pack(s1, s2, align)) { - if (!_do_vector_loop || same_origin_idx(s1, s2)) { - _pairset.add_pair(s1, s2); - } - } - } - } - } - - // Remove used mem nodes. - for (int i = memops.size() - 1; i >= 0; i--) { - MemNode* m = memops.at(i)->as_Mem(); - if (alignment(m) != top_align) { - memops.remove(i); - } - } - } // while (memops.size() != 0) + create_adjacent_memop_pairs_in_all_groups(vpointers); #ifndef PRODUCT if (is_trace_superword_packset()) { - tty->print_cr("\nAfter Superword::find_adjacent_refs"); + tty->print_cr("\nAfter Superword::create_adjacent_memop_pairs"); _pairset.print(); } #endif } -//------------------------------find_align_to_ref--------------------------- -// Find a memory reference to align the loop induction variable to. -// Looks first at stores then at loads, looking for a memory reference -// with the largest number of references similar to it. -MemNode* SuperWord::find_align_to_ref(Node_List &memops, int &idx) { - GrowableArray cmp_ct(arena(), memops.size(), memops.size(), 0); - - // Count number of comparable memory ops - for (uint i = 0; i < memops.size(); i++) { - MemNode* s1 = memops.at(i)->as_Mem(); - const VPointer& p1 = vpointer(s1); - for (uint j = i+1; j < memops.size(); j++) { - MemNode* s2 = memops.at(j)->as_Mem(); - if (isomorphic(s1, s2)) { - const VPointer& p2 = vpointer(s2); - if (p1.comparable(p2)) { - (*cmp_ct.adr_at(i))++; - (*cmp_ct.adr_at(j))++; - } - } +// Collect all memops vpointers that could potentially be vectorized. +void SuperWord::collect_valid_vpointers(GrowableArray& vpointers) { + for_each_mem([&] (const MemNode* mem, int bb_idx) { + const VPointer& p = vpointer(mem); + if (p.valid() && + !mem->is_LoadStore() && + is_java_primitive(mem->memory_type())) { + vpointers.append(&p); } + }); +} + +// For each group, find the adjacent memops. +void SuperWord::create_adjacent_memop_pairs_in_all_groups(const GrowableArray &vpointers) { + int group_start = 0; + while (group_start < vpointers.length()) { + int group_end = find_group_end(vpointers, group_start); + create_adjacent_memop_pairs_in_one_group(vpointers, group_start, group_end); + group_start = group_end; } +} - // Find Store (or Load) with the greatest number of "comparable" references, - // biggest vector size, smallest data size and smallest iv offset. - int max_ct = 0; - int max_vw = 0; - int max_idx = -1; - int min_size = max_jint; - int min_iv_offset = max_jint; - for (uint j = 0; j < memops.size(); j++) { - MemNode* s = memops.at(j)->as_Mem(); - if (s->is_Store()) { - int vw = vector_width_in_bytes(s); - assert(vw > 1, "sanity"); - const VPointer& p = vpointer(s); - if ( cmp_ct.at(j) > max_ct || - (cmp_ct.at(j) == max_ct && - ( vw > max_vw || - (vw == max_vw && - ( data_size(s) < min_size || - (data_size(s) == min_size && - p.offset_in_bytes() < min_iv_offset)))))) { - max_ct = cmp_ct.at(j); - max_vw = vw; - max_idx = j; - min_size = data_size(s); - min_iv_offset = p.offset_in_bytes(); - } - } - } - // If no stores, look at loads - if (max_ct == 0) { - for (uint j = 0; j < memops.size(); j++) { - MemNode* s = memops.at(j)->as_Mem(); - if (s->is_Load()) { - int vw = vector_width_in_bytes(s); - assert(vw > 1, "sanity"); - const VPointer& p = vpointer(s); - if ( cmp_ct.at(j) > max_ct || - (cmp_ct.at(j) == max_ct && - ( vw > max_vw || - (vw == max_vw && - ( data_size(s) < min_size || - (data_size(s) == min_size && - p.offset_in_bytes() < min_iv_offset)))))) { - max_ct = cmp_ct.at(j); - max_vw = vw; - max_idx = j; - min_size = data_size(s); - min_iv_offset = p.offset_in_bytes(); - } - } - } +// Step forward until we find a VPointer of another group, or we reach the end of the array. +int SuperWord::find_group_end(const GrowableArray& vpointers, int group_start) { + int group_end = group_start + 1; + while (group_end < vpointers.length() && + VPointer::cmp_for_sort_by_group( + vpointers.adr_at(group_start), + vpointers.adr_at(group_end) + ) == 0) { + group_end++; } + return group_end; +} +// Find adjacent memops for a single group, e.g. for all LoadI of the same base, invar, etc. +// Create pairs and add them to the pairset. +void SuperWord::create_adjacent_memop_pairs_in_one_group(const GrowableArray& vpointers, const int group_start, const int group_end) { #ifndef PRODUCT - if (is_trace_superword_verbose()) { - tty->print_cr("\nVector memops after find_align_to_ref"); - for (uint i = 0; i < memops.size(); i++) { - MemNode* s = memops.at(i)->as_Mem(); - s->dump(); + if (is_trace_superword_adjacent_memops()) { + tty->print_cr(" group:"); + for (int i = group_start; i < group_end; i++) { + const VPointer* p = vpointers.at(i); + tty->print(" "); + p->print(); } } #endif - idx = max_idx; - if (max_ct > 0) { -#ifndef PRODUCT - if (is_trace_superword_adjacent_memops()) { - tty->print("SuperWord::find_align_to_ref: "); - memops.at(max_idx)->as_Mem()->dump(); - } -#endif - return memops.at(max_idx)->as_Mem(); - } - return nullptr; -} + MemNode* first = vpointers.at(group_start)->mem(); + int element_size = data_size(first); -//---------------------------get_vw_bytes_special------------------------ -int SuperWord::get_vw_bytes_special(MemNode* s) { - // Get the vector width in bytes. - int vw = vector_width_in_bytes(s); + // For each ref in group: find others that can be paired: + for (int i = group_start; i < group_end; i++) { + const VPointer* p1 = vpointers.at(i); + MemNode* mem1 = p1->mem(); - // Check for special case where there is an MulAddS2I usage where short vectors are going to need combined. - BasicType btype = velt_basic_type(s); - if (type2aelembytes(btype) == 2) { - bool should_combine_adjacent = true; - for (DUIterator_Fast imax, i = s->fast_outs(imax); i < imax; i++) { - Node* user = s->fast_out(i); - if (!VectorNode::is_muladds2i(user)) { - should_combine_adjacent = false; - } - } - if (should_combine_adjacent) { - vw = MIN2(Matcher::max_vector_size_auto_vectorization(btype)*type2aelembytes(btype), vw * 2); - } - } + bool found = false; + // For each ref in group with larger or equal offset: + for (int j = i + 1; j < group_end; j++) { + const VPointer* p2 = vpointers.at(j); + MemNode* mem2 = p2->mem(); + assert(mem1 != mem2, "look only at pair of different memops"); - // Check for special case where there is a type conversion between different data size. - int vectsize = max_vector_size_in_def_use_chain(s); - if (vectsize < Matcher::max_vector_size_auto_vectorization(btype)) { - vw = MIN2(vectsize * type2aelembytes(btype), vw); - } + // Check for correct distance. + assert(data_size(mem1) == element_size, "all nodes in group must have the same element size"); + assert(data_size(mem2) == element_size, "all nodes in group must have the same element size"); + assert(p1->offset_in_bytes() <= p2->offset_in_bytes(), "must be sorted by offset"); + if (p1->offset_in_bytes() + element_size > p2->offset_in_bytes()) { continue; } + if (p1->offset_in_bytes() + element_size < p2->offset_in_bytes()) { break; } - return vw; -} + // Only allow nodes from same origin idx to be packed (see CompileCommand Option Vectorize) + if (_do_vector_loop && !same_origin_idx(mem1, mem2)) { continue; } -//---------------------------get_iv_adjustment--------------------------- -// Calculate loop's iv adjustment for this memory ops. -int SuperWord::get_iv_adjustment(MemNode* mem_ref) { - const VPointer& align_to_ref_p = vpointer(mem_ref); - int offset = align_to_ref_p.offset_in_bytes(); - int scale = align_to_ref_p.scale_in_bytes(); - int elt_size = align_to_ref_p.memory_size(); - int vw = get_vw_bytes_special(mem_ref); - assert(vw > 1, "sanity"); - int iv_adjustment; - if (scale != 0) { - int stride_sign = (scale * iv_stride()) > 0 ? 1 : -1; - // At least one iteration is executed in pre-loop by default. As result - // several iterations are needed to align memory operations in main-loop even - // if offset is 0. - int iv_adjustment_in_bytes = (stride_sign * vw - (offset % vw)); - iv_adjustment = iv_adjustment_in_bytes/elt_size; - } else { - // This memory op is not dependent on iv (scale == 0) - iv_adjustment = 0; - } + if (!can_pack_into_pair(mem1, mem2)) { continue; } #ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print("SuperWord::get_iv_adjustment: n = %d, noffset = %d iv_adjust = %d elt_size = %d scale = %d iv_stride = %d vect_size %d: ", - mem_ref->_idx, offset, iv_adjustment, elt_size, scale, iv_stride(), vw); - mem_ref->dump(); - } + if (is_trace_superword_adjacent_memops()) { + if (found) { + tty->print_cr(" WARNING: multiple pairs with the same node. Ignored pairing:"); + } else { + tty->print_cr(" pair:"); + } + tty->print(" "); + p1->print(); + tty->print(" "); + p2->print(); + } #endif - return iv_adjustment; + + if (!found) { + _pairset.add_pair(mem1, mem2); + } + } + } } void VLoopMemorySlices::find_memory_slices() { @@ -809,10 +693,8 @@ void VLoopMemorySlices::get_slice_in_reverse_order(PhiNode* head, MemNode* tail, #endif } -//------------------------------stmts_can_pack--------------------------- -// Can s1 and s2 be in a pack with s1 immediately preceding s2 and -// s1 aligned at "align" -bool SuperWord::stmts_can_pack(Node* s1, Node* s2, int align) { +// Check if two nodes can be packed into a pair. +bool SuperWord::can_pack_into_pair(Node* s1, Node* s2) { // Do not use superword for non-primitives BasicType bt1 = velt_basic_type(s1); @@ -831,13 +713,7 @@ bool SuperWord::stmts_can_pack(Node* s1, Node* s2, int align) { if ((independent(s1, s2) && have_similar_inputs(s1, s2)) || reduction(s1, s2)) { if (!_pairset.is_left(s1) && !_pairset.is_right(s2)) { if (!s1->is_Mem() || are_adjacent_refs(s1, s2)) { - int s1_align = alignment(s1); - int s2_align = alignment(s2); - if (s1_align == top_align || s1_align == align) { - if (s2_align == top_align || s2_align == align + data_size(s1)) { - return true; - } - } + return true; } } } @@ -1013,16 +889,6 @@ bool VLoopReductions::is_marked_reduction_pair(const Node* s1, const Node* s2) c return false; } -//------------------------------set_alignment--------------------------- -void SuperWord::set_alignment(Node* s1, Node* s2, int align) { - set_alignment(s1, align); - if (align == top_align || align == bottom_align) { - set_alignment(s2, align); - } else { - set_alignment(s2, align + data_size(s1)); - } -} - // Extend pairset by following use->def and def->use links from pair members. void SuperWord::extend_pairset_with_more_pairs_by_following_use_and_def() { bool changed; @@ -1058,57 +924,25 @@ void SuperWord::extend_pairset_with_more_pairs_by_following_use_and_def() { #endif } -//------------------------------adjust_alignment_for_type_conversion--------------------------------- -// Adjust the target alignment if conversion between different data size exists in def-use nodes. -int SuperWord::adjust_alignment_for_type_conversion(Node* s, Node* t, int align) { - // Do not use superword for non-primitives - BasicType bt1 = velt_basic_type(s); - BasicType bt2 = velt_basic_type(t); - if (!is_java_primitive(bt1) || !is_java_primitive(bt2)) { - return align; - } - if (longer_type_for_conversion(s) != T_ILLEGAL || - longer_type_for_conversion(t) != T_ILLEGAL) { - align = align / data_size(s) * data_size(t); - } - return align; -} - bool SuperWord::extend_pairset_with_more_pairs_by_following_def(Node* s1, Node* s2) { assert(_pairset.is_pair(s1, s2), "(s1, s2) must be a pair"); assert(s1->req() == s2->req(), "just checking"); - assert(alignment(s1) + data_size(s1) == alignment(s2), "just checking"); if (s1->is_Load()) return false; -#ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print_cr("SuperWord::extend_pairset_with_more_pairs_by_following_def: s1 %d, align %d", - s1->_idx, alignment(s1)); - } -#endif bool changed = false; int start = s1->is_Store() ? MemNode::ValueIn : 1; int end = s1->is_Store() ? MemNode::ValueIn+1 : s1->req(); for (int j = start; j < end; j++) { - int align = alignment(s1); Node* t1 = s1->in(j); Node* t2 = s2->in(j); if (!in_bb(t1) || !in_bb(t2) || t1->is_Mem() || t2->is_Mem()) { // Only follow non-memory nodes in block - we do not want to resurrect misaligned packs. continue; } - align = adjust_alignment_for_type_conversion(s1, t1, align); - if (stmts_can_pack(t1, t2, align)) { + if (can_pack_into_pair(t1, t2)) { if (estimate_cost_savings_when_packing_as_pair(t1, t2) >= 0) { _pairset.add_pair(t1, t2); -#ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print_cr("SuperWord::extend_pairset_with_more_pairs_by_following_def: set_alignment(%d, %d, %d)", - t1->_idx, t2->_idx, align); - } -#endif - set_alignment(t1, t2, align); changed = true; } } @@ -1122,17 +956,9 @@ bool SuperWord::extend_pairset_with_more_pairs_by_following_def(Node* s1, Node* bool SuperWord::extend_pairset_with_more_pairs_by_following_use(Node* s1, Node* s2) { assert(_pairset.is_pair(s1, s2), "(s1, s2) must be a pair"); assert(s1->req() == s2->req(), "just checking"); - assert(alignment(s1) + data_size(s1) == alignment(s2), "just checking"); if (s1->is_Store()) return false; - int align = alignment(s1); -#ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print_cr("SuperWord::extend_pairset_with_more_pairs_by_following_use: s1 %d, align %d", - s1->_idx, align); - } -#endif int savings = -1; Node* u1 = nullptr; Node* u2 = nullptr; @@ -1150,28 +976,18 @@ bool SuperWord::extend_pairset_with_more_pairs_by_following_use(Node* s1, Node* } if (t2->Opcode() == Op_AddI && t2 == cl()->incr()) continue; // don't mess with the iv if (order_inputs_of_uses_to_match_def_pair(s1, s2, t1, t2) != PairOrderStatus::Ordered) { continue; } - int adjusted_align = alignment(s1); - adjusted_align = adjust_alignment_for_type_conversion(s1, t1, adjusted_align); - if (stmts_can_pack(t1, t2, adjusted_align)) { + if (can_pack_into_pair(t1, t2)) { int my_savings = estimate_cost_savings_when_packing_as_pair(t1, t2); if (my_savings > savings) { savings = my_savings; u1 = t1; u2 = t2; - align = adjusted_align; } } } } if (savings >= 0) { _pairset.add_pair(u1, u2); -#ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print_cr("SuperWord::extend_pairset_with_more_pairs_by_following_use: set_alignment(%d, %d, %d)", - u1->_idx, u2->_idx, align); - } -#endif - set_alignment(u1, u2, align); return true; // changed } return false; // no change @@ -1814,6 +1630,11 @@ uint SuperWord::max_implemented_size(const Node_List* pack) { } } +// Java API for Long.bitCount/numberOfLeadingZeros/numberOfTrailingZeros +// returns int type, but Vector API for them returns long type. To unify +// the implementation in backend, superword splits the vector implementation +// for Java API into an execution node with long type plus another node +// converting long to int. bool SuperWord::requires_long_to_int_conversion(int opc) { switch(opc) { case Op_PopCountL: @@ -2948,7 +2769,17 @@ uint SuperWord::find_use_def_boundary(const Node_List* pack) const { bool SuperWord::is_vector_use(Node* use, int u_idx) const { Node_List* u_pk = get_pack(use); if (u_pk == nullptr) return false; - if (is_marked_reduction(use)) return true; + + // Reduction: first input is internal connection. + if (is_marked_reduction(use) && u_idx == 1) { +#ifdef ASSERT + for (uint i = 1; i < u_pk->size(); i++) { + assert(u_pk->at(i - 1) == u_pk->at(i)->in(1), "internal connection"); + } +#endif + return true; + } + Node* def = use->in(u_idx); Node_List* d_pk = get_pack(def); if (d_pk == nullptr) { @@ -2975,51 +2806,64 @@ bool SuperWord::is_vector_use(Node* use, int u_idx) const { return true; } + if (!is_velt_basic_type_compatible_use_def(use, def)) { + return false; + } + if (VectorNode::is_muladds2i(use)) { - // MulAddS2I takes shorts and produces ints - hence the special checks - // on alignment and size. + // MulAddS2I takes shorts and produces ints. if (u_pk->size() * 2 != d_pk->size()) { return false; } - for (uint i = 0; i < MIN2(d_pk->size(), u_pk->size()); i++) { - Node* ui = u_pk->at(i); - Node* di = d_pk->at(i); - if (alignment(ui) != alignment(di) * 2) { - return false; - } - } return true; } - if (u_pk->size() != d_pk->size()) + if (u_pk->size() != d_pk->size()) { return false; - - if (longer_type_for_conversion(use) != T_ILLEGAL) { - // These opcodes take a type of a kind of size and produce a type of - // another size - hence the special checks on alignment and size. - for (uint i = 0; i < u_pk->size(); i++) { - Node* ui = u_pk->at(i); - Node* di = d_pk->at(i); - if (ui->in(u_idx) != di) { - return false; - } - if (alignment(ui) / type2aelembytes(velt_basic_type(ui)) != - alignment(di) / type2aelembytes(velt_basic_type(di))) { - return false; - } - } - return true; } for (uint i = 0; i < u_pk->size(); i++) { Node* ui = u_pk->at(i); Node* di = d_pk->at(i); - if (ui->in(u_idx) != di || alignment(ui) != alignment(di)) + if (ui->in(u_idx) != di) { return false; + } } return true; } +// Check if the output type of def is compatible with the input type of use, i.e. if the +// types have the same size. +bool SuperWord::is_velt_basic_type_compatible_use_def(Node* use, Node* def) const { + assert(in_bb(def) && in_bb(use), "both use and def are in loop"); + + // Conversions are trivially compatible. + if (VectorNode::is_convert_opcode(use->Opcode())) { + return true; + } + + BasicType use_bt = velt_basic_type(use); + BasicType def_bt = velt_basic_type(def); + + assert(is_java_primitive(use_bt), "sanity %s", type2name(use_bt)); + assert(is_java_primitive(def_bt), "sanity %s", type2name(def_bt)); + + // Nodes like Long.bitCount: expect long input, and int output. + if (requires_long_to_int_conversion(use->Opcode())) { + return type2aelembytes(def_bt) == 8 && + type2aelembytes(use_bt) == 4; + } + + // MulAddS2I: expect short input, and int output. + if (VectorNode::is_muladds2i(use)) { + return type2aelembytes(def_bt) == 2 && + type2aelembytes(use_bt) == 4; + } + + // Default case: input size of use equals output size of def. + return type2aelembytes(use_bt) == type2aelembytes(def_bt); +} + // Return nullptr if success, else failure message VStatus VLoopBody::construct() { assert(_body.is_empty(), "body is empty"); @@ -3150,12 +2994,6 @@ VStatus VLoopBody::construct() { return VStatus::make_success(); } -// Initialize per node info -void SuperWord::initialize_node_info() { - Node* last = body().at(body().length() - 1); - grow_node_info(bb_idx(last)); -} - BasicType SuperWord::longer_type_for_conversion(Node* n) const { if (!(VectorNode::is_convert_opcode(n->Opcode()) || requires_long_to_int_conversion(n->Opcode())) || @@ -3177,34 +3015,6 @@ BasicType SuperWord::longer_type_for_conversion(Node* n) const { : (src_size > dst_size ? src_t : dst_t); } -int SuperWord::max_vector_size_in_def_use_chain(Node* n) { - BasicType bt = velt_basic_type(n); - BasicType vt = bt; - - // find the longest type among def nodes. - uint start, end; - VectorNode::vector_operands(n, &start, &end); - for (uint i = start; i < end; ++i) { - Node* input = n->in(i); - if (!in_bb(input)) continue; - BasicType newt = longer_type_for_conversion(input); - vt = (newt == T_ILLEGAL) ? vt : newt; - } - - // find the longest type among use nodes. - for (uint i = 0; i < n->outcnt(); ++i) { - Node* output = n->raw_out(i); - if (!in_bb(output)) continue; - BasicType newt = longer_type_for_conversion(output); - vt = (newt == T_ILLEGAL) ? vt : newt; - } - - int max = Matcher::max_vector_size_auto_vectorization(vt); - // If now there is no vectors for the longest type, the nodes with the longest - // type in the def-use chain are not packed in SuperWord::stmts_can_pack. - return max < 2 ? Matcher::max_vector_size_auto_vectorization(bt) : max; -} - void VLoopTypes::compute_vector_element_type() { #ifndef PRODUCT if (_vloop.is_trace_vector_element_type()) { @@ -3308,36 +3118,6 @@ void VLoopTypes::compute_vector_element_type() { #endif } -//------------------------------memory_alignment--------------------------- -// Alignment within a vector memory reference -int SuperWord::memory_alignment(MemNode* s, int iv_adjust) { -#ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print("SuperWord::memory_alignment within a vector memory reference for %d: ", s->_idx); s->dump(); - } -#endif - const VPointer& p = vpointer(s); - if (!p.valid()) { - NOT_PRODUCT(if(is_trace_superword_alignment()) tty->print_cr("SuperWord::memory_alignment: VPointer p invalid, return bottom_align");) - return bottom_align; - } - int vw = get_vw_bytes_special(s); - if (vw < 2) { - NOT_PRODUCT(if(is_trace_superword_alignment()) tty->print_cr("SuperWord::memory_alignment: vector_width_in_bytes < 2, return bottom_align");) - return bottom_align; // No vectors for this type - } - int offset = p.offset_in_bytes(); - offset += iv_adjust*p.memory_size(); - int off_rem = offset % vw; - int off_mod = off_rem >= 0 ? off_rem : off_rem + vw; -#ifndef PRODUCT - if (is_trace_superword_alignment()) { - tty->print_cr("SuperWord::memory_alignment: off_rem = %d, off_mod = %d (offset = %d)", off_rem, off_mod, offset); - } -#endif - return off_mod; -} - // Smallest type containing range of values const Type* VLoopTypes::container_type(Node* n) const { if (n->is_Mem()) { @@ -3794,10 +3574,6 @@ void VLoopBody::print() const { } #endif -// ========================= SWNodeInfo ===================== - -const SWNodeInfo SWNodeInfo::initial; - // // --------------------------------- vectorization/simd ----------------------------------- // diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 159032d94b9..a07cfcd5b18 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -384,18 +384,6 @@ class PackSet : public StackObj { NOT_PRODUCT(static void print_pack(Node_List* pack);) }; -// ========================= SuperWord ===================== - -// -----------------------------SWNodeInfo--------------------------------- -// Per node info needed by SuperWord -class SWNodeInfo { - public: - int _alignment; // memory alignment for a node - - SWNodeInfo() : _alignment(-1) {} - static const SWNodeInfo initial; -}; - // -----------------------------SuperWord--------------------------------- // Transforms scalar operations into packed (superword) operations. class SuperWord : public ResourceObj { @@ -407,9 +395,6 @@ class SuperWord : public ResourceObj { // VSharedData, and reused over many AutoVectorizations. Arena _arena; - enum consts { top_align = -1, bottom_align = -666 }; - - GrowableArray _node_info; // Info needed per node CloneMap& _clone_map; // map of nodes created in cloning PairSet _pairset; @@ -461,6 +446,11 @@ class SuperWord : public ResourceObj { return _vloop_analyzer.body().bb_idx(n); } + template + void for_each_mem(Callback callback) const { + return _vloop_analyzer.body().for_each_mem(callback); + } + // VLoopTypes accessors const Type* velt_type(Node* n) const { return _vloop_analyzer.types().velt_type(n); @@ -506,11 +496,6 @@ class SuperWord : public ResourceObj { #ifndef PRODUCT // TraceAutoVectorization and TraceSuperWord - bool is_trace_superword_alignment() const { - // Too verbose for TraceSuperWord - return _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_ALIGNMENT); - } - bool is_trace_superword_adjacent_memops() const { return TraceSuperWord || _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_ADJACENT_MEMOPS); @@ -531,15 +516,9 @@ class SuperWord : public ResourceObj { _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_INFO); } - bool is_trace_superword_verbose() const { - // Too verbose for TraceSuperWord - return _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_VERBOSE); - } - bool is_trace_superword_any() const { return TraceSuperWord || is_trace_align_vector() || - _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_ALIGNMENT) || _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_ADJACENT_MEMOPS) || _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_REJECTIONS) || _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_PACKSET) || @@ -549,7 +528,7 @@ class SuperWord : public ResourceObj { bool is_trace_align_vector() const { return _vloop.vtrace().is_trace(TraceAutoVectorizationTag::ALIGN_VECTOR) || - is_trace_superword_verbose(); + _vloop.vtrace().is_trace(TraceAutoVectorizationTag::SW_VERBOSE); } #endif @@ -566,37 +545,28 @@ class SuperWord : public ResourceObj { // Accessors Arena* arena() { return &_arena; } - int get_vw_bytes_special(MemNode* s); - - // Ensure node_info contains element "i" - void grow_node_info(int i) { if (i >= _node_info.length()) _node_info.at_put_grow(i, SWNodeInfo::initial); } - // should we align vector memory references on this platform? bool vectors_should_be_aligned() { return !Matcher::misaligned_vectors_ok() || AlignVector; } - // memory alignment for a node - int alignment(Node* n) const { return _node_info.adr_at(bb_idx(n))->_alignment; } - void set_alignment(Node* n, int a) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_alignment = a; } - - // is pack good for converting into one vector node replacing bunches of Cmp, Bool, CMov nodes. - static bool requires_long_to_int_conversion(int opc); // For pack p, are all idx operands the same? bool same_inputs(const Node_List* p, int idx) const; + // CloneMap utilities bool same_origin_idx(Node* a, Node* b) const; bool same_generation(Node* a, Node* b) const; private: bool SLP_extract(); - // Find the adjacent memory references and create pack pairs for them. - void find_adjacent_refs(); - // Find a memory reference to align the loop induction variable to. - MemNode* find_align_to_ref(Node_List &memops, int &idx); - // Calculate loop's iv adjustment for this memory ops. - int get_iv_adjustment(MemNode* mem); - - // Can s1 and s2 be in a pack with s1 immediately preceding s2 and s1 aligned at "align" - bool stmts_can_pack(Node* s1, Node* s2, int align); + + // Find the "seed" memops pairs. These are pairs that we strongly suspect would lead to vectorization. + void create_adjacent_memop_pairs(); + void collect_valid_vpointers(GrowableArray& vpointers); + void create_adjacent_memop_pairs_in_all_groups(const GrowableArray& vpointers); + static int find_group_end(const GrowableArray& vpointers, int group_start); + void create_adjacent_memop_pairs_in_one_group(const GrowableArray& vpointers, const int group_start, int group_end); + + // Various methods to check if we can pack two nodes. + bool can_pack_into_pair(Node* s1, Node* s2); // Is s1 immediately before s2 in memory? bool are_adjacent_refs(Node* s1, Node* s2) const; // Are s1 and s2 similar? @@ -606,8 +576,6 @@ class SuperWord : public ResourceObj { // For a node pair (s1, s2) which is isomorphic and independent, // do s1 and s2 have similar input edges? bool have_similar_inputs(Node* s1, Node* s2); - void set_alignment(Node* s1, Node* s2, int align); - int adjust_alignment_for_type_conversion(Node* s, Node* t, int align); void extend_pairset_with_more_pairs_by_following_use_and_def(); bool extend_pairset_with_more_pairs_by_following_def(Node* s1, Node* s2); @@ -661,16 +629,15 @@ class SuperWord : public ResourceObj { // Is use->in(u_idx) a vector use? bool is_vector_use(Node* use, int u_idx) const; - // Initialize per node info - void initialize_node_info(); // Return the longer type for vectorizable type-conversion node or illegal type for other nodes. BasicType longer_type_for_conversion(Node* n) const; - // Find the longest type in def-use chain for packed nodes, and then compute the max vector size. - int max_vector_size_in_def_use_chain(Node* n); + + static bool requires_long_to_int_conversion(int opc); + + bool is_velt_basic_type_compatible_use_def(Node* use, Node* def) const; static LoadNode::ControlDependency control_dependency(Node_List* p); - // Alignment within a vector memory reference - int memory_alignment(MemNode* s, int iv_adjust); + // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. void determine_mem_ref_and_aw_for_main_loop_alignment(); void adjust_pre_loop_limit_to_align_main_loop_vectors(); diff --git a/src/hotspot/share/opto/traceAutoVectorizationTag.hpp b/src/hotspot/share/opto/traceAutoVectorizationTag.hpp index b5e818efae3..3aae04c9453 100644 --- a/src/hotspot/share/opto/traceAutoVectorizationTag.hpp +++ b/src/hotspot/share/opto/traceAutoVectorizationTag.hpp @@ -37,8 +37,7 @@ flags(TYPES, "Trace VLoopTypes") \ flags(POINTERS, "Trace VLoopPointers") \ flags(DEPENDENCY_GRAPH, "Trace VLoopDependencyGraph") \ - flags(SW_ALIGNMENT, "Trace SuperWord alignment analysis") \ - flags(SW_ADJACENT_MEMOPS, "Trace SuperWord::find_adjacent_refs") \ + flags(SW_ADJACENT_MEMOPS, "Trace SuperWord::find_adjacent_memop_pairs") \ flags(SW_REJECTIONS, "Trace SuperWord rejections (non vectorizations)") \ flags(SW_PACKSET, "Trace SuperWord packset at different stages") \ flags(SW_INFO, "Trace SuperWord info (equivalent to TraceSuperWord)") \ @@ -115,7 +114,6 @@ class TraceAutoVectorizationTagValidator { } else if (ALL == tag) { _tags.set_range(0, TRACE_AUTO_VECTORIZATION_TAG_NUM); } else if (SW_VERBOSE == tag) { - _tags.at_put(SW_ALIGNMENT, set_bit); _tags.at_put(SW_ADJACENT_MEMOPS, set_bit); _tags.at_put(SW_REJECTIONS, set_bit); _tags.at_put(SW_PACKSET, set_bit); diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 3ef6ae02534..b31f6ace5a6 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -1616,21 +1616,23 @@ bool LibraryCallKit::inline_vector_reduction() { } Node* init = ReductionNode::make_identity_con_scalar(gvn(), opc, elem_bt); - Node* value = nullptr; - if (mask == nullptr) { - assert(!is_masked_op, "Masked op needs the mask value never null"); - value = ReductionNode::make(opc, nullptr, init, opd, elem_bt); - } else { - if (use_predicate) { - value = ReductionNode::make(opc, nullptr, init, opd, elem_bt); - value->add_req(mask); - value->add_flag(Node::Flag_is_predicated_vector); - } else { - Node* reduce_identity = gvn().transform(VectorNode::scalar2vector(init, num_elem, Type::get_const_basic_type(elem_bt))); - value = gvn().transform(new VectorBlendNode(reduce_identity, opd, mask)); - value = ReductionNode::make(opc, nullptr, init, value, elem_bt); - } + Node* value = opd; + + assert(mask != nullptr || !is_masked_op, "Masked op needs the mask value never null"); + if (mask != nullptr && !use_predicate) { + Node* reduce_identity = gvn().transform(VectorNode::scalar2vector(init, num_elem, Type::get_const_basic_type(elem_bt))); + value = gvn().transform(new VectorBlendNode(reduce_identity, value, mask)); } + + // Make an unordered Reduction node. This affects only AddReductionVF/VD and MulReductionVF/VD, + // as these operations are allowed to be associative (not requiring strict order) in VectorAPI. + value = ReductionNode::make(opc, nullptr, init, value, elem_bt, /* requires_strict_order */ false); + + if (mask != nullptr && use_predicate) { + value->add_req(mask); + value->add_flag(Node::Flag_is_predicated_vector); + } + value = gvn().transform(value); Node* bits = nullptr; diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index 9e6bc7e5939..ac575d7192c 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -202,7 +202,7 @@ void VLoopVPointers::allocate_vpointers_array() { void VLoopVPointers::compute_and_cache_vpointers() { int pointers_idx = 0; - _body.for_each_mem([&] (const MemNode* mem, int bb_idx) { + _body.for_each_mem([&] (MemNode* const mem, int bb_idx) { // Placement new: construct directly into the array. ::new (&_vpointers[pointers_idx]) VPointer(mem, _vloop); _bb_idx_to_vpointer.at_put(bb_idx, pointers_idx); @@ -410,7 +410,7 @@ void VLoopDependencyGraph::PredsIterator::next() { int VPointer::Tracer::_depth = 0; #endif -VPointer::VPointer(const MemNode* mem, const VLoop& vloop, +VPointer::VPointer(MemNode* const mem, const VLoop& vloop, Node_Stack* nstack, bool analyze_only) : _mem(mem), _vloop(vloop), _base(nullptr), _adr(nullptr), _scale(0), _offset(0), _invar(nullptr), @@ -807,10 +807,50 @@ void VPointer::maybe_add_to_invar(Node* new_invar, bool negate) { _invar = register_if_new(add); } +// To be in the same group, two VPointers must be the same, +// except for the offset. +int VPointer::cmp_for_sort_by_group(const VPointer** p1, const VPointer** p2) { + const VPointer* a = *p1; + const VPointer* b = *p2; + + int cmp_base = a->base()->_idx - b->base()->_idx; + if (cmp_base != 0) { return cmp_base; } + + int cmp_opcode = a->mem()->Opcode() - b->mem()->Opcode(); + if (cmp_opcode != 0) { return cmp_opcode; } + + int cmp_scale = a->scale_in_bytes() - b->scale_in_bytes(); + if (cmp_scale != 0) { return cmp_scale; } + + int cmp_invar = (a->invar() == nullptr ? 0 : a->invar()->_idx) - + (b->invar() == nullptr ? 0 : b->invar()->_idx); + return cmp_invar; +} + +// We compare by group, then by offset, and finally by node idx. +int VPointer::cmp_for_sort(const VPointer** p1, const VPointer** p2) { + int cmp_group = cmp_for_sort_by_group(p1, p2); + if (cmp_group != 0) { return cmp_group; } + + const VPointer* a = *p1; + const VPointer* b = *p2; + + int cmp_offset = a->offset_in_bytes() - b->offset_in_bytes(); + if (cmp_offset != 0) { return cmp_offset; } + + return a->mem()->_idx - b->mem()->_idx; +} + #ifndef PRODUCT // Function for printing the fields of a VPointer void VPointer::print() const { tty->print("VPointer[mem: %4d %10s, ", _mem->_idx, _mem->Name()); + + if (!valid()) { + tty->print_cr("invalid]"); + return; + } + tty->print("base: %4d, ", _base != nullptr ? _base->_idx : 0); tty->print("adr: %4d, ", _adr != nullptr ? _adr->_idx : 0); diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index 6840b01bb93..0acc78ed1a1 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -669,7 +669,7 @@ class VLoopAnalyzer : StackObj { // operation in a counted loop for vectorizable analysis. class VPointer : public ArenaObj { protected: - const MemNode* _mem; // My memory reference node + MemNode* const _mem; // My memory reference node const VLoop& _vloop; Node* _base; // null if unsafe nonheap reference @@ -711,12 +711,12 @@ class VPointer : public ArenaObj { NotComparable = (Less | Greater | Equal) }; - VPointer(const MemNode* mem, const VLoop& vloop) : + VPointer(MemNode* const mem, const VLoop& vloop) : VPointer(mem, vloop, nullptr, false) {} - VPointer(const MemNode* mem, const VLoop& vloop, Node_Stack* nstack) : + VPointer(MemNode* const mem, const VLoop& vloop, Node_Stack* nstack) : VPointer(mem, vloop, nstack, true) {} private: - VPointer(const MemNode* mem, const VLoop& vloop, + VPointer(MemNode* const mem, const VLoop& vloop, Node_Stack* nstack, bool analyze_only); // Following is used to create a temporary object during // the pattern match of an address expression. @@ -729,7 +729,7 @@ class VPointer : public ArenaObj { Node* base() const { return _base; } Node* adr() const { return _adr; } - const MemNode* mem() const { return _mem; } + MemNode* mem() const { return _mem; } int scale_in_bytes() const { return _scale; } Node* invar() const { return _invar; } int offset_in_bytes() const { return _offset; } @@ -781,6 +781,11 @@ class VPointer : public ArenaObj { static bool equal(int cmp) { return cmp == Equal; } static bool comparable(int cmp) { return cmp < NotComparable; } + // We need to be able to sort the VPointer to efficiently group the + // memops into groups, and to find adjacent memops. + static int cmp_for_sort_by_group(const VPointer** p1, const VPointer** p2); + static int cmp_for_sort(const VPointer** p1, const VPointer** p2); + NOT_PRODUCT( void print() const; ) #ifndef PRODUCT diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 600795bbc73..d560f112039 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -172,7 +172,7 @@ int VectorNode::opcode(int sopc, BasicType bt) { return (is_integral_type(bt) ? Op_ReverseV : 0); case Op_ReverseBytesS: case Op_ReverseBytesUS: - // Subword operations in superword usually don't have precise info + // Subword operations in auto vectorization usually don't have precise info // about signedness. But the behavior of reverseBytes for short and // char are exactly the same. return ((bt == T_SHORT || bt == T_CHAR) ? Op_ReverseBytesV : 0); @@ -388,7 +388,7 @@ int VectorNode::scalar_opcode(int sopc, BasicType bt) { } // Limits on vector size (number of elements) for auto-vectorization. -bool VectorNode::vector_size_supported_superword(const BasicType bt, int size) { +bool VectorNode::vector_size_supported_auto_vectorization(const BasicType bt, int size) { return Matcher::max_vector_size_auto_vectorization(bt) >= size && Matcher::min_vector_size(bt) <= size; } @@ -398,7 +398,7 @@ bool VectorNode::vector_size_supported_superword(const BasicType bt, int size) { bool VectorNode::implemented(int opc, uint vlen, BasicType bt) { if (is_java_primitive(bt) && (vlen > 1) && is_power_of_2(vlen) && - vector_size_supported_superword(bt, vlen)) { + vector_size_supported_auto_vectorization(bt, vlen)) { int vopc = VectorNode::opcode(opc, bt); // For rotate operation we will do a lazy de-generation into // OrV/LShiftV/URShiftV pattern if the target does not support @@ -414,14 +414,6 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) { return false; } -bool VectorNode::is_type_transition_short_to_int(Node* n) { - return n->Opcode() == Op_MulAddS2I; -} - -bool VectorNode::is_type_transition_to_int(Node* n) { - return is_type_transition_short_to_int(n); -} - bool VectorNode::is_muladds2i(const Node* n) { return n->Opcode() == Op_MulAddS2I; } @@ -1304,7 +1296,8 @@ int ReductionNode::opcode(int opc, BasicType bt) { } // Return the appropriate reduction node. -ReductionNode* ReductionNode::make(int opc, Node *ctrl, Node* n1, Node* n2, BasicType bt) { +ReductionNode* ReductionNode::make(int opc, Node* ctrl, Node* n1, Node* n2, BasicType bt, + bool requires_strict_order) { int vopc = opcode(opc, bt); @@ -1314,17 +1307,17 @@ ReductionNode* ReductionNode::make(int opc, Node *ctrl, Node* n1, Node* n2, Basi switch (vopc) { case Op_AddReductionVI: return new AddReductionVINode(ctrl, n1, n2); case Op_AddReductionVL: return new AddReductionVLNode(ctrl, n1, n2); - case Op_AddReductionVF: return new AddReductionVFNode(ctrl, n1, n2); - case Op_AddReductionVD: return new AddReductionVDNode(ctrl, n1, n2); + case Op_AddReductionVF: return new AddReductionVFNode(ctrl, n1, n2, requires_strict_order); + case Op_AddReductionVD: return new AddReductionVDNode(ctrl, n1, n2, requires_strict_order); case Op_MulReductionVI: return new MulReductionVINode(ctrl, n1, n2); case Op_MulReductionVL: return new MulReductionVLNode(ctrl, n1, n2); - case Op_MulReductionVF: return new MulReductionVFNode(ctrl, n1, n2); - case Op_MulReductionVD: return new MulReductionVDNode(ctrl, n1, n2); - case Op_MinReductionV: return new MinReductionVNode(ctrl, n1, n2); - case Op_MaxReductionV: return new MaxReductionVNode(ctrl, n1, n2); - case Op_AndReductionV: return new AndReductionVNode(ctrl, n1, n2); - case Op_OrReductionV: return new OrReductionVNode(ctrl, n1, n2); - case Op_XorReductionV: return new XorReductionVNode(ctrl, n1, n2); + case Op_MulReductionVF: return new MulReductionVFNode(ctrl, n1, n2, requires_strict_order); + case Op_MulReductionVD: return new MulReductionVDNode(ctrl, n1, n2, requires_strict_order); + case Op_MinReductionV: return new MinReductionVNode (ctrl, n1, n2); + case Op_MaxReductionV: return new MaxReductionVNode (ctrl, n1, n2); + case Op_AndReductionV: return new AndReductionVNode (ctrl, n1, n2); + case Op_OrReductionV: return new OrReductionVNode (ctrl, n1, n2); + case Op_XorReductionV: return new XorReductionVNode (ctrl, n1, n2); default: assert(false, "unknown node: %s", NodeClassNames[vopc]); return nullptr; @@ -1419,7 +1412,7 @@ bool VectorCastNode::implemented(int opc, uint vlen, BasicType src_type, BasicTy if (is_java_primitive(dst_type) && is_java_primitive(src_type) && (vlen > 1) && is_power_of_2(vlen) && - VectorNode::vector_size_supported_superword(dst_type, vlen)) { + VectorNode::vector_size_supported_auto_vectorization(dst_type, vlen)) { int vopc = VectorCastNode::opcode(opc, src_type); return vopc > 0 && Matcher::match_rule_supported_auto_vectorization(vopc, vlen, dst_type); } @@ -1513,7 +1506,7 @@ Node* ReductionNode::make_identity_con_scalar(PhaseGVN& gvn, int sopc, BasicType bool ReductionNode::implemented(int opc, uint vlen, BasicType bt) { if (is_java_primitive(bt) && (vlen > 1) && is_power_of_2(vlen) && - VectorNode::vector_size_supported_superword(bt, vlen)) { + VectorNode::vector_size_supported_auto_vectorization(bt, vlen)) { int vopc = ReductionNode::opcode(opc, bt); return vopc != opc && Matcher::match_rule_supported_auto_vectorization(vopc, vlen, bt); } diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index a9ded1bfa2d..6c5402eb511 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -96,12 +96,10 @@ class VectorNode : public TypeNode { static int scalar_opcode(int vopc, BasicType bt); // vector_opc -> scalar_opc // Limits on vector size (number of elements) for auto-vectorization. - static bool vector_size_supported_superword(const BasicType bt, int size); + static bool vector_size_supported_auto_vectorization(const BasicType bt, int size); static bool implemented(int opc, uint vlen, BasicType bt); static bool is_shift(Node* n); static bool is_vshift_cnt(Node* n); - static bool is_type_transition_short_to_int(Node* n); - static bool is_type_transition_to_int(Node* n); static bool is_muladds2i(const Node* n); static bool is_roundopD(Node* n); static bool is_scalar_rotate(Node* n); @@ -205,7 +203,9 @@ class ReductionNode : public Node { init_class_id(Class_Reduction); } - static ReductionNode* make(int opc, Node* ctrl, Node* in1, Node* in2, BasicType bt); + static ReductionNode* make(int opc, Node* ctrl, Node* in1, Node* in2, BasicType bt, + // This only effects floating-point add and mul reductions. + bool requires_strict_order = true); static int opcode(int opc, BasicType bt); static bool implemented(int opc, uint vlen, BasicType bt); // Make an identity scalar (zero for add, one for mul, etc) for scalar opc. @@ -227,47 +227,97 @@ class ReductionNode : public Node { // Needed for proper cloning. virtual uint size_of() const { return sizeof(*this); } -}; -//---------------------------UnorderedReductionNode------------------------------------- -// Order of reduction does not matter. Example int add. Not true for float add. -class UnorderedReductionNode : public ReductionNode { -public: - UnorderedReductionNode(Node * ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) { - init_class_id(Class_UnorderedReduction); + // Floating-point addition and multiplication are non-associative, so + // AddReductionVF/D and MulReductionVF/D require strict ordering + // in auto-vectorization. Vector API can generate AddReductionVF/D + // and MulReductionVF/VD without strict ordering, which can benefit + // some platforms. + // + // Other reductions don't need strict ordering. + virtual bool requires_strict_order() const { + return false; + } + +#ifndef PRODUCT + void dump_spec(outputStream* st) const { + if (requires_strict_order()) { + st->print("requires_strict_order"); + } else { + st->print("no_strict_order"); + } } +#endif }; //------------------------------AddReductionVINode-------------------------------------- // Vector add byte, short and int as a reduction -class AddReductionVINode : public UnorderedReductionNode { +class AddReductionVINode : public ReductionNode { public: - AddReductionVINode(Node * ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + AddReductionVINode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; //------------------------------AddReductionVLNode-------------------------------------- // Vector add long as a reduction -class AddReductionVLNode : public UnorderedReductionNode { +class AddReductionVLNode : public ReductionNode { public: - AddReductionVLNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + AddReductionVLNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; //------------------------------AddReductionVFNode-------------------------------------- // Vector add float as a reduction class AddReductionVFNode : public ReductionNode { +private: + // True if add reduction operation for floats requires strict ordering. + // As an example - The value is true when add reduction for floats is auto-vectorized + // as auto-vectorization mandates strict ordering but the value is false when this node + // is generated through VectorAPI as VectorAPI does not impose any such rules on ordering. + const bool _requires_strict_order; public: - AddReductionVFNode(Node *ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} + //_requires_strict_order is set to true by default as mandated by auto-vectorization + AddReductionVFNode(Node* ctrl, Node* in1, Node* in2, bool requires_strict_order = true) : + ReductionNode(ctrl, in1, in2), _requires_strict_order(requires_strict_order) {} + virtual int Opcode() const; + + virtual bool requires_strict_order() const { return _requires_strict_order; } + + virtual uint hash() const { return Node::hash() + _requires_strict_order; } + + virtual bool cmp(const Node& n) const { + return Node::cmp(n) && _requires_strict_order == ((ReductionNode&)n).requires_strict_order(); + } + + virtual uint size_of() const { return sizeof(*this); } }; //------------------------------AddReductionVDNode-------------------------------------- // Vector add double as a reduction class AddReductionVDNode : public ReductionNode { +private: + // True if add reduction operation for doubles requires strict ordering. + // As an example - The value is true when add reduction for doubles is auto-vectorized + // as auto-vectorization mandates strict ordering but the value is false when this node + // is generated through VectorAPI as VectorAPI does not impose any such rules on ordering. + const bool _requires_strict_order; public: - AddReductionVDNode(Node *ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} + //_requires_strict_order is set to true by default as mandated by auto-vectorization + AddReductionVDNode(Node* ctrl, Node* in1, Node* in2, bool requires_strict_order = true) : + ReductionNode(ctrl, in1, in2), _requires_strict_order(requires_strict_order) {} + virtual int Opcode() const; + + virtual bool requires_strict_order() const { return _requires_strict_order; } + + virtual uint hash() const { return Node::hash() + _requires_strict_order; } + + virtual bool cmp(const Node& n) const { + return Node::cmp(n) && _requires_strict_order == ((ReductionNode&)n).requires_strict_order(); + } + + virtual uint size_of() const { return sizeof(*this); } }; //------------------------------SubVBNode-------------------------------------- @@ -402,34 +452,70 @@ class FmaVFNode : public FmaVNode { //------------------------------MulReductionVINode-------------------------------------- // Vector multiply byte, short and int as a reduction -class MulReductionVINode : public UnorderedReductionNode { +class MulReductionVINode : public ReductionNode { public: - MulReductionVINode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + MulReductionVINode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; //------------------------------MulReductionVLNode-------------------------------------- // Vector multiply int as a reduction -class MulReductionVLNode : public UnorderedReductionNode { +class MulReductionVLNode : public ReductionNode { public: - MulReductionVLNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + MulReductionVLNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; //------------------------------MulReductionVFNode-------------------------------------- // Vector multiply float as a reduction class MulReductionVFNode : public ReductionNode { + // True if mul reduction operation for floats requires strict ordering. + // As an example - The value is true when mul reduction for floats is auto-vectorized + // as auto-vectorization mandates strict ordering but the value is false when this node + // is generated through VectorAPI as VectorAPI does not impose any such rules on ordering. + const bool _requires_strict_order; public: - MulReductionVFNode(Node *ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} + //_requires_strict_order is set to true by default as mandated by auto-vectorization + MulReductionVFNode(Node* ctrl, Node* in1, Node* in2, bool requires_strict_order = true) : + ReductionNode(ctrl, in1, in2), _requires_strict_order(requires_strict_order) {} + virtual int Opcode() const; + + virtual bool requires_strict_order() const { return _requires_strict_order; } + + virtual uint hash() const { return Node::hash() + _requires_strict_order; } + + virtual bool cmp(const Node& n) const { + return Node::cmp(n) && _requires_strict_order == ((ReductionNode&)n).requires_strict_order(); + } + + virtual uint size_of() const { return sizeof(*this); } }; //------------------------------MulReductionVDNode-------------------------------------- // Vector multiply double as a reduction class MulReductionVDNode : public ReductionNode { + // True if mul reduction operation for doubles requires strict ordering. + // As an example - The value is true when mul reduction for doubles is auto-vectorized + // as auto-vectorization mandates strict ordering but the value is false when this node + // is generated through VectorAPI as VectorAPI does not impose any such rules on ordering. + const bool _requires_strict_order; public: - MulReductionVDNode(Node *ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} + //_requires_strict_order is set to true by default as mandated by auto-vectorization + MulReductionVDNode(Node* ctrl, Node* in1, Node* in2, bool requires_strict_order = true) : + ReductionNode(ctrl, in1, in2), _requires_strict_order(requires_strict_order) {} + virtual int Opcode() const; + + virtual bool requires_strict_order() const { return _requires_strict_order; } + + virtual uint hash() const { return Node::hash() + _requires_strict_order; } + + virtual bool cmp(const Node& n) const { + return Node::cmp(n) && _requires_strict_order == ((ReductionNode&)n).requires_strict_order(); + } + + virtual uint size_of() const { return sizeof(*this); } }; //------------------------------DivVFNode-------------------------------------- @@ -755,9 +841,9 @@ class AndVNode : public VectorNode { //------------------------------AndReductionVNode-------------------------------------- // Vector and byte, short, int, long as a reduction -class AndReductionVNode : public UnorderedReductionNode { +class AndReductionVNode : public ReductionNode { public: - AndReductionVNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + AndReductionVNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; @@ -772,9 +858,9 @@ class OrVNode : public VectorNode { //------------------------------OrReductionVNode-------------------------------------- // Vector xor byte, short, int, long as a reduction -class OrReductionVNode : public UnorderedReductionNode { +class OrReductionVNode : public ReductionNode { public: - OrReductionVNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + OrReductionVNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; @@ -789,25 +875,25 @@ class XorVNode : public VectorNode { //------------------------------XorReductionVNode-------------------------------------- // Vector and int, long as a reduction -class XorReductionVNode : public UnorderedReductionNode { +class XorReductionVNode : public ReductionNode { public: - XorReductionVNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + XorReductionVNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; //------------------------------MinReductionVNode-------------------------------------- // Vector min byte, short, int, long, float, double as a reduction -class MinReductionVNode : public UnorderedReductionNode { +class MinReductionVNode : public ReductionNode { public: - MinReductionVNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + MinReductionVNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; //------------------------------MaxReductionVNode-------------------------------------- // Vector min byte, short, int, long, float, double as a reduction -class MaxReductionVNode : public UnorderedReductionNode { +class MaxReductionVNode : public ReductionNode { public: - MaxReductionVNode(Node *ctrl, Node* in1, Node* in2) : UnorderedReductionNode(ctrl, in1, in2) {} + MaxReductionVNode(Node* ctrl, Node* in1, Node* in2) : ReductionNode(ctrl, in1, in2) {} virtual int Opcode() const; }; diff --git a/src/hotspot/share/prims/upcallLinker.cpp b/src/hotspot/share/prims/upcallLinker.cpp index 4b924b5302d..b02746911a8 100644 --- a/src/hotspot/share/prims/upcallLinker.cpp +++ b/src/hotspot/share/prims/upcallLinker.cpp @@ -48,7 +48,6 @@ extern struct JavaVM_ main_vm; struct UpcallContext { Thread* attachedThread; - UpcallContext() {} // Explicit constructor to address XL C compiler bug. ~UpcallContext() { if (attachedThread != nullptr) { JavaVM_ *vm = (JavaVM *)(&main_vm); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 6c98f379db0..6680851405f 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -501,17 +501,11 @@ static SpecialFlag const special_jvm_flags[] = { { "DynamicDumpSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "RequireSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "UseSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, - { "RegisterFinalizersAtInit", JDK_Version::jdk(22), JDK_Version::jdk(23), JDK_Version::jdk(24) }, { "DontYieldALot", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "OldSize", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "PreserveAllAnnotations", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "UseNotificationThread", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "UseEmptySlotsInSupers", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, -#if defined(X86) - { "UseRTMLocking", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, - { "UseRTMDeopt", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, - { "RTMRetryCount", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, -#endif // X86 // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -519,32 +513,11 @@ static SpecialFlag const special_jvm_flags[] = { { "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() }, - { "G1ConcRefinementGreenZone", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(24) }, - { "G1ConcRefinementYellowZone", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(24) }, - { "G1ConcRefinementRedZone", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(24) }, - { "G1ConcRefinementThresholdStep", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(24) }, - { "G1UseAdaptiveConcRefinement", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(24) }, - { "G1ConcRefinementServiceIntervalMillis", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(24) }, - - { "G1ConcRSLogCacheSize", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::jdk(24) }, - { "G1ConcRSHotCardLimit", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::jdk(24) }, - { "RefDiscoveryPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::jdk(24) }, - - { "AdaptiveSizePolicyCollectionCostMargin", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "MaxGCMinorPauseMillis", JDK_Version::jdk(8), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "MaxRAMFraction", JDK_Version::jdk(10), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "MinRAMFraction", JDK_Version::jdk(10), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "TLABStats", JDK_Version::jdk(12), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "GCLockerEdenExpansionPercent", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "NUMAPageScanRate", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "ProcessDistributionStride", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - - { "ParallelOldDeadWoodLimiterMean", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "ParallelOldDeadWoodLimiterStdDev", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "UseNeon", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, - { "ScavengeBeforeFullGC", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, +#if defined(X86) + { "UseRTMLocking", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, + { "UseRTMDeopt", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, + { "RTMRetryCount", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, +#endif // X86 #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif @@ -1847,14 +1820,6 @@ bool Arguments::check_vm_args_consistency() { "LockingMode == 0 (LM_MONITOR) is not fully implemented on this architecture\n"); return false; } -#endif -#if defined(X86) && !defined(ZERO) - if (LockingMode == LM_MONITOR && UseRTMForStackLocks) { - jio_fprintf(defaultStream::error_stream(), - "LockingMode == 0 (LM_MONITOR) and -XX:+UseRTMForStackLocks are mutually exclusive\n"); - - return false; - } #endif if (VerifyHeavyMonitors && LockingMode != LM_MONITOR) { jio_fprintf(defaultStream::error_stream(), diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 17487688445..cf82ad7c027 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -2076,8 +2076,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr gather_statistics(reason, action, trap_bc); // Ensure that we can record deopt. history: - // Need MDO to record RTM code generation state. - bool create_if_missing = ProfileTraps RTM_OPT_ONLY( || UseRTMLocking ); + bool create_if_missing = ProfileTraps; methodHandle profiled_method; #if INCLUDE_JVMCI @@ -2425,16 +2424,6 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr pdata->set_trap_state(tstate1); } -#if INCLUDE_RTM_OPT - // Restart collecting RTM locking abort statistic if the method - // is recompiled for a reason other than RTM state change. - // Assume that in new recompiled code the statistic could be different, - // for example, due to different inlining. - if ((reason != Reason_rtm_state_change) && (trap_mdo != nullptr) && - UseRTMDeopt && (nm->rtm_state() != ProfileRTM)) { - trap_mdo->atomic_set_rtm_state(ProfileRTM); - } -#endif // For code aging we count traps separately here, using make_not_entrant() // as a guard against simultaneous deopts in multiple threads. if (reason == Reason_tenured && trap_mdo != nullptr) { @@ -2724,7 +2713,6 @@ const char* Deoptimization::_trap_reason_name[] = { "speculate_class_check", "speculate_null_check", "speculate_null_assert", - "rtm_state_change", "unstable_if", "unstable_fused_if", "receiver_constraint", diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index 61e85d19fd7..0a2bafb3830 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -113,7 +113,6 @@ class Deoptimization : AllStatic { Reason_speculate_class_check, // saw unexpected object class from type speculation Reason_speculate_null_check, // saw unexpected null from type speculation Reason_speculate_null_assert, // saw unexpected null from type speculation - Reason_rtm_state_change, // rtm state change detected Reason_unstable_if, // a branch predicted always false was taken Reason_unstable_fused_if, // fused two ifs that had each one untaken branch. One is now taken. Reason_receiver_constraint, // receiver subtype check failed diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index 2cd7371909d..ad2e755e698 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -378,20 +378,6 @@ JVMFlag::Error NodeLimitFudgeFactorConstraintFunc(intx value, bool verbose) { } #endif // COMPILER2 -JVMFlag::Error RTMTotalCountIncrRateConstraintFunc(int value, bool verbose) { -#if INCLUDE_RTM_OPT - if (UseRTMLocking && !is_power_of_2(RTMTotalCountIncrRate)) { - JVMFlag::printError(verbose, - "RTMTotalCountIncrRate (%d) must be " - "a power of 2, resetting it to 64\n", - RTMTotalCountIncrRate); - FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64); - } -#endif - - return JVMFlag::SUCCESS; -} - #ifdef COMPILER2 JVMFlag::Error LoopStripMiningIterConstraintFunc(uintx value, bool verbose) { if (UseCountedLoopSafepoints && LoopStripMiningIter == 0) { diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp index 60adf4903a3..cfca8ecf8ee 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp @@ -49,7 +49,6 @@ f(uint, TypeProfileLevelConstraintFunc) \ f(uint, VerifyIterativeGVNConstraintFunc) \ f(intx, InitArrayShortSizeConstraintFunc) \ - f(int , RTMTotalCountIncrRateConstraintFunc) \ f(ccstrlist, DisableIntrinsicConstraintFunc) \ f(ccstrlist, ControlIntrinsicConstraintFunc) \ COMPILER2_PRESENT( \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index d78e35c4e68..5271bdcda0b 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -265,7 +265,7 @@ void print_statistics() { #endif //COMPILER1 } - if (PrintLockStatistics || PrintPreciseRTMLockingStatistics) { + if (PrintLockStatistics) { OptoRuntime::print_named_counters(); } #ifdef ASSERT diff --git a/src/hotspot/share/runtime/rtmLocking.cpp b/src/hotspot/share/runtime/rtmLocking.cpp deleted file mode 100644 index c3752882423..00000000000 --- a/src/hotspot/share/runtime/rtmLocking.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 "compiler/compilerDefinitions.hpp" - -#if INCLUDE_RTM_OPT - -#include "memory/allocation.inline.hpp" -#include "runtime/task.hpp" -#include "runtime/rtmLocking.hpp" - - -// One-shot PeriodicTask subclass for enabling RTM locking -uintx RTMLockingCounters::_calculation_flag = 0; - -class RTMLockingCalculationTask : public PeriodicTask { - public: - RTMLockingCalculationTask(size_t interval_time) : PeriodicTask(interval_time){ } - - virtual void task() { - RTMLockingCounters::_calculation_flag = 1; - // Reclaim our storage and disenroll ourself - delete this; - } -}; - -void RTMLockingCounters::init() { - if (UseRTMLocking && RTMLockingCalculationDelay > 0) { - RTMLockingCalculationTask* task = new RTMLockingCalculationTask(RTMLockingCalculationDelay); - task->enroll(); - } else { - _calculation_flag = 1; - } -} - -const char* RTMLockingCounters::_abortX_desc[ABORT_STATUS_LIMIT] = { - "abort instruction ", - "may succeed on retry", - "thread conflict ", - "buffer overflow ", - "debug or trap hit ", - "maximum nested depth" -}; - -//------------------------------print_on------------------------------- -void RTMLockingCounters::print_on(outputStream* st) const { - tty->print_cr("# rtm locks total (estimated): " UINTX_FORMAT, _total_count * RTMTotalCountIncrRate); - tty->print_cr("# rtm lock aborts (total): " UINTX_FORMAT, _abort_count); - for (int i = 0; i < ABORT_STATUS_LIMIT; i++) { - tty->print_cr("# rtm lock aborts %d (%s): " UINTX_FORMAT, i, _abortX_desc[i], _abortX_count[i]); - } -} -void RTMLockingCounters::print() const { print_on(tty); } - -#endif diff --git a/src/hotspot/share/runtime/rtmLocking.hpp b/src/hotspot/share/runtime/rtmLocking.hpp deleted file mode 100644 index db9678b17b1..00000000000 --- a/src/hotspot/share/runtime/rtmLocking.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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_RTMLOCKING_HPP -#define SHARE_RUNTIME_RTMLOCKING_HPP - -// Generate RTM (Restricted Transactional Memory) locking code for all inflated -// locks when "UseRTMLocking" option is on with normal locking mechanism as fall back -// handler. -// -// On abort/lock busy the lock will be retried a fixed number of times under RTM -// as specified by "RTMRetryCount" option. The locks which abort too often -// can be auto tuned or manually tuned. -// -// Auto-tuning can be done on an option like UseRTMDeopt and it will need abort -// ratio calculation for each lock. The abort ratio will be calculated after -// "RTMAbortThreshold" number of aborts is reached. The formulas are: -// -// Aborted transactions = abort_count * 100 -// All transactions = total_count * RTMTotalCountIncrRate -// -// Aborted transactions >= All transactions * RTMAbortRatio -// -// If "UseRTMDeopt" is on and the aborts ratio reaches "RTMAbortRatio" -// the method containing the lock will be deoptimized and recompiled with -// all locks as normal locks. If the abort ratio continues to remain low after -// "RTMLockingThreshold" locks are attempted, then the method will be deoptimized -// and recompiled with all locks as RTM locks without abort ratio calculation code. -// The abort ratio calculation can be delayed by specifying flag -// -XX:RTMLockingCalculationDelay in millisecond. -// -// For manual tuning the abort statistics for each lock needs to be provided -// to the user on some JVM option like "PrintPreciseRTMLockingStatistics". -// Based on the abort statistics users can create a .hotspot_compiler file -// or use -XX:CompileCommand=option,class::method,NoRTMLockEliding -// to specify for which methods to disable RTM locking. -// -// When UseRTMForStackLocks option is enabled along with UseRTMLocking option, -// the RTM locking code is generated for stack locks too. -// The retries, auto-tuning support and rtm locking statistics are all -// supported for stack locks just like inflated locks. - -// RTM locking counters -class RTMLockingCounters { - private: - uintx _total_count; // Total RTM locks count - uintx _abort_count; // Total aborts count - - public: - enum { ABORT_STATUS_LIMIT = 6 }; - // Counters per RTM Abort Status. Incremented with +PrintPreciseRTMLockingStatistics - // RTM uses the EAX register to communicate abort status to software. - // Following an RTM abort the EAX register has the following definition. - // - // EAX register bit position Meaning - // 0 Set if abort caused by XABORT instruction. - // 1 If set, the transaction may succeed on a retry. This bit is always clear if bit 0 is set. - // 2 Set if another logical processor conflicted with a memory address that was part of the transaction that aborted. - // 3 Set if an internal buffer overflowed. - // 4 Set if a debug breakpoint was hit. - // 5 Set if an abort occurred during execution of a nested transaction. - private: - uintx _abortX_count[ABORT_STATUS_LIMIT]; - static const char* _abortX_desc[ABORT_STATUS_LIMIT]; - - public: - static uintx _calculation_flag; - static uintx* rtm_calculation_flag_addr() { return &_calculation_flag; } - - static void init(); - - RTMLockingCounters() : _total_count(0), _abort_count(0) { - for (int i = 0; i < ABORT_STATUS_LIMIT; i++) { - _abortX_count[i] = 0; - } - } - - uintx* total_count_addr() { return &_total_count; } - - static int total_count_offset() { return (int)offset_of(RTMLockingCounters, _total_count); } - static int abort_count_offset() { return (int)offset_of(RTMLockingCounters, _abort_count); } - static int abortX_count_offset() { return (int)offset_of(RTMLockingCounters, _abortX_count[0]); } - - - bool nonzero() { return (_abort_count + _total_count) > 0; } - - void print_on(outputStream* st) const; - void print() const; -}; - -#endif // SHARE_RUNTIME_RTMLOCKING_HPP diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 74286a4ac98..773f8031e15 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -149,6 +149,8 @@ address StubRoutines::_sha3_implCompressMB = nullptr; address StubRoutines::_updateBytesCRC32 = nullptr; address StubRoutines::_crc_table_adr = nullptr; +address StubRoutines::_string_indexof_array[4] = { nullptr }; + address StubRoutines::_crc32c_table_addr = nullptr; address StubRoutines::_updateBytesCRC32C = nullptr; address StubRoutines::_updateBytesAdler32 = nullptr; diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp index 65b0c0d2f26..762a6edf590 100644 --- a/src/hotspot/share/runtime/stubRoutines.hpp +++ b/src/hotspot/share/runtime/stubRoutines.hpp @@ -232,6 +232,8 @@ class StubRoutines: AllStatic { static address _updateBytesCRC32; static address _crc_table_adr; + static address _string_indexof_array[4]; + static address _crc32c_table_addr; static address _updateBytesCRC32C; static address _updateBytesAdler32; diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 051c2901fa0..e7c425b2b8c 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -109,9 +109,6 @@ #ifdef COMPILER2 #include "opto/idealGraphPrinter.hpp" #endif -#if INCLUDE_RTM_OPT -#include "runtime/rtmLocking.hpp" -#endif #if INCLUDE_JFR #include "jfr/jfr.hpp" #endif @@ -802,10 +799,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { StatSampler::engage(); if (CheckJNICalls) JniPeriodicChecker::engage(); -#if INCLUDE_RTM_OPT - RTMLockingCounters::init(); -#endif - call_postVMInitHook(THREAD); // The Java side of PostVMInitHook.run must deal with all // exceptions and provide means of diagnosis. @@ -1328,6 +1321,15 @@ void Threads::print_on(outputStream* st, bool print_stacks, p->trace_stack(); } else { p->print_stack_on(st); + const oop thread_oop = p->threadObj(); + if (thread_oop != nullptr) { + if (p->is_vthread_mounted()) { + const oop vt = p->vthread(); + assert(vt != nullptr, "vthread should not be null when vthread is mounted"); + st->print_cr(" Mounted virtual thread \"%s\" #" INT64_FORMAT, JavaThread::name_for(vt), (int64_t)java_lang_Thread::thread_id(vt)); + p->print_vthread_stack_on(st); + } + } } } st->cr(); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 4381bb973bb..8ff766af128 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -2259,7 +2259,6 @@ declare_constant(Deoptimization::Reason_speculate_class_check) \ declare_constant(Deoptimization::Reason_speculate_null_check) \ declare_constant(Deoptimization::Reason_speculate_null_assert) \ - declare_constant(Deoptimization::Reason_rtm_state_change) \ declare_constant(Deoptimization::Reason_unstable_if) \ declare_constant(Deoptimization::Reason_unstable_fused_if) \ declare_constant(Deoptimization::Reason_receiver_constraint) \ diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index b440a6cbb5e..6a7e4d1bd20 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -1190,18 +1190,25 @@ void SystemMapDCmd::execute(DCmdSource source, TRAPS) { MemMapPrinter::print_all_mappings(output(), _human_readable.value()); } +static constexpr char default_filename[] = "vm_memory_map_.txt"; + SystemDumpMapDCmd::SystemDumpMapDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _human_readable("-H", "Human readable format", "BOOLEAN", false, "false"), - _filename("-F", "file path (defaults: \"vm_memory_map_.txt\")", "STRING", false) { + _filename("-F", "file path", "STRING", false, default_filename) { _dcmdparser.add_dcmd_option(&_human_readable); _dcmdparser.add_dcmd_option(&_filename); } void SystemDumpMapDCmd::execute(DCmdSource source, TRAPS) { - stringStream default_name; - default_name.print("vm_memory_map_%d.txt", os::current_process_id()); - const char* name = _filename.is_set() ? _filename.value() : default_name.base(); + stringStream defaultname; + const char* name = nullptr; + if (::strcmp(default_filename, _filename.value()) == 0) { + defaultname.print("vm_memory_map_%d.txt", os::current_process_id()); + name = defaultname.base(); + } else { + name = _filename.value(); + } fileStream fs(name); if (fs.is_open()) { if (!MemTracker::enabled()) { diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index c7d5832048c..991ea9fe3c6 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -91,6 +91,13 @@ class ConcurrentHashTable : public CHeapObj { void print_on(outputStream* st) const {}; void print_value_on(outputStream* st) const {}; + + static bool is_dynamic_sized_value_compatible() { + // To support dynamically sized Value types, where part of the payload is + // allocated beyond the end of the object, it must be that the _value + // field ends where the Node object ends. (No end padding). + return offset_of(Node, _value) + sizeof(_value) == sizeof(Node); + } }; // Only constructed with placement new from an array allocated with MEMFLAGS @@ -419,6 +426,7 @@ class ConcurrentHashTable : public CHeapObj { size_t get_size_log2(Thread* thread); static size_t get_node_size() { return sizeof(Node); } + static size_t get_dynamic_node_size(size_t value_size); bool is_max_size_reached() { return _size_limit_reached; } // This means no paused bucket resize operation is going to resume diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 2b30e664109..a83b6dd8a58 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -1055,6 +1055,15 @@ inline size_t ConcurrentHashTable:: return _table->_log2_size; } +template +inline size_t ConcurrentHashTable:: + get_dynamic_node_size(size_t value_size) +{ + assert(Node::is_dynamic_sized_value_compatible(), "VALUE must be compatible"); + assert(value_size >= sizeof(VALUE), "must include the VALUE"); + return sizeof(Node) - sizeof(VALUE) + value_size; +} + template inline bool ConcurrentHashTable:: shrink(Thread* thread, size_t size_limit_log2) diff --git a/src/hotspot/share/utilities/nativeCallStack.cpp b/src/hotspot/share/utilities/nativeCallStack.cpp index 3ddf296506c..873f3856b74 100644 --- a/src/hotspot/share/utilities/nativeCallStack.cpp +++ b/src/hotspot/share/utilities/nativeCallStack.cpp @@ -71,24 +71,18 @@ int NativeCallStack::frames() const { return index; } -void NativeCallStack::print_on(outputStream* out) const { - print_on(out, 0); -} - // Decode and print this call path -void NativeCallStack::print_on(outputStream* out, int indent) const { +void NativeCallStack::print_on(outputStream* out) const { DEBUG_ONLY(assert_not_fake();) address pc; char buf[1024]; int offset; if (is_empty()) { - out->fill_to(indent); out->print("[BOOTSTRAP]"); } else { for (int frame = 0; frame < NMT_TrackingStackDepth; frame ++) { pc = get_frame(frame); if (pc == nullptr) break; - out->fill_to(indent); out->print("[" PTR_FORMAT "]", p2i(pc)); // Print function and library; shorten library name to just its last component // for brevity, and omit it completely for libjvm.so diff --git a/src/hotspot/share/utilities/nativeCallStack.hpp b/src/hotspot/share/utilities/nativeCallStack.hpp index 43e90512b52..6c04169146e 100644 --- a/src/hotspot/share/utilities/nativeCallStack.hpp +++ b/src/hotspot/share/utilities/nativeCallStack.hpp @@ -124,7 +124,6 @@ class NativeCallStack : public StackObj { } void print_on(outputStream* out) const; - void print_on(outputStream* out, int indent) const; }; #define FAKE_CALLSTACK NativeCallStack(NativeCallStack::FakeMarker::its_fake) diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 858f6798e28..5d6731785a3 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -44,18 +44,11 @@ extern "C" void jio_print(const char* s, size_t len); extern "C" int jio_printf(const char *fmt, ...); -outputStream::outputStream() { - _position = 0; - _precount = 0; - _indentation = 0; - _scratch = nullptr; - _scratch_len = 0; -} - outputStream::outputStream(bool has_time_stamps) { _position = 0; _precount = 0; _indentation = 0; + _autoindent = false; _scratch = nullptr; _scratch_len = 0; if (has_time_stamps) _stamp.update(); @@ -159,6 +152,9 @@ void outputStream::do_vsnprintf_and_write_with_scratch_buffer(const char* format } void outputStream::do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) { + if (_autoindent && _position == 0) { + indent(); + } if (_scratch) { do_vsnprintf_and_write_with_scratch_buffer(format, ap, add_cr); } else { @@ -188,6 +184,13 @@ void outputStream::vprint_cr(const char* format, va_list argptr) { do_vsnprintf_and_write(format, argptr, true); } +void outputStream::print_raw(const char* str, size_t len) { + if (_autoindent && _position == 0) { + indent(); + } + write(str, len); +} + void outputStream::fill_to(int col) { int need_fill = col - position(); sp(need_fill); @@ -274,6 +277,12 @@ outputStream& outputStream::indent() { return *this; } +bool outputStream::set_autoindent(bool value) { + const bool old = _autoindent; + _autoindent = value; + return old; +} + void outputStream::print_jlong(jlong value) { print(JLONG_FORMAT, value); } @@ -976,7 +985,7 @@ void ostream_exit() { ClassListWriter::delete_classlist(); // Make sure tty works after VM exit by assigning an always-on functioning fdStream. outputStream* tmp = tty; - tty = DisplayVMOutputToStderr ? fdStream::stdout_stream() : fdStream::stderr_stream(); + tty = DisplayVMOutputToStderr ? fdStream::stderr_stream() : fdStream::stdout_stream(); if (tmp != &tty_preinit_stream && tmp != defaultStream::instance) { delete tmp; } diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp index 98ea9f54a34..bff682a3e5a 100644 --- a/src/hotspot/share/utilities/ostream.hpp +++ b/src/hotspot/share/utilities/ostream.hpp @@ -46,9 +46,10 @@ DEBUG_ONLY(class ResourceMark;) class outputStream : public CHeapObjBase { private: NONCOPYABLE(outputStream); + int _indentation; // current indentation + bool _autoindent; // if true, every line starts with indentation protected: - int _indentation; // current indentation int _position; // visual position on the current line uint64_t _precount; // number of chars output, less than _position TimeStamp _stamp; // for time stamps @@ -90,8 +91,7 @@ class outputStream : public CHeapObjBase { class TestSupport; // Unit test support // creation - outputStream(); - outputStream(bool has_time_stamps); + outputStream(bool has_time_stamps = false); // indentation outputStream& indent(); @@ -104,6 +104,14 @@ class outputStream : public CHeapObjBase { void fill_to(int col); void move_to(int col, int slop = 6, int min_space = 2); + // Automatic indentation: + // If autoindent mode is on, the following APIs will automatically indent + // line starts depending on the current indentation level: + // print(), print_cr(), print_raw(), print_raw_cr() + // Other APIs are unaffected + // Returns old autoindent state. + bool set_autoindent(bool value); + // sizing int position() const { return _position; } julong count() const { return _precount + _position; } @@ -119,10 +127,10 @@ class outputStream : public CHeapObjBase { void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); - void print_raw(const char* str) { write(str, strlen(str)); } - void print_raw(const char* str, size_t len) { write(str, len); } - void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); } - void print_raw_cr(const char* str, size_t len){ write(str, len); cr(); } + void print_raw(const char* str) { print_raw(str, strlen(str)); } + void print_raw(const char* str, size_t len); + void print_raw_cr(const char* str) { print_raw(str); cr(); } + void print_raw_cr(const char* str, size_t len) { print_raw(str, len); cr(); } void print_data(void* data, size_t len, bool with_ascii, bool rel_addr=true); void put(char ch); void sp(int count = 1); @@ -168,17 +176,26 @@ class outputStream : public CHeapObjBase { extern outputStream* tty; // tty output class streamIndentor : public StackObj { - private: - outputStream* _str; - int _amount; - - public: + outputStream* const _str; + const int _amount; + NONCOPYABLE(streamIndentor); +public: streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) { _str->inc(_amount); } ~streamIndentor() { _str->dec(_amount); } }; +class StreamAutoIndentor : public StackObj { + outputStream* const _os; + const bool _old; + NONCOPYABLE(StreamAutoIndentor); + public: + StreamAutoIndentor(outputStream* os) : + _os(os), _old(os->set_autoindent(true)) {} + ~StreamAutoIndentor() { _os->set_autoindent(_old); } +}; + // advisory locking for the shared tty stream: class ttyLocker: StackObj { friend class ttyUnlocker; diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 4573a6dc690..4bc7ccab834 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -70,6 +70,7 @@ import java.util.Set; import java.util.stream.Collectors; +import jdk.internal.constant.ConstantUtils; import jdk.internal.javac.PreviewFeature; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; @@ -4709,7 +4710,7 @@ public Class arrayType() { public Optional describeConstable() { Class c = isArray() ? elementType() : this; return c.isHidden() ? Optional.empty() - : Optional.of(ClassDesc.ofDescriptor(descriptorString())); + : Optional.of(ConstantUtils.classDesc(this)); } /** diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java index c472f5c3fcf..277e1c14480 100644 --- a/src/java.base/share/classes/java/lang/Double.java +++ b/src/java.base/share/classes/java/lang/Double.java @@ -411,41 +411,43 @@ public final class Double extends Number public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324 /** - * The number of bits used to represent a {@code double} value. + * The number of bits used to represent a {@code double} value, + * {@value}. * * @since 1.5 */ public static final int SIZE = 64; /** - * The number of bits in the significand of a {@code double} value. - * This is the parameter N in section {@jls 4.2.3} of - * The Java Language Specification. + * The number of bits in the significand of a {@code double} + * value, {@value}. This is the parameter N in section {@jls + * 4.2.3} of The Java Language Specification. * * @since 19 */ public static final int PRECISION = 53; /** - * Maximum exponent a finite {@code double} variable may have. - * It is equal to the value returned by - * {@code Math.getExponent(Double.MAX_VALUE)}. + * Maximum exponent a finite {@code double} variable may have, + * {@value}. It is equal to the value returned by {@code + * Math.getExponent(Double.MAX_VALUE)}. * * @since 1.6 */ public static final int MAX_EXPONENT = (1 << (SIZE - PRECISION - 1)) - 1; // 1023 /** - * Minimum exponent a normalized {@code double} variable may - * have. It is equal to the value returned by - * {@code Math.getExponent(Double.MIN_NORMAL)}. + * Minimum exponent a normalized {@code double} variable may have, + * {@value}. It is equal to the value returned by {@code + * Math.getExponent(Double.MIN_NORMAL)}. * * @since 1.6 */ public static final int MIN_EXPONENT = 1 - MAX_EXPONENT; // -1022 /** - * The number of bytes used to represent a {@code double} value. + * The number of bytes used to represent a {@code double} value, + * {@value}. * * @since 1.8 */ diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java index fab92d5c4c9..63a4cc0fab2 100644 --- a/src/java.base/share/classes/java/lang/Float.java +++ b/src/java.base/share/classes/java/lang/Float.java @@ -127,15 +127,16 @@ public final class Float extends Number public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f /** - * The number of bits used to represent a {@code float} value. + * The number of bits used to represent a {@code float} value, + * {@value}. * * @since 1.5 */ public static final int SIZE = 32; /** - * The number of bits in the significand of a {@code float} value. - * This is the parameter N in section {@jls 4.2.3} of + * The number of bits in the significand of a {@code float} value, + * {@value}. This is the parameter N in section {@jls 4.2.3} of * The Java Language Specification. * * @since 19 @@ -143,8 +144,8 @@ public final class Float extends Number public static final int PRECISION = 24; /** - * Maximum exponent a finite {@code float} variable may have. It - * is equal to the value returned by {@code + * Maximum exponent a finite {@code float} variable may have, + * {@value}. It is equal to the value returned by {@code * Math.getExponent(Float.MAX_VALUE)}. * * @since 1.6 @@ -152,8 +153,8 @@ public final class Float extends Number public static final int MAX_EXPONENT = (1 << (SIZE - PRECISION - 1)) - 1; // 127 /** - * Minimum exponent a normalized {@code float} variable may have. - * It is equal to the value returned by {@code + * Minimum exponent a normalized {@code float} variable may have, + * {@value}. It is equal to the value returned by {@code * Math.getExponent(Float.MIN_NORMAL)}. * * @since 1.6 @@ -161,7 +162,8 @@ public final class Float extends Number public static final int MIN_EXPONENT = 1 - MAX_EXPONENT; // -126 /** - * The number of bytes used to represent a {@code float} value. + * The number of bytes used to represent a {@code float} value, + * {@value}. * * @since 1.8 */ diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java index eb93a8c6a31..1997ffb487c 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java @@ -45,6 +45,7 @@ import java.lang.classfile.instruction.ExceptionCatch; import java.util.List; import static java.util.Objects.requireNonNull; +import static jdk.internal.constant.ConstantUtils.CD_module_info; import jdk.internal.javac.PreviewFeature; /** @@ -392,7 +393,7 @@ default byte[] buildModule(ModuleAttribute moduleAttribute) { */ default byte[] buildModule(ModuleAttribute moduleAttribute, Consumer handler) { - return build(ClassDesc.of("module-info"), clb -> { + return build(CD_module_info, clb -> { clb.withFlags(AccessFlag.MODULE); clb.with(moduleAttribute); handler.accept(clb); diff --git a/src/java.base/share/classes/java/lang/constant/ClassDesc.java b/src/java.base/share/classes/java/lang/constant/ClassDesc.java index 130a81420b6..370d2eee507 100644 --- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java +++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java @@ -36,7 +36,6 @@ import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS; import static jdk.internal.constant.ConstantUtils.arrayDepth; import static jdk.internal.constant.ConstantUtils.binaryToInternal; -import static jdk.internal.constant.ConstantUtils.dropFirstAndLastChar; import static jdk.internal.constant.ConstantUtils.internalToBinary; import static jdk.internal.constant.ConstantUtils.validateBinaryClassName; import static jdk.internal.constant.ConstantUtils.validateInternalClassName; @@ -165,7 +164,7 @@ static ClassDesc of(String packageName, String className) { static ClassDesc ofDescriptor(String descriptor) { // implicit null-check return (descriptor.length() == 1) - ? Wrapper.forPrimitiveType(descriptor.charAt(0)).classDescriptor() + ? Wrapper.forPrimitiveType(descriptor.charAt(0)).basicClassDescriptor() // will throw IAE on descriptor.length == 0 or if array dimensions too long : ReferenceClassDescImpl.of(descriptor); } @@ -315,7 +314,7 @@ default ClassDesc componentType() { if (isArray()) { String desc = descriptorString(); if (desc.length() == 2) { - return Wrapper.forBasicType(desc.charAt(1)).classDescriptor(); + return Wrapper.forBasicType(desc.charAt(1)).basicClassDescriptor(); } else { return ReferenceClassDescImpl.ofValidated(desc.substring(1)); } diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 6c75c0385fa..1b378512316 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -630,6 +630,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@snippet lang=java : * asSlice(offset, newSize, 1); * } + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @see #asSlice(long, long, long) * @@ -646,6 +649,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * Returns a slice of this memory segment, at the given offset, with the provided * alignment constraint. The returned segment's address is the address of this * segment plus the given offset; its size is specified by the given argument. + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @param offset The new segment base offset (relative to the address of this segment), * specified in bytes @@ -670,6 +676,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@snippet lang=java : * asSlice(offset, layout.byteSize(), layout.byteAlignment()); * } + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @see #asSlice(long, long, long) * @@ -693,6 +702,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@snippet lang=java : * asSlice(offset, byteSize() - offset); * } + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @see #asSlice(long, long) * @@ -706,6 +718,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { /** * Returns a new memory segment that has the same address and scope as this segment, * but with the provided size. + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @param newSize the size of the returned segment * @return a new memory segment that has the same address and scope as @@ -741,6 +756,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * That is, the cleanup action receives a segment that is associated with the global * scope, and is accessible from any thread. The size of the segment accepted by the * cleanup action is {@link #byteSize()}. + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @apiNote The cleanup action (if present) should take care not to leak the received * segment to external clients that might access the segment after its @@ -786,6 +804,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * That is, the cleanup action receives a segment that is associated with the global * scope, and is accessible from any thread. The size of the segment accepted by the * cleanup action is {@code newSize}. + *

+ * The returned memory segment shares a region of backing memory with this segment. + * Hence, no memory will be allocated or freed by this method. * * @apiNote The cleanup action (if present) should take care not to leak the received * segment to external clients that might access the segment after its diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index 5ca45e3fe52..8f0f355a980 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,8 @@ import java.lang.classfile.ClassFile; import java.lang.classfile.CodeBuilder; import java.lang.classfile.TypeKind; + +import jdk.internal.constant.ConstantUtils; import jdk.internal.module.Modules; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -63,6 +65,7 @@ import static java.lang.invoke.MethodType.methodType; import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC; import static java.lang.classfile.ClassFile.*; +import static jdk.internal.constant.ConstantUtils.*; /** * This class consists exclusively of static methods that help adapt @@ -249,14 +252,14 @@ private static Class newProxyClass(Class intfc) { // the field name holding the method handle for this method String fieldName = "m" + count++; - var mt = methodType(m.getReturnType(), JLRA.getExecutableSharedParameterTypes(m), true); + var md = methodTypeDesc(m.getReturnType(), JLRA.getExecutableSharedParameterTypes(m)); var thrown = JLRA.getExecutableSharedExceptionTypes(m); var exceptionTypeDescs = thrown.length == 0 ? DEFAULT_RETHROWS : Stream.concat(DEFAULT_RETHROWS.stream(), - Arrays.stream(thrown).map(MethodHandleProxies::desc)) + Arrays.stream(thrown).map(ConstantUtils::referenceClassDesc)) .distinct().toList(); - methods.add(new MethodInfo(desc(mt), exceptionTypeDescs, fieldName)); + methods.add(new MethodInfo(md, exceptionTypeDescs, fieldName)); // find the types referenced by this method addElementType(referencedTypes, m.getReturnType()); @@ -279,7 +282,8 @@ private static Class newProxyClass(Class intfc) { int i = intfcName.lastIndexOf('.'); // jdk.MHProxy#.Interface String className = packageName + "." + (i > 0 ? intfcName.substring(i + 1) : intfcName); - byte[] template = createTemplate(loader, ClassDesc.of(className), desc(intfc), uniqueName, methods); + byte[] template = createTemplate(loader, binaryNameToDesc(className), + referenceClassDesc(intfc), uniqueName, methods); // define the dynamic module to the class loader of the interface var definer = new Lookup(intfc).makeHiddenClassDefiner(className, template, Set.of(), DUMPER); @@ -335,17 +339,17 @@ private static Class getProxyClass(Class intfc) { } } - private static final List DEFAULT_RETHROWS = List.of(desc(RuntimeException.class), desc(Error.class)); - private static final ClassDesc CD_UndeclaredThrowableException = desc(UndeclaredThrowableException.class); - private static final ClassDesc CD_IllegalAccessException = desc(IllegalAccessException.class); + private static final List DEFAULT_RETHROWS = List.of(referenceClassDesc(RuntimeException.class), referenceClassDesc(Error.class)); + private static final ClassDesc CD_UndeclaredThrowableException = referenceClassDesc(UndeclaredThrowableException.class); + private static final ClassDesc CD_IllegalAccessException = referenceClassDesc(IllegalAccessException.class); private static final MethodTypeDesc MTD_void_Throwable = MethodTypeDesc.of(CD_void, CD_Throwable); private static final MethodType MT_void_Lookup_MethodHandle_MethodHandle = methodType(void.class, Lookup.class, MethodHandle.class, MethodHandle.class); private static final MethodType MT_Object_Lookup_MethodHandle_MethodHandle = MT_void_Lookup_MethodHandle_MethodHandle.changeReturnType(Object.class); private static final MethodType MT_MethodHandle_Object = methodType(MethodHandle.class, Object.class); - private static final MethodTypeDesc MTD_void_Lookup_MethodHandle_MethodHandle = - desc(MT_void_Lookup_MethodHandle_MethodHandle); + private static final MethodTypeDesc MTD_void_Lookup_MethodHandle_MethodHandle + = methodTypeDesc(MT_void_Lookup_MethodHandle_MethodHandle); private static final MethodTypeDesc MTD_void_Lookup = MethodTypeDesc.of(CD_void, CD_MethodHandles_Lookup); private static final MethodTypeDesc MTD_MethodHandle_MethodType = MethodTypeDesc.of(CD_MethodHandle, CD_MethodType); private static final MethodTypeDesc MTD_Class = MethodTypeDesc.of(CD_Class); @@ -531,16 +535,6 @@ public static Class wrapperInstanceType(Object x) { } } - private static ClassDesc desc(Class cl) { - return cl.describeConstable().orElseThrow(() -> newInternalError("Cannot convert class " - + cl.getName() + " to a constant")); - } - - private static MethodTypeDesc desc(MethodType mt) { - return mt.describeConstable().orElseThrow(() -> newInternalError("Cannot convert method type " - + mt + " to a constant")); - } - private static final JavaLangReflectAccess JLRA = SharedSecrets.getJavaLangReflectAccess(); private static final AtomicInteger counter = new AtomicInteger(); diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 3499fd83525..29896fd8f93 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -27,6 +27,7 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.constant.ConstantUtils; import jdk.internal.misc.VM; import jdk.internal.util.ClassFileDumper; import jdk.internal.vm.annotation.Stable; @@ -1090,13 +1091,13 @@ private SimpleStringBuilderStrategy() { private static MethodHandle generate(Lookup lookup, MethodType args, String[] constants) throws Exception { String className = getClassName(lookup.lookupClass()); - byte[] classBytes = ClassFile.of().build(ClassDesc.of(className), + byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(className), new Consumer() { @Override public void accept(ClassBuilder clb) { clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC) .withMethodBody(METHOD_NAME, - MethodTypeDesc.ofDescriptor(args.toMethodDescriptorString()), + ConstantUtils.methodTypeDesc(args), ClassFile.ACC_FINAL | ClassFile.ACC_PRIVATE | ClassFile.ACC_STATIC, generateMethod(constants, args)); }}); diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandles.java b/src/java.base/share/classes/java/lang/invoke/VarHandles.java index bd608619e58..95b5a01550f 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java @@ -25,7 +25,6 @@ package java.lang.invoke; -import jdk.internal.foreign.Utils; import sun.invoke.util.Wrapper; import java.lang.reflect.Constructor; @@ -36,8 +35,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.stream.Stream; import static java.lang.invoke.MethodHandleStatics.UNSAFE; @@ -47,13 +44,6 @@ final class VarHandles { - static ClassValue> ADDRESS_FACTORIES = new ClassValue<>() { - @Override - protected ConcurrentMap computeValue(Class type) { - return new ConcurrentHashMap<>(); - } - }; - static VarHandle makeFieldHandle(MemberName f, Class refc, boolean isWriteAllowedOnFinalFields) { if (!f.isStatic()) { long foffset = MethodHandleNatives.objectFieldOffset(f); diff --git a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index 776f5df4e5a..a484c191206 100644 --- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -49,6 +49,8 @@ import java.lang.classfile.attribute.StackMapTableAttribute; import java.lang.constant.ConstantDescs; import static java.lang.constant.ConstantDescs.*; +import static jdk.internal.constant.ConstantUtils.*; + import java.lang.constant.DirectMethodHandleDesc; import java.lang.constant.DynamicConstantDesc; @@ -134,7 +136,7 @@ final class ProxyGenerator { /** * Name of proxy class */ - private ClassEntry classEntry; + private final ClassEntry classEntry; /** * Proxy interfaces @@ -160,10 +162,10 @@ final class ProxyGenerator { * A ProxyGenerator object contains the state for the ongoing * generation of a particular proxy class. */ - private ProxyGenerator(ClassLoader loader, String className, List> interfaces, + private ProxyGenerator(String className, List> interfaces, int accessFlags) { this.cp = ConstantPoolBuilder.of(); - this.classEntry = cp.classEntry(ReferenceClassDescImpl.ofValidatedBinaryName(className)); + this.classEntry = cp.classEntry(ConstantUtils.binaryNameToDesc(className)); this.interfaces = interfaces; this.accessFlags = accessFlags; this.throwableStack = List.of(StackMapFrameInfo.ObjectVerificationTypeInfo.of(cp.classEntry(CD_Throwable))); @@ -190,7 +192,7 @@ static byte[] generateProxyClass(ClassLoader loader, List> interfaces, int accessFlags) { Objects.requireNonNull(interfaces); - ProxyGenerator gen = new ProxyGenerator(loader, name, interfaces, accessFlags); + ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags); final byte[] classFile = gen.generateClassFile(); if (SAVE_GENERATED_FILES) { @@ -227,18 +229,10 @@ public Void run() { private static List toClassEntries(ConstantPoolBuilder cp, List> types) { var ces = new ArrayList(types.size()); for (var t : types) - ces.add(cp.classEntry(ReferenceClassDescImpl.ofValidatedBinaryName(t.getName()))); + ces.add(cp.classEntry(ConstantUtils.binaryNameToDesc(t.getName()))); return ces; } - /** - * {@return the {@code ClassDesc} of the given type} - * @param type the {@code Class} object - */ - private static ClassDesc toClassDesc(Class type) { - return ClassDesc.ofDescriptor(type.descriptorString()); - } - /** * For a given set of proxy methods with the same signature, check * that their return types are compatible according to the Proxy @@ -325,7 +319,7 @@ private static void checkReturnTypes(List methods) { * not assignable from any of the others. */ if (uncoveredReturnTypes.size() > 1) { - ProxyMethod pm = methods.get(0); + ProxyMethod pm = methods.getFirst(); throw new IllegalArgumentException( "methods with same signature " + pm.shortSignature + @@ -501,7 +495,7 @@ private void addProxyMethod(Method m, Class fromClass) { String sig = m.toShortSignature(); List sigmethods = proxyMethods.computeIfAbsent(sig, - (f) -> new ArrayList<>(3)); + _ -> new ArrayList<>(3)); for (ProxyMethod pm : sigmethods) { if (returnType == pm.returnType) { /* @@ -531,7 +525,7 @@ private void addProxyMethod(Method m, Class fromClass) { private void addProxyMethod(ProxyMethod pm) { String sig = pm.shortSignature; List sigmethods = proxyMethods.computeIfAbsent(sig, - (f) -> new ArrayList<>(3)); + _ -> new ArrayList<>(3)); sigmethods.add(pm); } @@ -637,7 +631,6 @@ private ProxyMethod(Method method, String sig, Class[] parameterTypes, * Create a new specific ProxyMethod with a specific field name * * @param method The method for which to create a proxy - * @param methodFieldName the fieldName to generate */ private ProxyMethod(Method method) { this(method, method.toShortSignature(), @@ -650,11 +643,7 @@ private ProxyMethod(Method method) { */ private void generateMethod(ProxyGenerator pg, ClassBuilder clb) { var cp = pg.cp; - var pTypes = new ClassDesc[parameterTypes.length]; - for (int i = 0; i < pTypes.length; i++) { - pTypes[i] = toClassDesc(parameterTypes[i]); - } - MethodTypeDesc desc = MethodTypeDescImpl.ofTrusted(toClassDesc(returnType), pTypes); + var desc = methodTypeDesc(returnType, parameterTypes); int accessFlags = (method.isVarArgs()) ? ACC_VARARGS | ACC_PUBLIC | ACC_FINAL : ACC_PUBLIC | ACC_FINAL; var catchList = computeUniqueCatchList(exceptionTypes); @@ -665,7 +654,7 @@ private void generateMethod(ProxyGenerator pg, ClassBuilder clb) { .getfield(pg.handlerField) .aload(0) .ldc(DynamicConstantDesc.of(pg.bsm, - toClassDesc(fromClass), + referenceClassDesc(fromClass), method.getName(), desc)); if (parameterTypes.length > 0) { @@ -693,7 +682,7 @@ private void generateMethod(ProxyGenerator pg, ClassBuilder clb) { if (!catchList.isEmpty()) { var c1 = cob.newBoundLabel(); for (var exc : catchList) { - cob.exceptionCatch(cob.startLabel(), c1, c1, toClassDesc(exc)); + cob.exceptionCatch(cob.startLabel(), c1, c1, referenceClassDesc(exc)); } cob.athrow(); // just rethrow the exception var c2 = cob.newBoundLabel(); @@ -739,7 +728,7 @@ private void codeUnwrapReturnValue(CodeBuilder cob, Class type) { .invokevirtual(prim.unwrapMethodRef(cob.constantPool())) .return_(TypeKind.from(type).asLoadable()); } else { - cob.checkcast(toClassDesc(type)) + cob.checkcast(referenceClassDesc(type)) .areturn(); } } diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index c564b7b69f6..3eecd2ab42f 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -26,7 +26,6 @@ package java.lang.runtime; import java.lang.Enum.EnumDesc; -import java.lang.classfile.ClassBuilder; import java.lang.classfile.CodeBuilder; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDesc; @@ -50,6 +49,7 @@ import java.lang.classfile.Label; import java.lang.classfile.instruction.SwitchCase; +import jdk.internal.constant.ConstantUtils; import jdk.internal.constant.ReferenceClassDescImpl; import jdk.internal.misc.PreviewFeatures; import jdk.internal.vm.annotation.Stable; @@ -59,6 +59,9 @@ import java.util.HashMap; import java.util.Map; import static java.util.Objects.requireNonNull; +import static jdk.internal.constant.ConstantUtils.classDesc; +import static jdk.internal.constant.ConstantUtils.referenceClassDesc; + import sun.invoke.util.Wrapper; /** @@ -321,7 +324,7 @@ private static > Object convertEnumConstants(MethodHandles.Loo } return label; } else if (labelClass == String.class) { - return EnumDesc.of(enumClassTemplate.describeConstable().orElseThrow(), (String) label); + return EnumDesc.of(referenceClassDesc(enumClassTemplate), (String) label); } else { throw new IllegalArgumentException("label with illegal type found: " + labelClass + ", expected label of type either String or Class"); @@ -464,10 +467,7 @@ record Element(Label target, Label next, Object caseLabel) { } // Object o = ... // o instanceof Wrapped(float) cb.aload(SELECTOR_OBJ); - cb.instanceOf(Wrapper.forBasicType(classLabel) - .wrapperType() - .describeConstable() - .orElseThrow()); + cb.instanceOf(Wrapper.forBasicType(classLabel).wrapperClassDescriptor()); cb.ifeq(next); } else if (!unconditionalExactnessCheck(Wrapper.asPrimitiveType(selectorType), classLabel)) { // Integer i = ... or int i = ... @@ -515,9 +515,9 @@ record Element(Label target, Label next, Object caseLabel) { } TypePairs typePair = TypePairs.of(Wrapper.asPrimitiveType(selectorType), classLabel); String methodName = TypePairs.typePairToName.get(typePair); - cb.invokestatic(ExactConversionsSupport.class.describeConstable().orElseThrow(), + cb.invokestatic(referenceClassDesc(ExactConversionsSupport.class), methodName, - MethodTypeDesc.of(ConstantDescs.CD_boolean, typePair.from.describeConstable().orElseThrow())); + MethodTypeDesc.of(ConstantDescs.CD_boolean, classDesc(typePair.from))); cb.ifeq(next); } } else { @@ -553,7 +553,7 @@ record Element(Label target, Label next, Object caseLabel) { } MethodTypeDesc.of(ConstantDescs.CD_Integer, ConstantDescs.CD_int)); cb.aload(SELECTOR_OBJ); - cb.invokeinterface(BiPredicate.class.describeConstable().orElseThrow(), + cb.invokeinterface(referenceClassDesc(BiPredicate.class), "test", MethodTypeDesc.of(ConstantDescs.CD_boolean, ConstantDescs.CD_Object, @@ -601,10 +601,11 @@ record Element(Label target, Label next, Object caseLabel) { } } else { cb.loadConstant((ConstantDesc) element.caseLabel()); } - cb.invokestatic(element.caseLabel().getClass().describeConstable().orElseThrow(), + var caseLabelWrapper = Wrapper.forWrapperType(element.caseLabel().getClass()); + cb.invokestatic(caseLabelWrapper.wrapperClassDescriptor(), "valueOf", - MethodTypeDesc.of(element.caseLabel().getClass().describeConstable().orElseThrow(), - Wrapper.asPrimitiveType(element.caseLabel().getClass()).describeConstable().orElseThrow())); + MethodTypeDesc.of(caseLabelWrapper.wrapperClassDescriptor(), + caseLabelWrapper.basicClassDescriptor())); cb.aload(SELECTOR_OBJ); cb.invokevirtual(ConstantDescs.CD_Object, "equals", @@ -631,7 +632,7 @@ private static MethodHandle generateTypeSwitch(MethodHandles.Lookup caller, Clas List> enumDescs = new ArrayList<>(); List> extraClassLabels = new ArrayList<>(); - byte[] classBytes = ClassFile.of().build(ReferenceClassDescImpl.ofValidatedBinaryName(typeSwitchClassName(caller.lookupClass())), + byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())), clb -> { clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC) .withMethodBody("typeSwitch", diff --git a/src/java.base/share/classes/java/util/Spliterators.java b/src/java.base/share/classes/java/util/Spliterators.java index c047d96ab49..6cc9146a3cf 100644 --- a/src/java.base/share/classes/java/util/Spliterators.java +++ b/src/java.base/share/classes/java/util/Spliterators.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,12 +57,9 @@ private Spliterators() {} */ @SuppressWarnings("unchecked") public static Spliterator emptySpliterator() { - return (Spliterator) EMPTY_SPLITERATOR; + return (Spliterator) EmptySpliterator.OfRef.EMPTY_SPLITERATOR; } - private static final Spliterator EMPTY_SPLITERATOR = - new EmptySpliterator.OfRef<>(); - /** * Creates an empty {@code Spliterator.OfInt} * @@ -73,12 +70,9 @@ public static Spliterator emptySpliterator() { * @return An empty spliterator */ public static Spliterator.OfInt emptyIntSpliterator() { - return EMPTY_INT_SPLITERATOR; + return EmptySpliterator.OfInt.EMPTY_INT_SPLITERATOR; } - private static final Spliterator.OfInt EMPTY_INT_SPLITERATOR = - new EmptySpliterator.OfInt(); - /** * Creates an empty {@code Spliterator.OfLong} * @@ -89,12 +83,9 @@ public static Spliterator.OfInt emptyIntSpliterator() { * @return An empty spliterator */ public static Spliterator.OfLong emptyLongSpliterator() { - return EMPTY_LONG_SPLITERATOR; + return EmptySpliterator.OfLong.EMPTY_LONG_SPLITERATOR; } - private static final Spliterator.OfLong EMPTY_LONG_SPLITERATOR = - new EmptySpliterator.OfLong(); - /** * Creates an empty {@code Spliterator.OfDouble} * @@ -105,12 +96,9 @@ public static Spliterator.OfLong emptyLongSpliterator() { * @return An empty spliterator */ public static Spliterator.OfDouble emptyDoubleSpliterator() { - return EMPTY_DOUBLE_SPLITERATOR; + return EmptySpliterator.OfDouble.EMPTY_DOUBLE_SPLITERATOR; } - private static final Spliterator.OfDouble EMPTY_DOUBLE_SPLITERATOR = - new EmptySpliterator.OfDouble(); - // Array-based spliterators /** @@ -905,28 +893,40 @@ public int characteristics() { private static final class OfRef extends EmptySpliterator, Consumer> implements Spliterator { - OfRef() { } + static final Spliterator EMPTY_SPLITERATOR = + new EmptySpliterator.OfRef<>(); + + private OfRef() { } } @SuppressWarnings("overloads") private static final class OfInt extends EmptySpliterator implements Spliterator.OfInt { - OfInt() { } + static final Spliterator.OfInt EMPTY_INT_SPLITERATOR = + new EmptySpliterator.OfInt(); + + private OfInt() { } } @SuppressWarnings("overloads") private static final class OfLong extends EmptySpliterator implements Spliterator.OfLong { - OfLong() { } + static final Spliterator.OfLong EMPTY_LONG_SPLITERATOR = + new EmptySpliterator.OfLong(); + + private OfLong() { } } @SuppressWarnings("overloads") private static final class OfDouble extends EmptySpliterator implements Spliterator.OfDouble { - OfDouble() { } + static final Spliterator.OfDouble EMPTY_DOUBLE_SPLITERATOR = + new EmptySpliterator.OfDouble(); + + private OfDouble() { } } } diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index a82f523a66f..e334f7263e4 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.util.ByteArrayLittleEndian; import jdk.internal.util.HexDigits; /** @@ -467,38 +466,24 @@ public long node() { */ @Override public String toString() { - long lsb = leastSigBits; - long msb = mostSigBits; + int i0 = (int) (mostSigBits >> 32); + int i1 = (int) mostSigBits; + int i2 = (int) (leastSigBits >> 32); + int i3 = (int) leastSigBits; + byte[] buf = new byte[36]; - ByteArrayLittleEndian.setLong( - buf, - 0, - HexDigits.packDigits((int) (msb >> 56), (int) (msb >> 48), (int) (msb >> 40), (int) (msb >> 32))); + HexDigits.put4(buf, 0, i0 >> 16); + HexDigits.put4(buf, 4, i0); buf[8] = '-'; - ByteArrayLittleEndian.setInt( - buf, - 9, - HexDigits.packDigits(((int) msb) >> 24, ((int) msb) >> 16)); + HexDigits.put4(buf, 9, i1 >> 16); buf[13] = '-'; - ByteArrayLittleEndian.setInt( - buf, - 14, - HexDigits.packDigits(((int) msb) >> 8, (int) msb)); + HexDigits.put4(buf, 14, i1); buf[18] = '-'; - ByteArrayLittleEndian.setInt( - buf, - 19, - HexDigits.packDigits((int) (lsb >> 56), (int) (lsb >> 48))); + HexDigits.put4(buf, 19, i2 >> 16); buf[23] = '-'; - ByteArrayLittleEndian.setLong( - buf, - 24, - HexDigits.packDigits((int) (lsb >> 40), (int) (lsb >> 32), ((int) lsb) >> 24, ((int) lsb) >> 16)); - ByteArrayLittleEndian.setInt( - buf, - 32, - HexDigits.packDigits(((int) lsb) >> 8, (int) lsb)); - + HexDigits.put4(buf, 24, i2); + HexDigits.put4(buf, 28, i3 >> 16); + HexDigits.put4(buf, 32, i3); try { return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1); } catch (CharacterCodingException cce) { diff --git a/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java b/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java index 7e4aab20e68..67daf8bb19a 100644 --- a/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java +++ b/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,9 +37,7 @@ * size, and optionally an initialization vector (IV) (only in feedback mode). * *

This class can be used to initialize a {@code Cipher} object that - * implements the RC5 algorithm as supplied by - * RSA Security LLC, - * or any parties authorized by RSA Security. + * implements the RC5 algorithm. * * @author Jan Luehe * diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java index 1154b038dee..6765bdee3bd 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassHierarchyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import static java.lang.constant.ConstantDescs.CD_Object; import static java.lang.classfile.ClassFile.*; import static java.util.Objects.requireNonNull; +import static jdk.internal.constant.ConstantUtils.referenceClassDesc; /** * Class hierarchy resolution framework is answering questions about classes assignability, common classes ancestor and whether the class represents an interface. @@ -245,7 +246,7 @@ public ClassHierarchyInfo getClassInfo(ClassDesc cd) { } return cl.isInterface() ? ClassHierarchyInfo.ofInterface() - : ClassHierarchyInfo.ofClass(cl.getSuperclass().describeConstable().orElseThrow()); + : ClassHierarchyInfo.ofClass(referenceClassDesc(cl.getSuperclass())); } } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java index ba032c7b0c2..ddb14b2d26a 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java @@ -26,14 +26,12 @@ package jdk.internal.classfile.impl; import java.lang.classfile.constantpool.InvokeDynamicEntry; -import java.lang.classfile.constantpool.NameAndTypeEntry; import java.lang.constant.ClassDesc; import static java.lang.constant.ConstantDescs.*; import java.lang.constant.MethodTypeDesc; import java.lang.classfile.ClassFile; import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantDynamicEntry; -import java.lang.classfile.constantpool.DynamicConstantPoolEntry; import java.lang.classfile.constantpool.MemberRefEntry; import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.nio.ByteBuffer; @@ -46,6 +44,8 @@ import java.lang.classfile.Attribute; import static java.lang.classfile.ClassFile.*; +import static jdk.internal.constant.ConstantUtils.binaryNameToDesc; + import java.lang.classfile.BufWriter; import java.lang.classfile.Label; import java.lang.classfile.attribute.StackMapTableAttribute; @@ -1321,8 +1321,8 @@ Type mergeComponentFrom(Type from, ClassHierarchyImpl context) { } } - private static final ClassDesc CD_Cloneable = ClassDesc.of("java.lang.Cloneable"); - private static final ClassDesc CD_Serializable = ClassDesc.of("java.io.Serializable"); + private static final ClassDesc CD_Cloneable = binaryNameToDesc("java.lang.Cloneable"); + private static final ClassDesc CD_Serializable = binaryNameToDesc("java.io.Serializable"); private Type mergeReferenceFrom(Type from, ClassHierarchyImpl context) { if (from == NULL_TYPE) { diff --git a/src/java.base/share/classes/jdk/internal/constant/ConstantUtils.java b/src/java.base/share/classes/jdk/internal/constant/ConstantUtils.java index 7c676a44b99..da90f373eb5 100644 --- a/src/java.base/share/classes/jdk/internal/constant/ConstantUtils.java +++ b/src/java.base/share/classes/jdk/internal/constant/ConstantUtils.java @@ -29,6 +29,8 @@ import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDesc; import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -41,12 +43,85 @@ public final class ConstantUtils { public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0]; public static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0]; public static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255; + public static final ClassDesc CD_module_info = binaryNameToDesc("module-info"); private static final Set pointyNames = Set.of(ConstantDescs.INIT_NAME, ConstantDescs.CLASS_INIT_NAME); /** No instantiation */ private ConstantUtils() {} + // Note: + // Non-JDK users should create their own utilities that wrap + // {@code .describeConstable().orElseThrow()} calls; + // these xxDesc methods has undefined and unsafe exceptional + // behavior, so they are not suitable as public APIs. + + /** + * Creates a {@linkplain ClassDesc} from a pre-validated binary name + * for a class or interface type. Validated version of {@link + * ClassDesc#of(String)}. + * + * @param binaryName a binary name + */ + public static ClassDesc binaryNameToDesc(String binaryName) { + return ReferenceClassDescImpl.ofValidated("L" + binaryToInternal(binaryName) + ";"); + } + + /** + * Creates a ClassDesc from a Class object, requires that this class + * can always be described nominally, i.e. this class is not a + * hidden class or interface or an array with a hidden component + * type. + */ + public static ClassDesc classDesc(Class type) { + if (type.isPrimitive()) { + return Wrapper.forPrimitiveType(type).basicClassDescriptor(); + } + return referenceClassDesc(type); + } + + /** + * Creates a ClassDesc from a Class object representing a non-hidden + * class or interface or an array type with a non-hidden component type. + */ + public static ClassDesc referenceClassDesc(Class type) { + return ReferenceClassDescImpl.ofValidated(type.descriptorString()); + } + + /** + * Creates a MethodTypeDesc from a MethodType object, requires that + * the type can be described nominally, i.e. all of its return + * type and parameter types can be described nominally. + */ + public static MethodTypeDesc methodTypeDesc(MethodType type) { + var returnDesc = classDesc(type.returnType()); + if (type.parameterCount() == 0) { + return MethodTypeDescImpl.ofValidated(returnDesc, EMPTY_CLASSDESC); + } + var paramDescs = new ClassDesc[type.parameterCount()]; + for (int i = 0; i < type.parameterCount(); i++) { + paramDescs[i] = classDesc(type.parameterType(i)); + } + return MethodTypeDescImpl.ofValidated(returnDesc, paramDescs); + } + + /** + * Creates a MethodTypeDesc from return class and parameter + * class objects, requires that all of them can be described nominally. + * This version is mainly useful for working with Method objects. + */ + public static MethodTypeDesc methodTypeDesc(Class returnType, Class[] parameterTypes) { + var returnDesc = classDesc(returnType); + if (parameterTypes.length == 0) { + return MethodTypeDescImpl.ofValidated(returnDesc, EMPTY_CLASSDESC); + } + var paramDescs = new ClassDesc[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + paramDescs[i] = classDesc(parameterTypes[i]); + } + return MethodTypeDescImpl.ofValidated(returnDesc, paramDescs); + } + /** * Validates the correctness of a binary class name. In particular checks for the presence of * invalid characters in the name. @@ -231,7 +306,7 @@ public static List parseMethodDescriptor(String descriptor) { private static ClassDesc resolveClassDesc(String descriptor, int start, int len) { if (len == 1) { - return Wrapper.forPrimitiveType(descriptor.charAt(start)).classDescriptor(); + return Wrapper.forPrimitiveType(descriptor.charAt(start)).basicClassDescriptor(); } // Pre-verified in parseMethodDescriptor; avoid redundant verification return ReferenceClassDescImpl.ofValidated(descriptor.substring(start, start + len)); diff --git a/src/java.base/share/classes/jdk/internal/constant/ReferenceClassDescImpl.java b/src/java.base/share/classes/jdk/internal/constant/ReferenceClassDescImpl.java index b4ec9c13de5..71473b87e18 100644 --- a/src/java.base/share/classes/jdk/internal/constant/ReferenceClassDescImpl.java +++ b/src/java.base/share/classes/jdk/internal/constant/ReferenceClassDescImpl.java @@ -66,20 +66,11 @@ public static ReferenceClassDescImpl of(String descriptor) { * @jvms 4.3.2 Field Descriptors */ public static ReferenceClassDescImpl ofValidated(String descriptor) { + assert ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length(), false) + == descriptor.length() : descriptor; return new ReferenceClassDescImpl(descriptor); } - /** - * Creates a {@linkplain ClassDesc} from a pre-validated descriptor string - * for a class or interface type or an array type. - * - * @param descriptor a field descriptor string for a class or interface type - * @jvms 4.3.2 Field Descriptors - */ - public static ClassDesc ofValidatedBinaryName(String typeSwitchClassName) { - return ofValidated("L" + binaryToInternal(typeSwitchClassName) + ";"); - } - @Override public String descriptorString() { return descriptor; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index 7f5ef54bdca..6109f59f2d8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.lang.classfile.Label; import java.lang.classfile.Opcode; import java.lang.classfile.TypeKind; + import jdk.internal.foreign.AbstractMemorySegmentImpl; import jdk.internal.foreign.MemorySessionImpl; import jdk.internal.foreign.Utils; @@ -50,7 +51,6 @@ import java.io.IOException; import java.lang.constant.ClassDesc; -import java.lang.constant.Constable; import java.lang.constant.ConstantDesc; import java.lang.constant.DynamicConstantDesc; import java.lang.constant.MethodTypeDesc; @@ -70,6 +70,7 @@ import static java.lang.constant.ConstantDescs.*; import static java.lang.classfile.ClassFile.*; import static java.lang.classfile.TypeKind.*; +import static jdk.internal.constant.ConstantUtils.*; public class BindingSpecializer { private static final String DUMP_CLASSES_DIR @@ -80,24 +81,24 @@ public class BindingSpecializer { // Bunch of helper constants private static final int CLASSFILE_VERSION = ClassFileFormatVersion.latest().major(); - private static final ClassDesc CD_Arena = desc(Arena.class); - private static final ClassDesc CD_MemorySegment = desc(MemorySegment.class); - private static final ClassDesc CD_MemorySegment_Scope = desc(MemorySegment.Scope.class); - private static final ClassDesc CD_SharedUtils = desc(SharedUtils.class); - private static final ClassDesc CD_AbstractMemorySegmentImpl = desc(AbstractMemorySegmentImpl.class); - private static final ClassDesc CD_MemorySessionImpl = desc(MemorySessionImpl.class); - private static final ClassDesc CD_Utils = desc(Utils.class); - private static final ClassDesc CD_SegmentAllocator = desc(SegmentAllocator.class); - private static final ClassDesc CD_ValueLayout = desc(ValueLayout.class); - private static final ClassDesc CD_ValueLayout_OfBoolean = desc(ValueLayout.OfBoolean.class); - private static final ClassDesc CD_ValueLayout_OfByte = desc(ValueLayout.OfByte.class); - private static final ClassDesc CD_ValueLayout_OfShort = desc(ValueLayout.OfShort.class); - private static final ClassDesc CD_ValueLayout_OfChar = desc(ValueLayout.OfChar.class); - private static final ClassDesc CD_ValueLayout_OfInt = desc(ValueLayout.OfInt.class); - private static final ClassDesc CD_ValueLayout_OfLong = desc(ValueLayout.OfLong.class); - private static final ClassDesc CD_ValueLayout_OfFloat = desc(ValueLayout.OfFloat.class); - private static final ClassDesc CD_ValueLayout_OfDouble = desc(ValueLayout.OfDouble.class); - private static final ClassDesc CD_AddressLayout = desc(AddressLayout.class); + private static final ClassDesc CD_Arena = referenceClassDesc(Arena.class); + private static final ClassDesc CD_MemorySegment = referenceClassDesc(MemorySegment.class); + private static final ClassDesc CD_MemorySegment_Scope = referenceClassDesc(MemorySegment.Scope.class); + private static final ClassDesc CD_SharedUtils = referenceClassDesc(SharedUtils.class); + private static final ClassDesc CD_AbstractMemorySegmentImpl = referenceClassDesc(AbstractMemorySegmentImpl.class); + private static final ClassDesc CD_MemorySessionImpl = referenceClassDesc(MemorySessionImpl.class); + private static final ClassDesc CD_Utils = referenceClassDesc(Utils.class); + private static final ClassDesc CD_SegmentAllocator = referenceClassDesc(SegmentAllocator.class); + private static final ClassDesc CD_ValueLayout = referenceClassDesc(ValueLayout.class); + private static final ClassDesc CD_ValueLayout_OfBoolean = referenceClassDesc(ValueLayout.OfBoolean.class); + private static final ClassDesc CD_ValueLayout_OfByte = referenceClassDesc(ValueLayout.OfByte.class); + private static final ClassDesc CD_ValueLayout_OfShort = referenceClassDesc(ValueLayout.OfShort.class); + private static final ClassDesc CD_ValueLayout_OfChar = referenceClassDesc(ValueLayout.OfChar.class); + private static final ClassDesc CD_ValueLayout_OfInt = referenceClassDesc(ValueLayout.OfInt.class); + private static final ClassDesc CD_ValueLayout_OfLong = referenceClassDesc(ValueLayout.OfLong.class); + private static final ClassDesc CD_ValueLayout_OfFloat = referenceClassDesc(ValueLayout.OfFloat.class); + private static final ClassDesc CD_ValueLayout_OfDouble = referenceClassDesc(ValueLayout.OfDouble.class); + private static final ClassDesc CD_AddressLayout = referenceClassDesc(AddressLayout.class); private static final MethodTypeDesc MTD_NEW_BOUNDED_ARENA = MethodTypeDesc.of(CD_Arena, CD_long); private static final MethodTypeDesc MTD_NEW_EMPTY_ARENA = MethodTypeDesc.of(CD_Arena); @@ -196,7 +197,7 @@ private static byte[] specializeHelper(MethodType leafType, MethodType callerMet clb.withSuperclass(CD_Object); clb.withVersion(CLASSFILE_VERSION, 0); - clb.withMethodBody(METHOD_NAME, desc(callerMethodType), ACC_PUBLIC | ACC_STATIC, + clb.withMethodBody(METHOD_NAME, methodTypeDesc(callerMethodType), ACC_PUBLIC | ACC_STATIC, cb -> new BindingSpecializer(cb, callerMethodType, callingSequence, abi, leafType).specialize()); }); @@ -362,7 +363,7 @@ private void specialize() { cb.loadLocal(TypeKind.from(leafArgTypes.get(i)), leafArgSlots[i]); } // call leaf MH - cb.invokevirtual(CD_MethodHandle, "invokeExact", desc(leafType)); + cb.invokevirtual(CD_MethodHandle, "invokeExact", methodTypeDesc(leafType)); // for downcalls, store the result of the leaf handle call away, until // it is requested by a VM_LOAD in the return recipe. @@ -466,9 +467,9 @@ private void doBindings(List bindings) { case Copy copy -> emitCopyBuffer(copy); case Allocate allocate -> emitAllocBuffer(allocate); case BoxAddress boxAddress -> emitBoxAddress(boxAddress); - case SegmentBase unused -> emitSegmentBase(); + case SegmentBase _ -> emitSegmentBase(); case SegmentOffset segmentOffset -> emitSegmentOffset(segmentOffset); - case Dup unused -> emitDupBinding(); + case Dup _ -> emitDupBinding(); case ShiftLeft shiftLeft -> emitShiftLeft(shiftLeft); case ShiftRight shiftRight -> emitShiftRight(shiftRight); case Cast cast -> emitCast(cast); @@ -608,7 +609,7 @@ private void emitBufferStore(BufferStore bufferStore) { ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType); cb.loadConstant(offset); cb.loadLocal(storeTypeKind, valueIdx); - MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType)); + MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType)); cb.invokeinterface(CD_MemorySegment, "set", descriptor); } else { // long longValue = ((Number) value).longValue(); @@ -666,7 +667,7 @@ private void emitBufferStore(BufferStore bufferStore) { long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize); cb.loadConstant(writeOffset); cb.loadLocal(chunkStoreTypeKind, chunkIdx); - MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(chunkStoreType)); + MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(chunkStoreType)); cb.invokeinterface(CD_MemorySegment, "set", descriptor); remaining -= chunkSize; @@ -697,7 +698,7 @@ private void emitVMStore(VMStore vmStore) { ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType); cb.loadConstant(retBufOffset); cb.loadLocal(storeTypeKind, valueIdx); - MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType)); + MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType)); cb.invokeinterface(CD_MemorySegment, "set", descriptor); retBufOffset += abi.arch.typeSize(vmStore.storage().type()); } @@ -716,7 +717,7 @@ private void emitVMLoad(VMLoad vmLoad) { cb.loadLocal(ReferenceType, returnBufferIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType); cb.loadConstant(retBufOffset); - MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long); + MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long); cb.invokeinterface(CD_MemorySegment, "get", descriptor); retBufOffset += abi.arch.typeSize(vmLoad.storage().type()); pushType(loadType); @@ -809,7 +810,7 @@ private void emitBufferLoad(BufferLoad bufferLoad) { if (SharedUtils.isPowerOfTwo(byteWidth)) { ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType); cb.loadConstant(offset); - MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long); + MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long); cb.invokeinterface(CD_MemorySegment, "get", descriptor); } else { // chunked @@ -849,7 +850,7 @@ private void emitBufferLoad(BufferLoad bufferLoad) { // read from segment cb.loadLocal(ReferenceType, readAddrIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType); - MethodTypeDesc descriptor = MethodTypeDesc.of(desc(chunkType), valueLayoutType, CD_long); + MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(chunkType), valueLayoutType, CD_long); long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize); cb.loadConstant(readOffset); cb.invokeinterface(CD_MemorySegment, "get", descriptor); @@ -988,9 +989,4 @@ private void emitConstZero(TypeKind kind) { case ReferenceType -> cb.aconst_null(); } } - - @SuppressWarnings("unchecked") - private static T desc(Constable c) { - return (T) c.describeConstable().orElseThrow(); - } } diff --git a/src/java.base/share/classes/jdk/internal/util/HexDigits.java b/src/java.base/share/classes/jdk/internal/util/HexDigits.java index 075443571e1..c08db4f5b48 100644 --- a/src/java.base/share/classes/jdk/internal/util/HexDigits.java +++ b/src/java.base/share/classes/jdk/internal/util/HexDigits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,24 +114,19 @@ public static short digitPair(int i, boolean ucase) { } /** - * Return a little-endian packed integer for the 4 ASCII bytes for an input unsigned 2-byte integer. - * {@code b0} is the most significant byte and {@code b1} is the least significant byte. - * The integer is passed byte-wise to allow reordering of execution. + * Insert the unsigned 2-byte integer into the buffer as 4 hexadecimal digit ASCII bytes, + * only least significant 16 bits of {@code value} are used. + * @param buffer byte buffer to copy into + * @param index insert point + * @param value to convert */ - public static int packDigits(int b0, int b1) { - return DIGITS[b0 & 0xff] | (DIGITS[b1 & 0xff] << 16); - } - - /** - * Return a little-endian packed long for the 8 ASCII bytes for an input unsigned 4-byte integer. - * {@code b0} is the most significant byte and {@code b3} is the least significant byte. - * The integer is passed byte-wise to allow reordering of execution. - */ - public static long packDigits(int b0, int b1, int b2, int b3) { - return DIGITS[b0 & 0xff] - | (DIGITS[b1 & 0xff] << 16) - | (((long) DIGITS[b2 & 0xff]) << 32) - | (((long) DIGITS[b3 & 0xff]) << 48); + public static void put4(byte[] buffer, int index, int value) { + // Prepare an int value so C2 generates a 4-byte write instead of two 2-byte writes + int v = (DIGITS[value & 0xff] << 16) | DIGITS[(value >> 8) & 0xff]; + buffer[index] = (byte) v; + buffer[index + 1] = (byte) (v >> 8); + buffer[index + 2] = (byte) (v >> 16); + buffer[index + 3] = (byte) (v >> 24); } /** diff --git a/src/java.base/share/classes/sun/invoke/util/Wrapper.java b/src/java.base/share/classes/sun/invoke/util/Wrapper.java index 5f2e9ba2841..5d0849cd93d 100644 --- a/src/java.base/share/classes/sun/invoke/util/Wrapper.java +++ b/src/java.base/share/classes/sun/invoke/util/Wrapper.java @@ -32,20 +32,31 @@ import java.lang.constant.ConstantDescs; public enum Wrapper { - // wrapperType simple primitiveType simple char emptyArray format numericClass superClass classDescriptor - BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0], Format.unsigned( 1), 0, 0, ConstantDescs.CD_boolean), + // wrapperType simple primitiveType simple char emptyArray format numericClass superClass + // basicClassDescriptor wrapperClassDescriptor + BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0], Format.unsigned( 1), 0, 0, + ConstantDescs.CD_boolean, ConstantDescs.CD_Boolean), // These must be in the order defined for widening primitive conversions in JLS 5.1.2 // Avoid boxing integral types here to defer initialization of internal caches - BYTE ( Byte.class, "Byte", byte.class, "byte", 'B', new byte[0], Format.signed( 8), BYTE_CLASS, BYTE_SUPERCLASSES, ConstantDescs.CD_byte), - SHORT ( Short.class, "Short", short.class, "short", 'S', new short[0], Format.signed( 16), SHORT_CLASS, SHORT_SUPERCLASSES, ConstantDescs.CD_short), - CHAR (Character.class, "Character", char.class, "char", 'C', new char[0], Format.unsigned(16), CHAR_CLASS, CHAR_SUPERCLASSES, ConstantDescs.CD_char), - INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0], Format.signed( 32), INT_CLASS, INT_SUPERCLASSES, ConstantDescs.CD_int), - LONG ( Long.class, "Long", long.class, "long", 'J', new long[0], Format.signed( 64), LONG_CLASS, LONG_SUPERCLASSES, ConstantDescs.CD_long), - FLOAT ( Float.class, "Float", float.class, "float", 'F', new float[0], Format.floating(32), FLOAT_CLASS, FLOAT_SUPERCLASSES, ConstantDescs.CD_float), - DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0], Format.floating(64), DOUBLE_CLASS, DOUBLE_CLASS, ConstantDescs.CD_double), - OBJECT ( Object.class, "Object", Object.class, "Object", 'L', new Object[0], Format.other( 1), 0, 0, ConstantDescs.CD_Object), + BYTE ( Byte.class, "Byte", byte.class, "byte", 'B', new byte[0], Format.signed( 8), BYTE_CLASS, BYTE_SUPERCLASSES, + ConstantDescs.CD_byte, ConstantDescs.CD_Byte), + SHORT ( Short.class, "Short", short.class, "short", 'S', new short[0], Format.signed( 16), SHORT_CLASS, SHORT_SUPERCLASSES, + ConstantDescs.CD_short, ConstantDescs.CD_Short), + CHAR (Character.class, "Character", char.class, "char", 'C', new char[0], Format.unsigned(16), CHAR_CLASS, CHAR_SUPERCLASSES, + ConstantDescs.CD_char, ConstantDescs.CD_Character), + INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0], Format.signed( 32), INT_CLASS, INT_SUPERCLASSES, + ConstantDescs.CD_int, ConstantDescs.CD_Integer), + LONG ( Long.class, "Long", long.class, "long", 'J', new long[0], Format.signed( 64), LONG_CLASS, LONG_SUPERCLASSES, + ConstantDescs.CD_long, ConstantDescs.CD_Long), + FLOAT ( Float.class, "Float", float.class, "float", 'F', new float[0], Format.floating(32), FLOAT_CLASS, FLOAT_SUPERCLASSES, + ConstantDescs.CD_float, ConstantDescs.CD_Float), + DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0], Format.floating(64), DOUBLE_CLASS, DOUBLE_CLASS, + ConstantDescs.CD_double, ConstantDescs.CD_Double), + OBJECT ( Object.class, "Object", Object.class, "Object", 'L', new Object[0], Format.other( 1), 0, 0, + ConstantDescs.CD_Object, ConstantDescs.CD_Object), // VOID must be the last type, since it is "assignable" from any other type: - VOID ( Void.class, "Void", void.class, "void", 'V', null, Format.other( 0), 0, 0, ConstantDescs.CD_void), + VOID ( Void.class, "Void", void.class, "void", 'V', null, Format.other( 0), 0, 0, + ConstantDescs.CD_void, ConstantDescs.CD_Void), ; public static final int COUNT = 10; @@ -60,18 +71,20 @@ public enum Wrapper { private final int superClasses; private final String wrapperSimpleName; private final String primitiveSimpleName; - private final ClassDesc classDesc; - - private Wrapper(Class wtype, - String wtypeName, - Class ptype, - String ptypeName, - char tchar, - Object emptyArray, - int format, - int numericClass, - int superClasses, - ClassDesc classDesc) { + private final ClassDesc basicClassDesc; + private final ClassDesc wrapperClassDesc; + + Wrapper(Class wtype, + String wtypeName, + Class ptype, + String ptypeName, + char tchar, + Object emptyArray, + int format, + int numericClass, + int superClasses, + ClassDesc basicClassDesc, + ClassDesc wrapperClassDesc) { this.wrapperType = wtype; this.primitiveType = ptype; this.basicTypeChar = tchar; @@ -82,7 +95,8 @@ private Wrapper(Class wtype, this.superClasses = superClasses; this.wrapperSimpleName = wtypeName; this.primitiveSimpleName = ptypeName; - this.classDesc = classDesc; + this.basicClassDesc = basicClassDesc; + this.wrapperClassDesc = wrapperClassDesc; } /** For debugging, give the details of this wrapper. */ @@ -390,7 +404,10 @@ public static Wrapper forBasicType(Class type) { } /** A nominal descriptor of the wrapped type */ - public ClassDesc classDescriptor() { return classDesc; } + public ClassDesc basicClassDescriptor() { return basicClassDesc; } + + /** A nominal descriptor of the wrapper type */ + public ClassDesc wrapperClassDescriptor() { return wrapperClassDesc; } /** What is the primitive type wrapped by this wrapper? */ public Class primitiveType() { return primitiveType; } diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 4790ee75dd9..31823cfbb87 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -806,14 +806,19 @@ private int receive(ByteBuffer dst, boolean connected) throws IOException { } } + /** + * Receives a datagram into a direct buffer. + */ private int receiveIntoNativeBuffer(ByteBuffer bb, int rem, int pos, boolean connected) throws IOException { NIO_ACCESS.acquireSession(bb); try { + long bufAddress = NIO_ACCESS.getBufferAddress(bb); int n = receive0(fd, - ((DirectBuffer)bb).address() + pos, rem, + bufAddress + pos, + rem, sourceSockAddr.address(), connected); if (n > 0) @@ -991,6 +996,9 @@ private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) } } + /** + * Send a datagram contained in a direct buffer. + */ private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, InetSocketAddress target) throws IOException @@ -1003,9 +1011,13 @@ private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, int written; NIO_ACCESS.acquireSession(bb); try { + long bufAddress = NIO_ACCESS.getBufferAddress(bb); int addressLen = targetSocketAddress(target); - written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, - targetSockAddr.address(), addressLen); + written = send0(fd, + bufAddress + pos, + rem, + targetSockAddr.address(), + addressLen); } catch (PortUnreachableException pue) { if (isConnected()) throw pue; diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 6cef707d19a..839d46e1228 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -36,7 +36,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JAVA" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JAVA" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP @@ -186,7 +186,7 @@ with new values added and old values removed. You\[aq]ll get an error message if you use a value of \f[I]N\f[R] that is no longer supported. The supported values of \f[I]N\f[R] are the current Java SE release -(\f[V]23\f[R]) and a limited number of previous releases, detailed in +(\f[V]24\f[R]) and a limited number of previous releases, detailed in the command-line help for \f[V]javac\f[R], under the \f[V]--source\f[R] and \f[V]--release\f[R] options. .RE @@ -1195,7 +1195,7 @@ or directories. \f[V]--source\f[R] \f[I]version\f[R] Sets the version of the source in source-file mode. .TP -\f[V]--sun-misc-unsafe-memory-acces=\f[R] \f[I]value\f[R] +\f[V]--sun-misc-unsafe-memory-access=\f[R] \f[I]value\f[R] Allow or deny usage of unsupported API \f[V]sun.misc.Unsafe\f[R]. \f[I]value\f[R] is one of: .RS @@ -3484,16 +3484,6 @@ By default, this option is disabled. Enables printing of information about adaptive-generation sizing. By default, this option is disabled. .TP -\f[V]-XX:+ScavengeBeforeFullGC\f[R] -Enables GC of the young generation before each full GC. -This option is enabled by default. -It is recommended that you \f[I]don\[aq]t\f[R] disable it, because -scavenging the young generation before a full GC can reduce the number -of objects reachable from the old generation space into the young -generation space. -To disable GC of the young generation before each full GC, specify the -option \f[V]-XX:-ScavengeBeforeFullGC\f[R]. -.TP \f[V]-XX:SoftRefLRUPolicyMSPerMB=\f[R]\f[I]time\f[R] Sets the amount of time (in milliseconds) a softly reachable object is kept active on the heap after the last time it was referenced. @@ -3747,45 +3737,18 @@ Example: Enables the use of Java Flight Recorder (JFR) during the runtime of the application. Since JDK 8u40 this option has not been required to use JFR. -.TP -\f[V]-XX:InitialRAMFraction=\f[R]\f[I]ratio\f[R] -Sets the initial amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a ratio of the maximum amount -determined as described in the \f[V]-XX:MaxRAM\f[R] option. -The default value is 64. -.RS -.PP -Use the option \f[V]-XX:InitialRAMPercentage\f[R] instead. -.RE -.TP -\f[V]-XX:MaxRAMFraction=\f[R]\f[I]ratio\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a fraction of the maximum -amount determined as described in the \f[V]-XX:MaxRAM\f[R] option. -The default value is 4. -.RS -.PP -Specifying this option disables automatic use of compressed oops if the -combined result of this and other options influencing the maximum amount -of memory is larger than the range of memory addressable by compressed -oops. -See \f[V]-XX:UseCompressedOops\f[R] for further information about -compressed oops. +.SH OBSOLETE JAVA OPTIONS .PP -Use the option \f[V]-XX:MaxRAMPercentage\f[R] instead. -.RE +These \f[V]java\f[R] options are still accepted but ignored, and a +warning is issued when they\[aq]re used. .TP -\f[V]-XX:MinRAMFraction=\f[R]\f[I]ratio\f[R] -Sets the maximum amount of memory that the JVM may use for the Java heap -before applying ergonomics heuristics as a fraction of the maximum -amount determined as described in the \f[V]-XX:MaxRAM\f[R] option for -small heaps. -A small heap is a heap of approximately 125 MB. -The default value is 2. -.RS -.PP -Use the option \f[V]-XX:MinRAMPercentage\f[R] instead. -.RE +\f[V]--illegal-access=\f[R]\f[I]parameter\f[R] +Controlled \f[I]relaxed strong encapsulation\f[R], as defined in +\f[B]JEP 261\f[R] +[https://openjdk.org/jeps/261#Relaxed-strong-encapsulation]. +This option was deprecated in JDK 16 by \f[B]JEP 396\f[R] +[https://openjdk.org/jeps/396] and made obsolete in JDK 17 by \f[B]JEP +403\f[R] [https://openjdk.org/jeps/403]. .TP \f[V]-XX:RTMAbortRatio=\f[R]\f[I]abort_ratio\f[R] Specifies the RTM abort ratio is specified as a percentage (%) of all @@ -3863,43 +3826,70 @@ As a result, the processors repeatedly invalidate the cache lines of other processors, which forces them to read from main memory instead of their cache. .RE -.SH OBSOLETE JAVA OPTIONS -.PP -These \f[V]java\f[R] options are still accepted but ignored, and a -warning is issued when they\[aq]re used. -.TP -\f[V]--illegal-access=\f[R]\f[I]parameter\f[R] -Controlled \f[I]relaxed strong encapsulation\f[R], as defined in -\f[B]JEP 261\f[R] -[https://openjdk.org/jeps/261#Relaxed-strong-encapsulation]. -This option was deprecated in JDK 16 by \f[B]JEP 396\f[R] -[https://openjdk.org/jeps/396] and made obsolete in JDK 17 by \f[B]JEP -403\f[R] [https://openjdk.org/jeps/403]. .SH REMOVED JAVA OPTIONS .PP -These \f[V]java\f[R] options have been removed in JDK 23 and using them +These \f[V]java\f[R] options have been removed in JDK 24 and using them results in an error of: .RS .PP \f[V]Unrecognized VM option\f[R] \f[I]option-name\f[R] .RE .TP -\f[V]-XX:+UseHugeTLBFS\f[R] -\f[B]Linux only:\f[R] This option is the equivalent of specifying -\f[V]-XX:+UseLargePages\f[R]. -This option is disabled by default. -This option pre-allocates all large pages up-front, when memory is -reserved; consequently the JVM can\[aq]t dynamically grow or shrink -large pages memory areas; see \f[V]-XX:UseTransparentHugePages\f[R] if -you want this behavior. +\f[V]-XX:InitialRAMFraction=\f[R]\f[I]ratio\f[R] +Sets the initial amount of memory that the JVM may use for the Java heap +before applying ergonomics heuristics as a ratio of the maximum amount +determined as described in the \f[V]-XX:MaxRAM\f[R] option. +The default value is 64. +.RS +.PP +Use the option \f[V]-XX:InitialRAMPercentage\f[R] instead. +.RE .TP -\f[V]-XX:+UseSHM\f[R] -\f[B]Linux only:\f[R] Enables the JVM to use shared memory to set up -large pages. +\f[V]-XX:MaxRAMFraction=\f[R]\f[I]ratio\f[R] +Sets the maximum amount of memory that the JVM may use for the Java heap +before applying ergonomics heuristics as a fraction of the maximum +amount determined as described in the \f[V]-XX:MaxRAM\f[R] option. +The default value is 4. +.RS +.PP +Specifying this option disables automatic use of compressed oops if the +combined result of this and other options influencing the maximum amount +of memory is larger than the range of memory addressable by compressed +oops. +See \f[V]-XX:UseCompressedOops\f[R] for further information about +compressed oops. +.PP +Use the option \f[V]-XX:MaxRAMPercentage\f[R] instead. +.RE +.TP +\f[V]-XX:MinRAMFraction=\f[R]\f[I]ratio\f[R] +Sets the maximum amount of memory that the JVM may use for the Java heap +before applying ergonomics heuristics as a fraction of the maximum +amount determined as described in the \f[V]-XX:MaxRAM\f[R] option for +small heaps. +A small heap is a heap of approximately 125 MB. +The default value is 2. +.RS +.PP +Use the option \f[V]-XX:MinRAMPercentage\f[R] instead. +.RE +.TP +\f[V]-XX:+ScavengeBeforeFullGC\f[R] +Enables GC of the young generation before each full GC. +This option is enabled by default. +It is recommended that you \f[I]don\[aq]t\f[R] disable it, because +scavenging the young generation before a full GC can reduce the number +of objects reachable from the old generation space into the young +generation space. +To disable GC of the young generation before each full GC, specify the +option \f[V]-XX:-ScavengeBeforeFullGC\f[R]. .PP For the lists and descriptions of options removed in previous releases see the \f[I]Removed Java Options\f[R] section in: .IP \[bu] 2 +\f[B]The \f[VB]java\f[B] Command, Release 23\f[R] +[https://docs.oracle.com/en/java/javase/23/docs/specs/man/java.html] +.IP \[bu] 2 \f[B]The \f[VB]java\f[B] Command, Release 22\f[R] [https://docs.oracle.com/en/java/javase/22/docs/specs/man/java.html] .IP \[bu] 2 diff --git a/src/java.base/share/man/keytool.1 b/src/java.base/share/man/keytool.1 index a61095d4504..63a134eb932 100644 --- a/src/java.base/share/man/keytool.1 +++ b/src/java.base/share/man/keytool.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. .\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. .\" .\" This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "KEYTOOL" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "KEYTOOL" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP @@ -1747,7 +1747,7 @@ risk. The \f[V]keytool\f[R] command supports these named extensions. The names aren\[aq]t case-sensitive. .TP -\f[V]BC\f[R] or \f[V]BasicContraints\f[R] +\f[V]BC\f[R] or \f[V]BasicConstraints\f[R] Values: .RS .PP diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java index d6fb51c4494..fd0d5b03b0c 100644 --- a/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -557,8 +557,14 @@ public InputStream getErrorStream() { public int exitValue() { int exitCode = getExitCodeProcess(handle); - if (exitCode == STILL_ACTIVE) - throw new IllegalThreadStateException("process has not exited"); + if (exitCode == STILL_ACTIVE) { + // STILL_ACTIVE (259) might be the real exit code + if (isProcessAlive(handle)) { + throw new IllegalThreadStateException("process has not exited"); + } + // call again, in case the process just exited + return getExitCodeProcess(handle); + } return exitCode; } private static native int getExitCodeProcess(long handle); @@ -582,7 +588,7 @@ public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions - if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; + if (!isProcessAlive(handle)) return true; if (timeout <= 0) return false; long deadline = System.nanoTime() + remainingNanos; @@ -601,13 +607,13 @@ public boolean waitFor(long timeout, TimeUnit unit) } if (Thread.interrupted()) throw new InterruptedException(); - if (getExitCodeProcess(handle) != STILL_ACTIVE) { + if (!isProcessAlive(handle)) { return true; } remainingNanos = deadline - System.nanoTime(); } while (remainingNanos > 0); - return (getExitCodeProcess(handle) != STILL_ACTIVE); + return !isProcessAlive(handle); } private static native void waitForTimeoutInterruptibly( diff --git a/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c b/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c index 0bc036b7236..0064113729a 100644 --- a/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c +++ b/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,27 +109,19 @@ Java_java_lang_ProcessHandleImpl_waitForProcessExit0(JNIEnv* env, if (handle == NULL) { return exitValue; // No process with that pid is alive } - do { - if (!GetExitCodeProcess(handle, &exitValue)) { + if (!GetExitCodeProcess(handle, &exitValue)) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "GetExitCodeProcess"); + } else if (exitValue == STILL_ACTIVE) { + if (WaitForSingleObject(handle, INFINITE) /* Wait forever */ + == WAIT_FAILED) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "WaitForSingleObjects"); + } else if (!GetExitCodeProcess(handle, &exitValue)) { JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException", "GetExitCodeProcess"); - break; - } - if (exitValue == STILL_ACTIVE) { - HANDLE events[2]; - events[0] = handle; - events[1] = JVM_GetThreadInterruptEvent(); - - if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, - FALSE, /* Wait for ANY event */ - INFINITE) /* Wait forever */ - == WAIT_FAILED) { - JNU_ThrowByNameWithLastError(env, - "java/lang/RuntimeException", "WaitForMultipleObjects"); - break; - } } - } while (exitValue == STILL_ACTIVE); + } CloseHandle(handle); // Ignore return code return exitValue; } diff --git a/src/java.base/windows/native/libjava/ProcessImpl_md.c b/src/java.base/windows/native/libjava/ProcessImpl_md.c index a1890578888..127c27981ba 100644 --- a/src/java.base/windows/native/libjava/ProcessImpl_md.c +++ b/src/java.base/windows/native/libjava/ProcessImpl_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -467,9 +467,8 @@ Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong h JNIEXPORT jboolean JNICALL Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle) { - DWORD dwExitStatus; - GetExitCodeProcess((HANDLE) handle, &dwExitStatus); - return dwExitStatus == STILL_ACTIVE; + return WaitForSingleObject((HANDLE) handle, 0) /* don't wait */ + == WAIT_TIMEOUT; } JNIEXPORT jboolean JNICALL diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java index f14c7b40cba..0501bbfab03 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ void handleMouseEvent(int eventType, int modifierFlags, int buttonNumber, jmodifiers |= MouseEvent.getMaskForButton(jbuttonNumber); } - boolean jpopupTrigger = NSEvent.isPopupTrigger(jmodifiers); + boolean jpopupTrigger = NSEvent.isPopupTrigger(jmodifiers, jeventType); eventNotifier.notifyMouseEvent(jeventType, System.currentTimeMillis(), jbuttonNumber, x, y, absX, absY, jmodifiers, jclickCount, diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java index d0b9288aeae..7d35f859a7a 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java @@ -253,7 +253,7 @@ private void handleMouseEvent(NSEvent nsEvent) { int jmodifiers = NSEvent.nsToJavaModifiers( nsEvent.getModifierFlags()); - boolean isPopupTrigger = NSEvent.isPopupTrigger(jmodifiers); + boolean isPopupTrigger = NSEvent.isPopupTrigger(jmodifiers, jeventType); int eventButtonMask = (jbuttonNumber > 0)? MouseEvent.getMaskForButton(jbuttonNumber) : 0; diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java index ca3d9ad5da7..f3fcfdfb43c 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,7 +269,12 @@ static int nsToJavaEventType(int nsEventType) { */ static native char nsToJavaChar(char nsChar, int modifierFlags, boolean spaceKeyTyped); - static boolean isPopupTrigger(int jmodifiers) { + static boolean isPopupTrigger(int jmodifiers, int jeventType) { + if (jeventType != MouseEvent.MOUSE_PRESSED + && jeventType != MouseEvent.MOUSE_RELEASED) { + return false; + } + final boolean isRightButtonDown = ((jmodifiers & InputEvent.BUTTON3_DOWN_MASK) != 0); final boolean isLeftButtonDown = ((jmodifiers & InputEvent.BUTTON1_DOWN_MASK) != 0); final boolean isControlDown = ((jmodifiers & InputEvent.CTRL_DOWN_MASK) != 0); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java index ed95f815913..09ad87f9205 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -356,6 +356,7 @@ public void onNext(List items) { // incoming buffers are allocated by http client internally, // and won't be used anywhere except this place. // So it's free simply to store them for further processing. + Objects.requireNonNull(items); // ensure NPE is thrown before assert assert Utils.hasRemaining(items); received.addAll(items); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index 9bd7f350286..b2eb570db0c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -746,6 +746,7 @@ public static String stringOf(Collection source) { } public static long remaining(ByteBuffer[] bufs) { + if (bufs == null) return 0; long remain = 0; for (ByteBuffer buf : bufs) { remain += buf.remaining(); @@ -754,6 +755,7 @@ public static long remaining(ByteBuffer[] bufs) { } public static boolean hasRemaining(List bufs) { + if (bufs == null) return false; for (ByteBuffer buf : bufs) { if (buf.hasRemaining()) return true; @@ -762,6 +764,7 @@ public static boolean hasRemaining(List bufs) { } public static boolean hasRemaining(ByteBuffer[] bufs) { + if (bufs == null) return false; for (ByteBuffer buf : bufs) { if (buf.hasRemaining()) return true; @@ -770,6 +773,7 @@ public static boolean hasRemaining(ByteBuffer[] bufs) { } public static long remaining(List bufs) { + if (bufs == null) return 0L; long remain = 0; for (ByteBuffer buf : bufs) { remain += buf.remaining(); @@ -778,12 +782,14 @@ public static long remaining(List bufs) { } public static long synchronizedRemaining(List bufs) { + if (bufs == null) return 0L; synchronized (bufs) { return remaining(bufs); } } - public static int remaining(List bufs, int max) { + public static long remaining(List bufs, long max) { + if (bufs == null) return 0; long remain = 0; for (ByteBuffer buf : bufs) { remain += buf.remaining(); @@ -794,7 +800,13 @@ public static int remaining(List bufs, int max) { return (int) remain; } - public static int remaining(ByteBuffer[] refs, int max) { + public static int remaining(List bufs, int max) { + // safe cast since max is an int + return (int) remaining(bufs, (long) max); + } + + public static long remaining(ByteBuffer[] refs, long max) { + if (refs == null) return 0; long remain = 0; for (ByteBuffer b : refs) { remain += b.remaining(); @@ -805,6 +817,11 @@ public static int remaining(ByteBuffer[] refs, int max) { return (int) remain; } + public static int remaining(ByteBuffer[] refs, int max) { + // safe cast since max is an int + return (int) remaining(refs, (long) max); + } + public static void close(Closeable... closeables) { for (Closeable c : closeables) { try { diff --git a/src/java.rmi/share/man/rmiregistry.1 b/src/java.rmi/share/man/rmiregistry.1 index 29a2e2c965a..c168e1482a6 100644 --- a/src/java.rmi/share/man/rmiregistry.1 +++ b/src/java.rmi/share/man/rmiregistry.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "RMIREGISTRY" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "RMIREGISTRY" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.scripting/share/man/jrunscript.1 b/src/java.scripting/share/man/jrunscript.1 index 43029582b3e..59389c274d1 100644 --- a/src/java.scripting/share/man/jrunscript.1 +++ b/src/java.scripting/share/man/jrunscript.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JRUNSCRIPT" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JRUNSCRIPT" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp index 036d0c8b667..32fbcded07e 100644 --- a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp +++ b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2773,7 +2773,7 @@ WinAccessBridge::getAccessibleTextItems(long vmID, if (destABWindow != (HWND) 0) { if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) { memcpy(textItems, &(pkg->rTextItemsInfo), sizeof(AccessibleTextItemsInfo)); - if (pkg->rTextItemsInfo.letter != '/0') { + if (pkg->rTextItemsInfo.letter != '\0') { return TRUE; } } diff --git a/src/jdk.compiler/share/data/symbols/java.base-N.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-N.sym.txt index 905a0db8b73..8fab1f56765 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-N.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-N.sym.txt @@ -34,6 +34,7 @@ class name java/io/ByteArrayOutputStream method name writeTo descriptor (Ljava/io/OutputStream;)V thrownTypes java/io/IOException flags 1 class name java/io/Console +header extends java/lang/Object implements java/io/Flushable sealed true permittedSubclasses java/io/ProxyingConsole flags 21 method name format descriptor (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/Console; flags 81 method name printf descriptor (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/Console; flags 81 method name readLine descriptor (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; flags 81 @@ -63,6 +64,27 @@ method name println descriptor (Ljava/lang/Object;)Ljava/io/Console; flags 1 method name print descriptor (Ljava/lang/Object;)Ljava/io/Console; flags 1 method name readln descriptor (Ljava/lang/String;)Ljava/lang/String; flags 1 +class name java/lang/ScopedValue +header extends java/lang/Object nestMembers java/lang/ScopedValue$CallableOp,java/lang/ScopedValue$Carrier flags 31 signature Ljava/lang/Object; classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;SCOPED_VALUES;) +innerclass innerClass java/lang/ScopedValue$Carrier outerClass java/lang/ScopedValue innerClassName Carrier flags 19 +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 +-method name callWhere descriptor (Ljava/lang/ScopedValue;Ljava/lang/Object;Ljava/util/concurrent/Callable;)Ljava/lang/Object; +-method name getWhere descriptor (Ljava/lang/ScopedValue;Ljava/lang/Object;Ljava/util/function/Supplier;)Ljava/lang/Object; +method name callWhere descriptor (Ljava/lang/ScopedValue;Ljava/lang/Object;Ljava/lang/ScopedValue$CallableOp;)Ljava/lang/Object; thrownTypes java/lang/Throwable flags 9 signature (Ljava/lang/ScopedValue;TT;Ljava/lang/ScopedValue$CallableOp<+TR;TX;>;)TR;^TX; + +class name java/lang/ScopedValue$CallableOp +header extends java/lang/Object nestHost java/lang/ScopedValue flags 601 signature Ljava/lang/Object; classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;SCOPED_VALUES;) runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 +method name call descriptor ()Ljava/lang/Object; thrownTypes java/lang/Throwable flags 401 signature ()TT;^TX; + +class name java/lang/ScopedValue$Carrier +header extends java/lang/Object nestHost java/lang/ScopedValue flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;SCOPED_VALUES;) +innerclass innerClass java/lang/ScopedValue$Carrier outerClass java/lang/ScopedValue innerClassName Carrier flags 19 +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 +-method name call descriptor (Ljava/util/concurrent/Callable;)Ljava/lang/Object; +-method name get descriptor (Ljava/util/function/Supplier;)Ljava/lang/Object; +method name call descriptor (Ljava/lang/ScopedValue$CallableOp;)Ljava/lang/Object; thrownTypes java/lang/Throwable flags 1 signature (Ljava/lang/ScopedValue$CallableOp<+TR;TX;>;)TR;^TX; + -class name java/lang/StringTemplate -class name java/lang/StringTemplate$Processor @@ -175,6 +197,12 @@ innerclass innerClass java/lang/classfile/ClassFile$ShortJumpsOption outerClass innerclass innerClass java/lang/classfile/ClassFile$StackMapsOption outerClass java/lang/classfile/ClassFile innerClassName StackMapsOption flags 4019 innerclass innerClass java/lang/classfile/ClassFile$AttributesProcessingOption outerClass java/lang/classfile/ClassFile innerClassName AttributesProcessingOption flags 4019 +class name java/lang/classfile/ClassReader +-method name thisClassPos descriptor ()I +-method name skipAttributeHolder descriptor (I)I +-method name utf8EntryByIndex descriptor (I)Ljava/lang/classfile/constantpool/Utf8Entry; +method name readEntryOrNull descriptor (ILjava/lang/Class;)Ljava/lang/classfile/constantpool/PoolEntry; flags 401 signature (ILjava/lang/Class;)TT; + class name java/lang/classfile/ClassSignature header extends java/lang/Object sealed true permittedSubclasses jdk/internal/classfile/impl/SignaturesImpl$ClassSignatureImpl flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;CLASSFILE_API;) innerclass innerClass java/lang/classfile/Signature$ClassTypeSig outerClass java/lang/classfile/Signature innerClassName ClassTypeSig flags 609 @@ -311,6 +339,12 @@ class name java/lang/classfile/TypeKind method name newarrayCode descriptor ()I flags 1 method name fromNewarrayCode descriptor (I)Ljava/lang/classfile/TypeKind; flags 9 +class name java/lang/classfile/components/ClassPrinter$ListNode +header extends java/lang/Object implements java/lang/classfile/components/ClassPrinter$Node,java/util/List nestHost java/lang/classfile/components/ClassPrinter sealed true permittedSubclasses jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl flags 601 signature Ljava/lang/Object;Ljava/lang/classfile/components/ClassPrinter$Node;Ljava/util/List; classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;CLASSFILE_API;) +innerclass innerClass java/lang/classfile/components/ClassPrinter$ListNode outerClass java/lang/classfile/components/ClassPrinter innerClassName ListNode flags 609 +innerclass innerClass java/lang/classfile/components/ClassPrinter$Node outerClass java/lang/classfile/components/ClassPrinter innerClassName Node flags 609 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName ListNodeImpl flags 9 + class name java/lang/classfile/components/ClassPrinter$Node header extends java/lang/Object nestHost java/lang/classfile/components/ClassPrinter sealed true permittedSubclasses java/lang/classfile/components/ClassPrinter$LeafNode,java/lang/classfile/components/ClassPrinter$ListNode,java/lang/classfile/components/ClassPrinter$MapNode flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;CLASSFILE_API;) innerclass innerClass java/lang/classfile/components/ClassPrinter$Node outerClass java/lang/classfile/components/ClassPrinter innerClassName Node flags 609 @@ -318,6 +352,9 @@ innerclass innerClass java/lang/classfile/components/ClassPrinter$LeafNode outer innerclass innerClass java/lang/classfile/components/ClassPrinter$ListNode outerClass java/lang/classfile/components/ClassPrinter innerClassName ListNode flags 609 innerclass innerClass java/lang/classfile/components/ClassPrinter$MapNode outerClass java/lang/classfile/components/ClassPrinter innerClassName MapNode flags 609 +class name java/lang/classfile/constantpool/ConstantPool +method name entryByIndex descriptor (ILjava/lang/Class;)Ljava/lang/classfile/constantpool/PoolEntry; flags 401 signature (ILjava/lang/Class;)TT; + class name java/lang/constant/ClassDesc header extends java/lang/Object implements java/lang/constant/ConstantDesc,java/lang/invoke/TypeDescriptor$OfField sealed true permittedSubclasses jdk/internal/constant/PrimitiveClassDescImpl,jdk/internal/constant/ReferenceClassDescImpl flags 601 signature Ljava/lang/Object;Ljava/lang/constant/ConstantDesc;Ljava/lang/invoke/TypeDescriptor$OfField; innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 @@ -419,6 +456,12 @@ method name setTTL descriptor (B)V thrownTypes java/io/IOException flags 1 depre method name getTTL descriptor ()B thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") method name send descriptor (Ljava/net/DatagramPacket;B)V thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.4") +class name java/net/Socket +-method name descriptor (Ljava/lang/String;IZ)V +-method name descriptor (Ljava/net/InetAddress;IZ)V +method name descriptor (Ljava/lang/String;IZ)V thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.1") +method name descriptor (Ljava/net/InetAddress;IZ)V thrownTypes java/io/IOException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.1") + class name java/nio/HeapByteBuffer method name hashCode descriptor ()I flags 1 @@ -461,6 +504,10 @@ method name isStrict descriptor ()Z flags 1 method name setStrict descriptor (Z)V flags 1 method name toString descriptor ()Ljava/lang/String; flags 1 +class name java/text/DecimalFormatSymbols +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + class name java/text/MessageFormat header extends java/text/Format nestMembers java/text/MessageFormat$Field flags 21 innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 @@ -521,6 +568,12 @@ method name getTotalOut descriptor ()I flags 1 deprecated true runtimeAnnotation class name java/util/zip/ZipFile method name toString descriptor ()Ljava/lang/String; flags 1 +class name javax/security/auth/Subject +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name jdk/internal/classfile/impl/AbstractInstruction header extends jdk/internal/classfile/impl/AbstractElement implements java/lang/classfile/Instruction nestMembers jdk/internal/classfile/impl/AbstractInstruction$UnboundRetInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundJsrInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundNopInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundMonitorInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundLoadConstantInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundArgumentConstantInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundIntrinsicConstantInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundOperatorInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundConvertInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundStackInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundTypeCheckInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundArrayStoreInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundArrayLoadInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundNewMultidimensionalArrayInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundNewReferenceArrayInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundNewPrimitiveArrayInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundNewObjectInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundInvokeDynamicInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundInvokeInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundFieldInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundThrowInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundReturnInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundTableSwitchInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundLookupSwitchInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundBranchInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundIncrementInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundStoreInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundLoadInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundRetInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundJsrInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundLoadConstantInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundArgumentConstantInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundTypeCheckInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundNewMultidimensionalArrayInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundNewReferenceArrayInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundNewPrimitiveArrayInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundNewObjectInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundInvokeDynamicInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundInvokeInterfaceInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundInvokeInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundFieldInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundTableSwitchInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundLookupSwitchInstruction,jdk/internal/classfile/impl/AbstractInstruction$SwitchCaseImpl,jdk/internal/classfile/impl/AbstractInstruction$BoundBranchInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundIncrementInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundStoreInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundLoadInstruction,jdk/internal/classfile/impl/AbstractInstruction$BoundInstruction sealed true permittedSubclasses jdk/internal/classfile/impl/AbstractInstruction$BoundInstruction,jdk/internal/classfile/impl/AbstractInstruction$UnboundInstruction flags 421 innerclass innerClass jdk/internal/classfile/impl/AbstractInstruction$UnboundRetInstruction outerClass jdk/internal/classfile/impl/AbstractInstruction innerClassName UnboundRetInstruction flags 19 @@ -747,10 +800,10 @@ innerclass innerClass jdk/internal/classfile/impl/BoundAttribute$BoundStackMapTa method name standardAttribute descriptor (Ljava/lang/classfile/constantpool/Utf8Entry;)Ljava/lang/classfile/AttributeMapper; flags 9 signature (Ljava/lang/classfile/constantpool/Utf8Entry;)Ljava/lang/classfile/AttributeMapper<*>; class name jdk/internal/classfile/impl/ClassPrinterImpl -header extends java/lang/Object nestMembers jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl,jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl,jdk/internal/classfile/impl/ClassPrinterImpl$LeafNodeImpl flags 31 +header extends java/lang/Object nestMembers jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl,jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl,jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl,jdk/internal/classfile/impl/ClassPrinterImpl$LeafNodeImpl flags 31 innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$LeafNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName LeafNodeImpl flags 19 innerclass innerClass java/lang/classfile/components/ClassPrinter$Node outerClass java/lang/classfile/components/ClassPrinter innerClassName Node flags 609 -innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName ListNodeImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName ListNodeImpl flags 9 innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName MapNodeImpl flags 19 innerclass innerClass java/lang/classfile/components/ClassPrinter$LeafNode outerClass java/lang/classfile/components/ClassPrinter innerClassName LeafNode flags 609 innerclass innerClass java/lang/classfile/AnnotationValue$OfString outerClass java/lang/classfile/AnnotationValue innerClassName OfString flags 609 @@ -781,8 +834,63 @@ innerclass innerClass java/lang/classfile/attribute/StackMapFrameInfo$Verificati innerclass innerClass java/lang/classfile/attribute/StackMapFrameInfo$SimpleVerificationTypeInfo outerClass java/lang/classfile/attribute/StackMapFrameInfo innerClassName SimpleVerificationTypeInfo flags 4019 innerclass innerClass java/lang/classfile/attribute/StackMapFrameInfo$ObjectVerificationTypeInfo outerClass java/lang/classfile/attribute/StackMapFrameInfo innerClassName ObjectVerificationTypeInfo flags 609 innerclass innerClass java/lang/classfile/attribute/StackMapFrameInfo$UninitializedVerificationTypeInfo outerClass java/lang/classfile/attribute/StackMapFrameInfo innerClassName UninitializedVerificationTypeInfo flags 609 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl innerClassName PrivateListNodeImpl flags 1a innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +class name jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl +header extends java/util/AbstractList implements java/lang/classfile/components/ClassPrinter$ListNode nestHost jdk/internal/classfile/impl/ClassPrinterImpl sealed true permittedSubclasses jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl flags 21 signature Ljava/util/AbstractList;Ljava/lang/classfile/components/ClassPrinter$ListNode; +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName ListNodeImpl flags 9 +innerclass innerClass java/lang/classfile/components/ClassPrinter$Node outerClass java/lang/classfile/components/ClassPrinter innerClassName Node flags 609 +innerclass innerClass java/lang/classfile/components/ClassPrinter$ListNode outerClass java/lang/classfile/components/ClassPrinter innerClassName ListNode flags 609 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName MapNodeImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl innerClassName PrivateListNodeImpl flags 1a +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +field name nodes descriptor Ljava/util/List; flags 14 signature Ljava/util/List; +method name descriptor (Ljdk/internal/classfile/impl/ClassPrinterImpl$Style;Ljava/lang/constant/ConstantDesc;Ljava/util/List;)V flags 4 signature (Ljdk/internal/classfile/impl/ClassPrinterImpl$Style;Ljava/lang/constant/ConstantDesc;Ljava/util/List;)V + +class name jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl +header extends java/lang/Object implements java/lang/classfile/components/ClassPrinter$MapNode nestHost jdk/internal/classfile/impl/ClassPrinterImpl flags 31 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName MapNodeImpl flags 19 +innerclass innerClass java/lang/classfile/components/ClassPrinter$Node outerClass java/lang/classfile/components/ClassPrinter innerClassName Node flags 609 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl innerClassName PrivateListNodeImpl flags 1a +innerclass innerClass java/lang/classfile/components/ClassPrinter$MapNode outerClass java/lang/classfile/components/ClassPrinter innerClassName MapNode flags 609 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl +header extends jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl nestHost jdk/internal/classfile/impl/ClassPrinterImpl flags 30 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$ListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName ListNodeImpl flags 9 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl innerClassName MapNodeImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl$PrivateListNodeImpl outerClass jdk/internal/classfile/impl/ClassPrinterImpl$MapNodeImpl innerClassName PrivateListNodeImpl flags 1a +innerclass innerClass java/lang/classfile/components/ClassPrinter$Node outerClass java/lang/classfile/components/ClassPrinter innerClassName Node flags 609 + +class name jdk/internal/classfile/impl/ClassReaderImpl +header extends java/lang/Object implements java/lang/classfile/ClassReader flags 31 +innerclass innerClass java/lang/classfile/ClassFile$AttributeMapperOption outerClass java/lang/classfile/ClassFile innerClassName AttributeMapperOption flags 609 +innerclass innerClass jdk/internal/classfile/impl/UnboundAttribute$EmptyBootstrapAttribute outerClass jdk/internal/classfile/impl/UnboundAttribute innerClassName EmptyBootstrapAttribute flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$MethodHandleEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName MethodHandleEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$Utf8EntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName Utf8EntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$IntegerEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName IntegerEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$FloatEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName FloatEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$LongEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName LongEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$DoubleEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName DoubleEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$ClassEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName ClassEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$StringEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName StringEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$FieldRefEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName FieldRefEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$MethodRefEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName MethodRefEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$InterfaceMethodRefEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName InterfaceMethodRefEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$NameAndTypeEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName NameAndTypeEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$MethodTypeEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName MethodTypeEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$ConstantDynamicEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName ConstantDynamicEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$InvokeDynamicEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName InvokeDynamicEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$ModuleEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName ModuleEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$PackageEntryImpl outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName PackageEntryImpl flags 19 +innerclass innerClass jdk/internal/classfile/impl/AbstractPoolEntry$AbstractMemberRefEntry outerClass jdk/internal/classfile/impl/AbstractPoolEntry innerClassName AbstractMemberRefEntry flags 409 +-method name utf8EntryByIndex descriptor (I)Ljdk/internal/classfile/impl/AbstractPoolEntry$Utf8EntryImpl; +-method name utf8EntryByIndex descriptor (I)Ljava/lang/classfile/constantpool/Utf8Entry; +method name entryByIndex descriptor (ILjava/lang/Class;)Ljava/lang/classfile/constantpool/PoolEntry; flags 1 signature (ILjava/lang/Class;)TT; +method name readEntryOrNull descriptor (ILjava/lang/Class;)Ljava/lang/classfile/constantpool/PoolEntry; flags 1 signature (ILjava/lang/Class;)TT; + class name jdk/internal/classfile/impl/ClassRemapperImpl header extends java/lang/Record implements java/lang/classfile/components/ClassRemapper record true flags 31 recordcomponent name mapFunction descriptor Ljava/util/function/Function; signature Ljava/util/function/Function; @@ -893,6 +1001,22 @@ field name INSTANCE descriptor Ljdk/internal/classfile/impl/SignaturesImpl$Unbou method name values descriptor ()[Ljdk/internal/classfile/impl/SignaturesImpl$UnboundedTypeArgImpl; flags 9 method name valueOf descriptor (Ljava/lang/String;)Ljdk/internal/classfile/impl/SignaturesImpl$UnboundedTypeArgImpl; flags 9 methodParameters 8000:null +class name jdk/internal/classfile/impl/SplitConstantPool +method name entryByIndex descriptor (ILjava/lang/Class;)Ljava/lang/classfile/constantpool/PoolEntry; flags 1 signature (ILjava/lang/Class;)TT; + +class name jdk/internal/classfile/impl/StackMapDecoder$ObjectVerificationTypeInfoImpl +header extends java/lang/Record implements java/lang/classfile/attribute/StackMapFrameInfo$ObjectVerificationTypeInfo nestHost jdk/internal/classfile/impl/StackMapDecoder record true flags 31 +recordcomponent name className descriptor Ljava/lang/classfile/constantpool/ClassEntry; +innerclass innerClass jdk/internal/classfile/impl/StackMapDecoder$ObjectVerificationTypeInfoImpl outerClass jdk/internal/classfile/impl/StackMapDecoder innerClassName ObjectVerificationTypeInfoImpl flags 19 +innerclass innerClass java/lang/classfile/attribute/StackMapFrameInfo$ObjectVerificationTypeInfo outerClass java/lang/classfile/attribute/StackMapFrameInfo innerClassName ObjectVerificationTypeInfo flags 609 +-method name hashCode descriptor ()I +-method name equals descriptor (Ljava/lang/Object;)Z +method name equals descriptor (Ljava/lang/Object;)Z flags 1 +method name hashCode descriptor ()I flags 1 + +class name jdk/internal/classfile/impl/TemporaryConstantPool +method name entryByIndex descriptor (ILjava/lang/Class;)Ljava/lang/classfile/constantpool/PoolEntry; flags 1 signature (ILjava/lang/Class;)TT; + class name jdk/internal/classfile/impl/UnboundAttribute header extends jdk/internal/classfile/impl/AbstractElement implements java/lang/classfile/Attribute nestMembers jdk/internal/classfile/impl/UnboundAttribute$EmptyBootstrapAttribute,jdk/internal/classfile/impl/UnboundAttribute$AdHocAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleAttribute,jdk/internal/classfile/impl/UnboundAttribute$TypePathComponentImpl,jdk/internal/classfile/impl/UnboundAttribute$UnboundTypeAnnotation,jdk/internal/classfile/impl/UnboundAttribute$UnboundRecordComponentInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleRequiresInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleProvideInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleOpenInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleHashInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleExportInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundMethodParameterInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundLocalVariableTypeInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundLocalVariableInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundLineNumberInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundInnerClassInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundCharacterRangeInfo,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeInvisibleTypeAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleTypeAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeInvisibleParameterAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleParameterAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeInvisibleAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundLocalVariableTypeTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundLocalVariableTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundLineNumberTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundCharacterRangeTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceDebugExtensionAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceIDAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundCompilationIDAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundNestHostAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundNestMembersAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundPermittedSubclassesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleResolutionAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModulePackagesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleHashesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleMainClassAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleTargetAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundMethodParametersAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundEnclosingMethodAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRecordAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundInnerClassesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundStackMapTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceFileAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundAnnotationDefaultAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundExceptionsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSignatureAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSyntheticAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundDeprecatedAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundConstantValueAttribute sealed true permittedSubclasses jdk/internal/classfile/impl/UnboundAttribute$UnboundConstantValueAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundDeprecatedAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSyntheticAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSignatureAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundExceptionsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundAnnotationDefaultAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceFileAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundStackMapTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundInnerClassesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRecordAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundEnclosingMethodAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundMethodParametersAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleTargetAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleMainClassAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleHashesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModulePackagesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleResolutionAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundPermittedSubclassesAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundNestMembersAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundNestHostAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundCompilationIDAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceIDAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundSourceDebugExtensionAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundCharacterRangeTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundLineNumberTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundLocalVariableTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundLocalVariableTypeTableAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeInvisibleAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleParameterAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeInvisibleParameterAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeVisibleTypeAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundRuntimeInvisibleTypeAnnotationsAttribute,jdk/internal/classfile/impl/UnboundAttribute$UnboundModuleAttribute,jdk/internal/classfile/impl/UnboundAttribute$AdHocAttribute,jdk/internal/classfile/impl/UnboundAttribute$EmptyBootstrapAttribute flags 421 signature ;>Ljdk/internal/classfile/impl/AbstractElement;Ljava/lang/classfile/Attribute; innerclass innerClass jdk/internal/classfile/impl/UnboundAttribute$EmptyBootstrapAttribute outerClass jdk/internal/classfile/impl/UnboundAttribute innerClassName EmptyBootstrapAttribute flags 19 @@ -970,7 +1094,6 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 innerclass innerClass java/lang/invoke/TypeDescriptor$OfMethod outerClass java/lang/invoke/TypeDescriptor innerClassName OfMethod flags 609 method name ofTrusted descriptor (Ljava/lang/constant/ClassDesc;[Ljava/lang/constant/ClassDesc;)Ljdk/internal/constant/MethodTypeDescImpl; flags 9 -method name ofValidated descriptor (Ljava/lang/constant/ClassDesc;[Ljava/lang/constant/ClassDesc;)Ljdk/internal/constant/MethodTypeDescImpl; flags 9 method name ofDescriptor descriptor (Ljava/lang/String;)Ljdk/internal/constant/MethodTypeDescImpl; flags 9 method name returnType descriptor ()Ljava/lang/constant/ClassDesc; flags 1 method name parameterCount descriptor ()I flags 1 @@ -994,6 +1117,7 @@ method name changeReturnType descriptor (Ljava/lang/invoke/TypeDescriptor$OfFiel method name parameterArray descriptor ()[Ljava/lang/invoke/TypeDescriptor$OfField; flags 1041 method name returnType descriptor ()Ljava/lang/invoke/TypeDescriptor$OfField; flags 1041 method name parameterType descriptor (I)Ljava/lang/invoke/TypeDescriptor$OfField; flags 1041 methodParameters 1000:null +method name ofValidated descriptor (Ljava/lang/constant/ClassDesc;[Ljava/lang/constant/ClassDesc;)Ljdk/internal/constant/MethodTypeDescImpl; flags 89 class name jdk/internal/constant/ModuleDescImpl header extends java/lang/Record implements java/lang/constant/ModuleDesc record true flags 31 diff --git a/src/jdk.compiler/share/data/symbols/java.desktop-N.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-N.sym.txt index 38cfc456f03..fdc899578cf 100644 --- a/src/jdk.compiler/share/data/symbols/java.desktop-N.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.desktop-N.sym.txt @@ -26,6 +26,9 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name java.desktop +header exports java/applet,java/awt,java/awt/color,java/awt/desktop,java/awt/dnd,java/awt/event,java/awt/font,java/awt/geom,java/awt/im,java/awt/im/spi,java/awt/image,java/awt/image/renderable,java/awt/print,java/beans,java/beans/beancontext,javax/accessibility,javax/imageio,javax/imageio/event,javax/imageio/metadata,javax/imageio/plugins/bmp,javax/imageio/plugins/jpeg,javax/imageio/plugins/tiff,javax/imageio/spi,javax/imageio/stream,javax/print,javax/print/attribute,javax/print/attribute/standard,javax/print/event,javax/sound/midi,javax/sound/midi/spi,javax/sound/sampled,javax/sound/sampled/spi,javax/swing,javax/swing/border,javax/swing/colorchooser,javax/swing/event,javax/swing/filechooser,javax/swing/plaf,javax/swing/plaf/basic,javax/swing/plaf/metal,javax/swing/plaf/multi,javax/swing/plaf/nimbus,javax/swing/plaf/synth,javax/swing/table,javax/swing/text,javax/swing/text/html,javax/swing/text/html/parser,javax/swing/text/rtf,javax/swing/tree,javax/swing/undo extraModulePackages sun/print requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.prefs\u0020;flags\u0020;0,name\u0020;java.datatransfer\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20 uses java/awt/im/spi/InputMethodDescriptor,javax/accessibility/AccessibilityProvider,javax/imageio/spi/ImageInputStreamSpi,javax/imageio/spi/ImageOutputStreamSpi,javax/imageio/spi/ImageReaderSpi,javax/imageio/spi/ImageTranscoderSpi,javax/imageio/spi/ImageWriterSpi,javax/print/PrintServiceLookup,javax/print/StreamPrintServiceFactory,javax/sound/midi/spi/MidiDeviceProvider,javax/sound/midi/spi/MidiFileReader,javax/sound/midi/spi/MidiFileWriter,javax/sound/midi/spi/SoundbankReader,javax/sound/sampled/spi/AudioFileReader,javax/sound/sampled/spi/AudioFileWriter,javax/sound/sampled/spi/FormatConversionProvider,javax/sound/sampled/spi/MixerProvider,sun/swing/InteropProvider provides interface\u0020;sun/datatransfer/DesktopDatatransferService\u0020;impls\u0020;sun/awt/datatransfer/DesktopDatatransferServiceImpl,interface\u0020;java/net/ContentHandlerFactory\u0020;impls\u0020;sun/awt/www/content/MultimediaContentHandlers,interface\u0020;javax/print/PrintServiceLookup\u0020;impls\u0020;sun/print/PrintServiceLookupProvider,interface\u0020;javax/print/StreamPrintServiceFactory\u0020;impls\u0020;sun/print/PSStreamPrinterFactory,interface\u0020;javax/sound/midi/spi/MidiDeviceProvider\u0020;impls\u0020;com/sun/media/sound/MidiInDeviceProvider\u005C;u002C;com/sun/media/sound/MidiOutDeviceProvider\u005C;u002C;com/sun/media/sound/RealTimeSequencerProvider\u005C;u002C;com/sun/media/sound/SoftProvider,interface\u0020;javax/sound/midi/spi/MidiFileReader\u0020;impls\u0020;com/sun/media/sound/StandardMidiFileReader,interface\u0020;javax/sound/midi/spi/MidiFileWriter\u0020;impls\u0020;com/sun/media/sound/StandardMidiFileWriter,interface\u0020;javax/sound/midi/spi/SoundbankReader\u0020;impls\u0020;com/sun/media/sound/AudioFileSoundbankReader\u005C;u002C;com/sun/media/sound/DLSSoundbankReader\u005C;u002C;com/sun/media/sound/JARSoundbankReader\u005C;u002C;com/sun/media/sound/SF2SoundbankReader,interface\u0020;javax/sound/sampled/spi/AudioFileReader\u0020;impls\u0020;com/sun/media/sound/AiffFileReader\u005C;u002C;com/sun/media/sound/AuFileReader\u005C;u002C;com/sun/media/sound/SoftMidiAudioFileReader\u005C;u002C;com/sun/media/sound/WaveFileReader\u005C;u002C;com/sun/media/sound/WaveFloatFileReader\u005C;u002C;com/sun/media/sound/WaveExtensibleFileReader,interface\u0020;javax/sound/sampled/spi/AudioFileWriter\u0020;impls\u0020;com/sun/media/sound/AiffFileWriter\u005C;u002C;com/sun/media/sound/AuFileWriter\u005C;u002C;com/sun/media/sound/WaveFileWriter\u005C;u002C;com/sun/media/sound/WaveFloatFileWriter,interface\u0020;javax/sound/sampled/spi/FormatConversionProvider\u0020;impls\u0020;com/sun/media/sound/AlawCodec\u005C;u002C;com/sun/media/sound/AudioFloatFormatConverter\u005C;u002C;com/sun/media/sound/PCMtoPCMCodec\u005C;u002C;com/sun/media/sound/UlawCodec,interface\u0020;javax/sound/sampled/spi/MixerProvider\u0020;impls\u0020;com/sun/media/sound/DirectAudioDeviceProvider\u005C;u002C;com/sun/media/sound/PortMixerProvider target linux-amd64 flags 8000 + class name java/beans/Beans -method name instantiate descriptor (Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/beans/beancontext/BeanContext;)Ljava/lang/Object; method name instantiate descriptor (Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/beans/beancontext/BeanContext;)Ljava/lang/Object; thrownTypes java/io/IOException,java/lang/ClassNotFoundException flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="23") @@ -93,6 +96,25 @@ innerclass innerClass java/beans/beancontext/BeanContextSupport$BCSIterator oute innerclass innerClass java/beans/beancontext/BeanContextSupport$BCSChild outerClass java/beans/beancontext/BeanContextSupport innerClassName BCSChild flags 4 innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +class name javax/print/attribute/standard/OutputBin +header extends javax/print/attribute/EnumSyntax implements javax/print/attribute/PrintRequestAttribute,javax/print/attribute/PrintJobAttribute sealed true permittedSubclasses sun/print/CustomOutputBin flags 21 +field name TOP descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name MIDDLE descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name BOTTOM descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name SIDE descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name LEFT descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name RIGHT descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name CENTER descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name REAR descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name FACE_UP descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name FACE_DOWN descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +field name LARGE_CAPACITY descriptor Ljavax/print/attribute/standard/OutputBin; flags 19 +method name descriptor (I)V flags 4 +method name getStringTable descriptor ()[Ljava/lang/String; flags 4 +method name getEnumValueTable descriptor ()[Ljavax/print/attribute/EnumSyntax; flags 4 +method name getCategory descriptor ()Ljava/lang/Class; flags 11 signature ()Ljava/lang/Class<+Ljavax/print/attribute/Attribute;>; +method name getName descriptor ()Ljava/lang/String; flags 11 + class name javax/swing/JScrollBar method name setMinimumSize descriptor (Ljava/awt/Dimension;)V flags 1 method name setMaximumSize descriptor (Ljava/awt/Dimension;)V flags 1 @@ -100,3 +122,13 @@ method name setMaximumSize descriptor (Ljava/awt/Dimension;)V flags 1 class name javax/swing/plaf/synth/SynthTreeUI method name getCollapsedIcon descriptor ()Ljavax/swing/Icon; flags 1 +class name sun/print/CustomOutputBin +header extends javax/print/attribute/standard/OutputBin flags 31 +method name createOutputBin descriptor (Ljava/lang/String;Ljava/lang/String;)Lsun/print/CustomOutputBin; flags 29 +method name getChoiceName descriptor ()Ljava/lang/String; flags 1 +method name getSuperEnumTable descriptor ()[Ljavax/print/attribute/standard/OutputBin; flags 1 +method name getStringTable descriptor ()[Ljava/lang/String; flags 4 +method name getCustomName descriptor ()Ljava/lang/String; flags 1 +method name getEnumValueTable descriptor ()[Lsun/print/CustomOutputBin; flags 4 +method name getEnumValueTable descriptor ()[Ljavax/print/attribute/EnumSyntax; flags 1044 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jshell-N.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-N.sym.txt index 5bbe0692944..da0509ee6c0 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.jshell-N.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.jshell-N.sym.txt @@ -26,6 +26,9 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name jdk.jshell +header exports jdk/jshell,jdk/jshell/execution,jdk/jshell/spi,jdk/jshell/tool requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;jdk.compiler\u0020;flags\u0020;0,name\u0020;jdk.internal.ed\u0020;flags\u0020;0,name\u0020;jdk.internal.le\u0020;flags\u0020;0,name\u0020;jdk.internal.md\u0020;flags\u0020;0,name\u0020;jdk.internal.opt\u0020;flags\u0020;0,name\u0020;java.compiler\u0020;flags\u0020;20,name\u0020;java.prefs\u0020;flags\u0020;20,name\u0020;jdk.jdi\u0020;flags\u0020;20 uses jdk/jshell/spi/ExecutionControlProvider,jdk/internal/editor/spi/BuildInEditorProvider provides interface\u0020;javax/tools/Tool\u0020;impls\u0020;jdk/internal/jshell/tool/JShellToolProvider,interface\u0020;jdk/jshell/spi/ExecutionControlProvider\u0020;impls\u0020;jdk/jshell/execution/JdiExecutionControlProvider\u005C;u002C;jdk/jshell/execution/LocalExecutionControlProvider\u005C;u002C;jdk/jshell/execution/FailOverExecutionControlProvider,interface\u0020;jdk/internal/io/JdkConsoleProvider\u0020;impls\u0020;jdk/jshell/execution/impl/ConsoleImpl$ConsoleProviderImpl target linux-amd64 moduleMainClass jdk/internal/jshell/tool/JShellToolProvider flags 8000 classAnnotations @Ljdk/internal/javac/ParticipatesInPreview; + class name jdk/jshell/Snippet$SubKind field name MODULE_IMPORT_SUBKIND descriptor Ljdk/jshell/Snippet$SubKind; flags 4019 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;MODULE_IMPORTS;,reflective=Ztrue) diff --git a/src/jdk.compiler/share/man/javac.1 b/src/jdk.compiler/share/man/javac.1 index de374e7d0c7..ebee0369238 100644 --- a/src/jdk.compiler/share/man/javac.1 +++ b/src/jdk.compiler/share/man/javac.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. .\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. .\" .\" This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JAVAC" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JAVAC" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.compiler/share/man/serialver.1 b/src/jdk.compiler/share/man/serialver.1 index cd437b7e9bf..bad14872ee6 100644 --- a/src/jdk.compiler/share/man/serialver.1 +++ b/src/jdk.compiler/share/man/serialver.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "SERIALVER" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "SERIALVER" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.hotspot.agent/share/man/jhsdb.1 b/src/jdk.hotspot.agent/share/man/jhsdb.1 index 30b2d3fe95c..5b65f7eafb4 100644 --- a/src/jdk.hotspot.agent/share/man/jhsdb.1 +++ b/src/jdk.hotspot.agent/share/man/jhsdb.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JHSDB" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JHSDB" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.hotspot.agent/test/libproc/Makefile b/src/jdk.hotspot.agent/test/libproc/Makefile index 81fadaeb552..c7b171bc633 100644 --- a/src/jdk.hotspot.agent/test/libproc/Makefile +++ b/src/jdk.hotspot.agent/test/libproc/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -19,7 +19,7 @@ # 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. -# +# # all: diff --git a/src/jdk.httpserver/share/man/jwebserver.1 b/src/jdk.httpserver/share/man/jwebserver.1 index 3c48d81fc9c..4fbaf9dd09d 100644 --- a/src/jdk.httpserver/share/man/jwebserver.1 +++ b/src/jdk.httpserver/share/man/jwebserver.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JWEBSERVER" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JWEBSERVER" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java index 9f611b0dfce..c76ec64278a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java @@ -233,6 +233,7 @@ public enum CPUFeature implements CPUFeatureName { CET_SS, AVX512_IFMA, AVX_IFMA, + APX_F, } private final EnumSet features; diff --git a/src/jdk.jartool/share/man/jar.1 b/src/jdk.jartool/share/man/jar.1 index 49a028e0f29..2d983eb561e 100644 --- a/src/jdk.jartool/share/man/jar.1 +++ b/src/jdk.jartool/share/man/jar.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JAR" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JAR" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1 index ea8f686a4c8..d085efcfcd0 100644 --- a/src/jdk.jartool/share/man/jarsigner.1 +++ b/src/jdk.jartool/share/man/jarsigner.1 @@ -36,7 +36,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JARSIGNER" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JARSIGNER" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.javadoc/share/man/javadoc.1 b/src/jdk.javadoc/share/man/javadoc.1 index 73d12efbf30..4e256a7ce38 100644 --- a/src/jdk.javadoc/share/man/javadoc.1 +++ b/src/jdk.javadoc/share/man/javadoc.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JAVADOC" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JAVADOC" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP @@ -218,7 +218,7 @@ summary is required. For more explicit control in any individual documentation comment, enclose the contents of the first sentence in a \f[V]{\[at]summary ...}\f[R] tag, or when applicable, in a -\[ga]{\[at]return ...} tag. +\f[V]{\[at]return ...}\f[R] tag. .RE .TP \f[V]-doclet\f[R] \f[I]class\f[R] @@ -522,7 +522,8 @@ Allow JavaScript in documentation comments, and options whose value is \f[I]html-code\f[R]. .TP \f[V]-author\f[R] -Includes the \f[V]\[at]author\f[R] text in the generated docs. +Includes the text of any \f[V]author\f[R] tags in the generated +documentation. .TP \f[V]-bottom\f[R] \f[I]html-code\f[R] Specifies the text to be placed at the bottom of each generated page. @@ -986,8 +987,8 @@ is used. .RE .TP \f[V]-nosince\f[R] -Omits from the generated documents the \f[V]Since\f[R] sections -associated with the \f[V]\[at]since\f[R] tags. +Omits from the generated documentation the \f[V]Since\f[R] sections +derived from any \f[V]since\f[R] tags. .TP \f[V]-notimestamp\f[R] Suppresses the time stamp, which is hidden in an HTML comment in the @@ -1020,9 +1021,6 @@ to the current working directory. .PP The file may be an HTML file, with a filename ending in \f[V].html\f[R], or a Markdown file, with a filename ending in \f[V].md\f[R]. -.PD 0 -.P -.PD If the file is an HTML file, the content for the overview documentation is taken from the \f[V]

\f[R] element in the file, if one is present, or from the \f[V]\f[R] element is there is no @@ -1213,10 +1211,11 @@ To access the generated Use page, go to the class or package and click the \f[B]USE\f[R] link in the navigation bar. .TP \f[V]-version\f[R] -Includes the version text in the generated docs. +Includes the text of any \f[V]version\f[R] tags in the generated +documentation. This text is omitted by default. -To find out what version of the \f[V]javadoc\f[R] tool you are using, -use the \f[V]--version\f[R] option (with two hyphens). +Note: To find out what version of the \f[V]javadoc\f[R] tool you are +using, use the \f[V]--version\f[R] option (with two hyphens). .TP \f[V]-windowtitle\f[R] \f[I]title\f[R] Specifies the title to be placed in the HTML \f[V]\f[R] tag. diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index c88d2a22a41..2befaf5a949 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JCMD" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JCMD" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jinfo.1 b/src/jdk.jcmd/share/man/jinfo.1 index fc87807c6fe..49d8a852633 100644 --- a/src/jdk.jcmd/share/man/jinfo.1 +++ b/src/jdk.jcmd/share/man/jinfo.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JINFO" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JINFO" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jmap.1 b/src/jdk.jcmd/share/man/jmap.1 index 4865f43d1c4..42831aa68ac 100644 --- a/src/jdk.jcmd/share/man/jmap.1 +++ b/src/jdk.jcmd/share/man/jmap.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JMAP" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JMAP" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jps.1 b/src/jdk.jcmd/share/man/jps.1 index be506be2e82..cbc69872b60 100644 --- a/src/jdk.jcmd/share/man/jps.1 +++ b/src/jdk.jcmd/share/man/jps.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JPS" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JPS" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstack.1 b/src/jdk.jcmd/share/man/jstack.1 index 9effcb0902f..933db5fc80d 100644 --- a/src/jdk.jcmd/share/man/jstack.1 +++ b/src/jdk.jcmd/share/man/jstack.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JSTACK" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JSTACK" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstat.1 b/src/jdk.jcmd/share/man/jstat.1 index dd7d3832908..22e111a812b 100644 --- a/src/jdk.jcmd/share/man/jstat.1 +++ b/src/jdk.jcmd/share/man/jstat.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JSTAT" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JSTAT" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jconsole/share/man/jconsole.1 b/src/jdk.jconsole/share/man/jconsole.1 index ce1f948e6f1..ec70040acf4 100644 --- a/src/jdk.jconsole/share/man/jconsole.1 +++ b/src/jdk.jconsole/share/man/jconsole.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JCONSOLE" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JCONSOLE" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/javap.1 b/src/jdk.jdeps/share/man/javap.1 index f9ec998e0af..27b0a29d0ba 100644 --- a/src/jdk.jdeps/share/man/javap.1 +++ b/src/jdk.jdeps/share/man/javap.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JAVAP" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JAVAP" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeprscan.1 b/src/jdk.jdeps/share/man/jdeprscan.1 index ac850cf78de..fc13f05c449 100644 --- a/src/jdk.jdeps/share/man/jdeprscan.1 +++ b/src/jdk.jdeps/share/man/jdeprscan.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JDEPRSCAN" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JDEPRSCAN" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeps.1 b/src/jdk.jdeps/share/man/jdeps.1 index 53891441665..d3dde37e3b9 100644 --- a/src/jdk.jdeps/share/man/jdeps.1 +++ b/src/jdk.jdeps/share/man/jdeps.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JDEPS" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JDEPS" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdi/share/man/jdb.1 b/src/jdk.jdi/share/man/jdb.1 index 530c9bed6a1..88097ffeae4 100644 --- a/src/jdk.jdi/share/man/jdb.1 +++ b/src/jdk.jdi/share/man/jdb.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JDB" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JDB" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jfr/share/man/jfr.1 b/src/jdk.jfr/share/man/jfr.1 index c6a568582c0..71a487f558e 100644 --- a/src/jdk.jfr/share/man/jfr.1 +++ b/src/jdk.jfr/share/man/jfr.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JFR" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JFR" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/man/jlink.1 b/src/jdk.jlink/share/man/jlink.1 index 1a0b79a39c1..9f4bf38ffa5 100644 --- a/src/jdk.jlink/share/man/jlink.1 +++ b/src/jdk.jlink/share/man/jlink.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JLINK" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JLINK" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/man/jmod.1 b/src/jdk.jlink/share/man/jmod.1 index b26685615ed..4475505e524 100644 --- a/src/jdk.jlink/share/man/jmod.1 +++ b/src/jdk.jlink/share/man/jmod.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JMOD" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JMOD" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jpackage/share/man/jpackage.1 b/src/jdk.jpackage/share/man/jpackage.1 index f9848200059..13d9c41c31d 100644 --- a/src/jdk.jpackage/share/man/jpackage.1 +++ b/src/jdk.jpackage/share/man/jpackage.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JPACKAGE" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JPACKAGE" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java index 894d41d7642..c0ae65b3b0b 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.TEMP_ROOT; import static jdk.jpackage.internal.StandardBundlerParam.VENDOR; import static jdk.jpackage.internal.StandardBundlerParam.VERSION; +import jdk.jpackage.internal.WixToolset.WixToolsetType; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -253,7 +254,7 @@ public String getBundleType() { public boolean supported(boolean platformInstaller) { try { if (wixToolset == null) { - wixToolset = WixTool.toolset(); + wixToolset = WixTool.createToolset(); } return true; } catch (ConfigException ce) { @@ -300,7 +301,7 @@ public boolean validate(Map<String, ? super Object> params) appImageBundler.validate(params); if (wixToolset == null) { - wixToolset = WixTool.toolset(); + wixToolset = WixTool.createToolset(); } try { @@ -309,16 +310,17 @@ public boolean validate(Map<String, ? super Object> params) throw new ConfigException(ex); } - for (var toolInfo: wixToolset.values()) { + for (var tool : wixToolset.getType().getTools()) { Log.verbose(MessageFormat.format(I18N.getString( - "message.tool-version"), toolInfo.path.getFileName(), - toolInfo.version)); + "message.tool-version"), wixToolset.getToolPath(tool). + getFileName(), wixToolset.getVersion())); } - wixFragments.forEach(wixFragment -> wixFragment.setWixVersion( - wixToolset.get(WixTool.Light).version)); + wixFragments.forEach(wixFragment -> wixFragment.setWixVersion(wixToolset.getVersion(), + wixToolset.getType())); - wixFragments.get(0).logWixFeatures(); + wixFragments.stream().map(WixFragmentBuilder::getLoggableWixFeatures).flatMap( + List::stream).distinct().toList().forEach(Log::verbose); /********* validate bundle parameters *************/ @@ -512,22 +514,6 @@ private Map<String, String> prepareMainProjectFile( data.put("JpIsSystemWide", "yes"); } - // Copy standard l10n files. - for (String loc : Arrays.asList("de", "en", "ja", "zh_CN")) { - String fname = "MsiInstallerStrings_" + loc + ".wxl"; - createResource(fname, params) - .setCategory(I18N.getString("resource.wxl-file")) - .saveToFile(configDir.resolve(fname)); - } - - createResource("main.wxs", params) - .setCategory(I18N.getString("resource.main-wix-file")) - .saveToFile(configDir.resolve("main.wxs")); - - createResource("overrides.wxi", params) - .setCategory(I18N.getString("resource.overrides-wix-file")) - .saveToFile(configDir.resolve("overrides.wxi")); - return data; } @@ -542,13 +528,11 @@ private Path buildMSI(Map<String, ? super Object> params, .toString())); WixPipeline wixPipeline = new WixPipeline() - .setToolset(wixToolset.entrySet().stream().collect( - Collectors.toMap( - entry -> entry.getKey(), - entry -> entry.getValue().path))) - .setWixObjDir(TEMP_ROOT.fetchFrom(params).resolve("wixobj")) - .setWorkDir(WIN_APP_IMAGE.fetchFrom(params)) - .addSource(CONFIG_ROOT.fetchFrom(params).resolve("main.wxs"), wixVars); + .setToolset(wixToolset) + .setWixObjDir(TEMP_ROOT.fetchFrom(params).resolve("wixobj")) + .setWorkDir(WIN_APP_IMAGE.fetchFrom(params)) + .addSource(CONFIG_ROOT.fetchFrom(params).resolve("main.wxs"), + wixVars); for (var wixFragment : wixFragments) { wixFragment.configureWixPipeline(wixPipeline); @@ -557,16 +541,46 @@ private Path buildMSI(Map<String, ? super Object> params, Log.verbose(MessageFormat.format(I18N.getString( "message.generating-msi"), msiOut.toAbsolutePath().toString())); - wixPipeline.addLightOptions("-sice:ICE27"); + switch (wixToolset.getType()) { + case Wix3 -> { + wixPipeline.addLightOptions("-sice:ICE27"); + + if (!MSI_SYSTEM_WIDE.fetchFrom(params)) { + wixPipeline.addLightOptions("-sice:ICE91"); + } + } + case Wix4 -> { + } + default -> { + throw new IllegalArgumentException(); + } + } + + final Path configDir = CONFIG_ROOT.fetchFrom(params); + + var primaryWxlFiles = Stream.of("de", "en", "ja", "zh_CN").map(loc -> { + return configDir.resolve("MsiInstallerStrings_" + loc + ".wxl"); + }).toList(); + + var wixResources = new WixSourceConverter.ResourceGroup(wixToolset.getType()); - if (!MSI_SYSTEM_WIDE.fetchFrom(params)) { - wixPipeline.addLightOptions("-sice:ICE91"); + // Copy standard l10n files. + for (var path : primaryWxlFiles) { + var name = path.getFileName().toString(); + wixResources.addResource(createResource(name, params).setPublicName(name).setCategory( + I18N.getString("resource.wxl-file")), path); } + wixResources.addResource(createResource("main.wxs", params).setPublicName("main.wxs"). + setCategory(I18N.getString("resource.main-wix-file")), configDir.resolve("main.wxs")); + + wixResources.addResource(createResource("overrides.wxi", params).setPublicName( + "overrides.wxi").setCategory(I18N.getString("resource.overrides-wix-file")), + configDir.resolve("overrides.wxi")); + // Filter out custom l10n files that were already used to // override primary l10n files. Ignore case filename comparison, // both lists are expected to be short. - List<Path> primaryWxlFiles = getWxlFilesFromDir(params, CONFIG_ROOT); List<Path> customWxlFiles = getWxlFilesFromDir(params, RESOURCE_DIR).stream() .filter(custom -> primaryWxlFiles.stream().noneMatch(primary -> primary.getFileName().toString().equalsIgnoreCase( @@ -577,6 +591,17 @@ private Path buildMSI(Map<String, ? super Object> params, custom.getFileName().toString()))) .toList(); + // Copy custom l10n files. + for (var path : customWxlFiles) { + var name = path.getFileName().toString(); + wixResources.addResource(createResource(name, params).setPublicName(name). + setSourceOrder(OverridableResource.Source.ResourceDir).setCategory(I18N. + getString("resource.wxl-file")), configDir.resolve(name)); + } + + // Save all WiX resources into config dir. + wixResources.saveResources(); + // All l10n files are supplied to WiX with "-loc", but only // Cultures from custom files and a single primary Culture are // included into "-cultures" list @@ -586,6 +611,7 @@ private Path buildMSI(Map<String, ? super Object> params, List<String> cultures = new ArrayList<>(); for (var wxl : customWxlFiles) { + wxl = configDir.resolve(wxl.getFileName()); wixPipeline.addLightOptions("-loc", wxl.toAbsolutePath().normalize().toString()); cultures.add(getCultureFromWxlFile(wxl)); } @@ -598,8 +624,20 @@ private Path buildMSI(Map<String, ? super Object> params, // Build ordered list of unique cultures. Set<String> uniqueCultures = new LinkedHashSet<>(); uniqueCultures.addAll(cultures); - wixPipeline.addLightOptions(uniqueCultures.stream().collect( - Collectors.joining(";", "-cultures:", ""))); + switch (wixToolset.getType()) { + case Wix3 -> { + wixPipeline.addLightOptions(uniqueCultures.stream().collect(Collectors.joining(";", + "-cultures:", ""))); + } + case Wix4 -> { + uniqueCultures.forEach(culture -> { + wixPipeline.addLightOptions("-culture", culture); + }); + } + default -> { + throw new IllegalArgumentException(); + } + } wixPipeline.buildMsi(msiOut.toAbsolutePath()); @@ -751,7 +789,7 @@ private static OverridableResource initServiceInstallerResource( } private Path installerIcon; - private Map<WixTool, WixTool.ToolInfo> wixToolset; + private WixToolset wixToolset; private AppImageBundler appImageBundler; private final List<WixFragmentBuilder> wixFragments; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java index cf7338f7d0b..5bc20c1413c 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java @@ -64,6 +64,7 @@ import static jdk.jpackage.internal.WinMsiBundler.MSI_SYSTEM_WIDE; import static jdk.jpackage.internal.WinMsiBundler.SERVICE_INSTALLER; import static jdk.jpackage.internal.WinMsiBundler.WIN_APP_IMAGE; +import jdk.jpackage.internal.WixToolset.WixToolsetType; import org.w3c.dom.NodeList; /** @@ -152,6 +153,16 @@ void addFilesToConfigRoot() throws IOException { super.addFilesToConfigRoot(); } + @Override + List<String> getLoggableWixFeatures() { + if (isWithWix36Features()) { + return List.of(MessageFormat.format(I18N.getString("message.use-wix36-features"), + getWixVersion())); + } else { + return List.of(); + } + } + @Override protected Collection<XmlConsumer> getFragmentWriters() { return List.of( @@ -314,12 +325,25 @@ boolean isFile() { return cfg.isFile; } - static void startElement(XMLStreamWriter xml, String componentId, + static void startElement(WixToolsetType wixType, XMLStreamWriter xml, String componentId, String componentGuid) throws XMLStreamException, IOException { xml.writeStartElement("Component"); - xml.writeAttribute("Win64", is64Bit() ? "yes" : "no"); + switch (wixType) { + case Wix3 -> { + xml.writeAttribute("Win64", is64Bit() ? "yes" : "no"); + xml.writeAttribute("Guid", componentGuid); + } + case Wix4 -> { + xml.writeAttribute("Bitness", is64Bit() ? "always64" : "always32"); + if (!componentGuid.equals("*")) { + xml.writeAttribute("Guid", componentGuid); + } + } + default -> { + throw new IllegalArgumentException(); + } + } xml.writeAttribute("Id", componentId); - xml.writeAttribute("Guid", componentGuid); } private static final class Config { @@ -370,22 +394,31 @@ private String addComponent(XMLStreamWriter xml, Path path, directoryRefPath = path; } - xml.writeStartElement("DirectoryRef"); - xml.writeAttribute("Id", Id.Folder.of(directoryRefPath)); + startDirectoryElement(xml, "DirectoryRef", directoryRefPath); final String componentId = "c" + role.idOf(path); - Component.startElement(xml, componentId, String.format("{%s}", - role.guidOf(path))); + Component.startElement(getWixType(), xml, componentId, String.format( + "{%s}", role.guidOf(path))); if (role == Component.Shortcut) { - xml.writeStartElement("Condition"); String property = shortcutFolders.stream().filter(shortcutFolder -> { return path.startsWith(shortcutFolder.root); }).map(shortcutFolder -> { return shortcutFolder.property; }).findFirst().get(); - xml.writeCharacters(property); - xml.writeEndElement(); + switch (getWixType()) { + case Wix3 -> { + xml.writeStartElement("Condition"); + xml.writeCharacters(property); + xml.writeEndElement(); + } + case Wix4 -> { + xml.writeAttribute("Condition", property); + } + default -> { + throw new IllegalArgumentException(); + } + } } boolean isRegistryKeyPath = !systemWide || role.isRegistryKeyPath(); @@ -442,7 +475,7 @@ private void addFaComponentGroup(XMLStreamWriter xml) private void addShortcutComponentGroup(XMLStreamWriter xml) throws XMLStreamException, IOException { List<String> componentIds = new ArrayList<>(); - Set<ShortcutsFolder> defineShortcutFolders = new HashSet<>(); + Set<Path> defineShortcutFolders = new HashSet<>(); for (var launcher : launchers) { for (var folder : shortcutFolders) { Path launcherPath = addExeSuffixToPath(installedAppImage @@ -457,16 +490,27 @@ private void addShortcutComponentGroup(XMLStreamWriter xml) throws folder); if (componentId != null) { - defineShortcutFolders.add(folder); + Path folderPath = folder.getPath(this); + boolean defineFolder; + switch (getWixType()) { + case Wix3 -> + defineFolder = true; + case Wix4 -> + defineFolder = !SYSTEM_DIRS.contains(folderPath); + default -> + throw new IllegalArgumentException(); + } + if (defineFolder) { + defineShortcutFolders.add(folderPath); + } componentIds.add(componentId); } } } } - for (var folder : defineShortcutFolders) { - Path path = folder.getPath(this); - componentIds.addAll(addRootBranch(xml, path)); + for (var folderPath : defineShortcutFolders) { + componentIds.addAll(addRootBranch(xml, folderPath)); } addComponentGroup(xml, "Shortcuts", componentIds); @@ -546,13 +590,18 @@ private List<String> addRootBranch(XMLStreamWriter xml, Path path) throw throwInvalidPathException(path); } - Function<Path, String> createDirectoryName = dir -> null; - boolean sysDir = true; - int levels = 1; + int levels; var dirIt = path.iterator(); - xml.writeStartElement("DirectoryRef"); - xml.writeAttribute("Id", dirIt.next().toString()); + + if (getWixType() != WixToolsetType.Wix3 && TARGETDIR.equals(path.getName(0))) { + levels = 0; + dirIt.next(); + } else { + levels = 1; + xml.writeStartElement("DirectoryRef"); + xml.writeAttribute("Id", dirIt.next().toString()); + } path = path.getName(0); while (dirIt.hasNext()) { @@ -562,21 +611,11 @@ private List<String> addRootBranch(XMLStreamWriter xml, Path path) if (sysDir && !SYSTEM_DIRS.contains(path)) { sysDir = false; - createDirectoryName = dir -> dir.getFileName().toString(); } - final String directoryId; - if (!sysDir && path.equals(installDir)) { - directoryId = INSTALLDIR.toString(); - } else { - directoryId = Id.Folder.of(path); - } - xml.writeStartElement("Directory"); - xml.writeAttribute("Id", directoryId); - - String directoryName = createDirectoryName.apply(path); - if (directoryName != null) { - xml.writeAttribute("Name", directoryName); + startDirectoryElement(xml, "Directory", path); + if (!sysDir) { + xml.writeAttribute("Name", path.getFileName().toString()); } } @@ -584,9 +623,37 @@ private List<String> addRootBranch(XMLStreamWriter xml, Path path) xml.writeEndElement(); } - List<String> componentIds = new ArrayList<>(); + return List.of(); + } - return componentIds; + private void startDirectoryElement(XMLStreamWriter xml, String wix3ElementName, Path path) throws XMLStreamException { + final String elementName; + switch (getWixType()) { + case Wix3 -> { + elementName = wix3ElementName; + } + case Wix4 -> { + if (SYSTEM_DIRS.contains(path)) { + elementName = "StandardDirectory"; + } else { + elementName = wix3ElementName; + } + } + default -> { + throw new IllegalArgumentException(); + } + + } + + final String directoryId; + if (path.equals(installDir)) { + directoryId = INSTALLDIR.toString(); + } else { + directoryId = Id.Folder.of(path); + } + + xml.writeStartElement(elementName); + xml.writeAttribute("Id", directoryId); } private String addRemoveDirectoryComponent(XMLStreamWriter xml, Path path) @@ -785,7 +852,7 @@ private void addRegistryKeyPath(XMLStreamWriter xml, Path path, xml.writeStartElement("RegistryKey"); xml.writeAttribute("Root", regRoot); xml.writeAttribute("Key", registryKeyPath); - if (DottedVersion.compareComponents(getWixVersion(), DottedVersion.lazy("3.6")) < 0) { + if (!isWithWix36Features()) { xml.writeAttribute("Action", "createAndRemoveOnUninstall"); } xml.writeStartElement("RegistryValue"); @@ -799,7 +866,7 @@ private void addRegistryKeyPath(XMLStreamWriter xml, Path path, private String addDirectoryCleaner(XMLStreamWriter xml, Path path) throws XMLStreamException, IOException { - if (DottedVersion.compareComponents(getWixVersion(), DottedVersion.lazy("3.6")) < 0) { + if (!isWithWix36Features()) { return null; } @@ -821,14 +888,13 @@ private String addDirectoryCleaner(XMLStreamWriter xml, Path path) throws xml.writeStartElement("DirectoryRef"); xml.writeAttribute("Id", INSTALLDIR.toString()); - Component.startElement(xml, componentId, "*"); + Component.startElement(getWixType(), xml, componentId, "*"); addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> { return toWixPath(path); }); - xml.writeStartElement( - "http://schemas.microsoft.com/wix/UtilExtension", + xml.writeStartElement(getWixNamespaces().get(WixNamespace.Util), "RemoveFolderEx"); xml.writeAttribute("On", "uninstall"); xml.writeAttribute("Property", propertyId); @@ -839,6 +905,10 @@ private String addDirectoryCleaner(XMLStreamWriter xml, Path path) throws return componentId; } + private boolean isWithWix36Features() { + return DottedVersion.compareComponents(getWixVersion(), DottedVersion.greedy("3.6")) >= 0; + } + // Does the following conversions: // INSTALLDIR -> [INSTALLDIR] // TARGETDIR/ProgramFiles64Folder/foo/bar -> [ProgramFiles64Folder]foo/bar diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java index bc98899c659..0276cc96e65 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java @@ -29,31 +29,35 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.nio.file.Path; -import java.text.MessageFormat; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.stream.XMLStreamWriter; import jdk.jpackage.internal.IOUtils.XmlConsumer; import jdk.jpackage.internal.OverridableResource.Source; -import static jdk.jpackage.internal.OverridableResource.createResource; import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT; import jdk.internal.util.Architecture; +import static jdk.jpackage.internal.OverridableResource.createResource; +import jdk.jpackage.internal.WixSourceConverter.ResourceGroup; +import jdk.jpackage.internal.WixToolset.WixToolsetType; /** * Creates WiX fragment. */ abstract class WixFragmentBuilder { - void setWixVersion(DottedVersion v) { - wixVersion = v; + final void setWixVersion(DottedVersion version, WixToolsetType type) { + Objects.requireNonNull(version); + Objects.requireNonNull(type); + wixVersion = version; + wixType = type; } - void setOutputFileName(String v) { + final void setOutputFileName(String v) { outputFileName = v; } @@ -65,11 +69,8 @@ void initFromParams(Map<String, ? super Object> params) { Source.ResourceDir); } - void logWixFeatures() { - if (DottedVersion.compareComponents(wixVersion, DottedVersion.lazy("3.6")) >= 0) { - Log.verbose(MessageFormat.format(I18N.getString( - "message.use-wix36-features"), wixVersion)); - } + List<String> getLoggableWixFeatures() { + return List.of(); } void configureWixPipeline(WixPipeline wixPipeline) { @@ -91,52 +92,84 @@ void addFilesToConfigRoot() throws IOException { } if (additionalResources != null) { - for (var resource : additionalResources) { - resource.resource.saveToFile(configRoot.resolve( - resource.saveAsName)); - } + additionalResources.saveResources(); } } - DottedVersion getWixVersion() { + final WixToolsetType getWixType() { + return wixType; + } + + final DottedVersion getWixVersion() { return wixVersion; } + protected static enum WixNamespace { + Default, + Util; + } + + final protected Map<WixNamespace, String> getWixNamespaces() { + switch (wixType) { + case Wix3 -> { + return Map.of(WixNamespace.Default, + "http://schemas.microsoft.com/wix/2006/wi", + WixNamespace.Util, + "http://schemas.microsoft.com/wix/UtilExtension"); + } + case Wix4 -> { + return Map.of(WixNamespace.Default, + "http://wixtoolset.org/schemas/v4/wxs", + WixNamespace.Util, + "http://wixtoolset.org/schemas/v4/wxs/util"); + } + default -> { + throw new IllegalArgumentException(); + } + + } + } + static boolean is64Bit() { return Architecture.is64bit(); } - protected Path getConfigRoot() { + final protected Path getConfigRoot() { return configRoot; } protected abstract Collection<XmlConsumer> getFragmentWriters(); - protected void defineWixVariable(String variableName) { + final protected void defineWixVariable(String variableName) { setWixVariable(variableName, "yes"); } - protected void setWixVariable(String variableName, String variableValue) { + final protected void setWixVariable(String variableName, String variableValue) { if (wixVariables == null) { wixVariables = new WixVariables(); } wixVariables.setWixVariable(variableName, variableValue); } - protected void addResource(OverridableResource resource, String saveAsName) { + final protected void addResource(OverridableResource resource, String saveAsName) { if (additionalResources == null) { - additionalResources = new ArrayList<>(); + additionalResources = new ResourceGroup(getWixType()); } - additionalResources.add(new ResourceWithName(resource, saveAsName)); + additionalResources.addResource(resource, configRoot.resolve(saveAsName)); } - static void createWixSource(Path file, XmlConsumer xmlConsumer) - throws IOException { + private void createWixSource(Path file, XmlConsumer xmlConsumer) throws IOException { IOUtils.createXml(file, xml -> { xml.writeStartElement("Wix"); - xml.writeDefaultNamespace("http://schemas.microsoft.com/wix/2006/wi"); - xml.writeNamespace("util", - "http://schemas.microsoft.com/wix/UtilExtension"); + for (var ns : getWixNamespaces().entrySet()) { + switch (ns.getKey()) { + case Default -> + xml.writeDefaultNamespace(ns.getValue()); + default -> + xml.writeNamespace(ns.getKey().name().toLowerCase(), ns. + getValue()); + } + } xmlConsumer.accept((XMLStreamWriter) Proxy.newProxyInstance( XMLStreamWriter.class.getClassLoader(), new Class<?>[]{ @@ -146,16 +179,6 @@ static void createWixSource(Path file, XmlConsumer xmlConsumer) }); } - private static class ResourceWithName { - - ResourceWithName(OverridableResource resource, String saveAsName) { - this.resource = resource; - this.saveAsName = saveAsName; - } - private final OverridableResource resource; - private final String saveAsName; - } - private static class WixPreprocessorEscaper implements InvocationHandler { WixPreprocessorEscaper(XMLStreamWriter target) { @@ -208,9 +231,10 @@ private String escape(CharSequence str) { private final XMLStreamWriter target; } + private WixToolsetType wixType; private DottedVersion wixVersion; private WixVariables wixVariables; - private List<ResourceWithName> additionalResources; + private ResourceGroup additionalResources; private OverridableResource fragmentResource; private String outputFileName; private Path configRoot; diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java index 58a07b6cbaf..835247ed1de 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,18 +22,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.jpackage.internal; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.UnaryOperator; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -45,7 +46,7 @@ public class WixPipeline { lightOptions = new ArrayList<>(); } - WixPipeline setToolset(Map<WixTool, Path> v) { + WixPipeline setToolset(WixToolset v) { toolset = v; return this; } @@ -79,13 +80,92 @@ WixPipeline addLightOptions(String ... v) { } void buildMsi(Path msi) throws IOException { + Objects.requireNonNull(workDir); + + switch (toolset.getType()) { + case Wix3 -> buildMsiWix3(msi); + case Wix4 -> buildMsiWix4(msi); + default -> throw new IllegalArgumentException(); + } + } + + private void addWixVariblesToCommandLine( + Map<String, String> otherWixVariables, List<String> cmdline) { + Stream.of(wixVariables, Optional.ofNullable(otherWixVariables). + orElseGet(Collections::emptyMap)).filter(Objects::nonNull). + reduce((a, b) -> { + a.putAll(b); + return a; + }).ifPresent(wixVars -> { + var entryStream = wixVars.entrySet().stream(); + + Stream<String> stream; + switch (toolset.getType()) { + case Wix3 -> { + stream = entryStream.map(wixVar -> { + return String.format("-d%s=%s", wixVar.getKey(), wixVar. + getValue()); + }); + } + case Wix4 -> { + stream = entryStream.map(wixVar -> { + return Stream.of("-d", String.format("%s=%s", wixVar. + getKey(), wixVar.getValue())); + }).flatMap(Function.identity()); + } + default -> { + throw new IllegalArgumentException(); + } + } + + stream.reduce(cmdline, (ctnr, wixVar) -> { + ctnr.add(wixVar); + return ctnr; + }, (x, y) -> { + x.addAll(y); + return x; + }); + }); + } + + private void buildMsiWix4(Path msi) throws IOException { + var mergedSrcWixVars = sources.stream().map(wixSource -> { + return Optional.ofNullable(wixSource.variables).orElseGet( + Collections::emptyMap).entrySet().stream(); + }).flatMap(Function.identity()).collect(Collectors.toMap( + Map.Entry::getKey, Map.Entry::getValue)); + + List<String> cmdline = new ArrayList<>(List.of( + toolset.getToolPath(WixTool.Wix4).toString(), + "build", + "-nologo", + "-pdbtype", "none", + "-intermediatefolder", wixObjDir.toAbsolutePath().toString(), + "-ext", "WixToolset.Util.wixext", + "-arch", WixFragmentBuilder.is64Bit() ? "x64" : "x86" + )); + + cmdline.addAll(lightOptions); + + addWixVariblesToCommandLine(mergedSrcWixVars, cmdline); + + cmdline.addAll(sources.stream().map(wixSource -> { + return wixSource.source.toAbsolutePath().toString(); + }).toList()); + + cmdline.addAll(List.of("-out", msi.toString())); + + execute(cmdline); + } + + private void buildMsiWix3(Path msi) throws IOException { List<Path> wixObjs = new ArrayList<>(); for (var source : sources) { - wixObjs.add(compile(source)); + wixObjs.add(compileWix3(source)); } List<String> lightCmdline = new ArrayList<>(List.of( - toolset.get(WixTool.Light).toString(), + toolset.getToolPath(WixTool.Light3).toString(), "-nologo", "-spdb", "-ext", "WixUtilExtension", @@ -99,31 +179,20 @@ void buildMsi(Path msi) throws IOException { execute(lightCmdline); } - private Path compile(WixSource wixSource) throws IOException { - UnaryOperator<Path> adjustPath = path -> { - return workDir != null ? path.toAbsolutePath() : path; - }; - - Path wixObj = adjustPath.apply(wixObjDir).resolve(IOUtils.replaceSuffix( + private Path compileWix3(WixSource wixSource) throws IOException { + Path wixObj = wixObjDir.toAbsolutePath().resolve(IOUtils.replaceSuffix( IOUtils.getFileName(wixSource.source), ".wixobj")); List<String> cmdline = new ArrayList<>(List.of( - toolset.get(WixTool.Candle).toString(), + toolset.getToolPath(WixTool.Candle3).toString(), "-nologo", - adjustPath.apply(wixSource.source).toString(), + wixSource.source.toAbsolutePath().toString(), "-ext", "WixUtilExtension", "-arch", WixFragmentBuilder.is64Bit() ? "x64" : "x86", "-out", wixObj.toAbsolutePath().toString() )); - Map<String, String> appliedVaribales = new HashMap<>(); - Stream.of(wixVariables, wixSource.variables) - .filter(Objects::nonNull) - .forEachOrdered(appliedVaribales::putAll); - - appliedVaribales.entrySet().stream().map(wixVar -> String.format("-d%s=%s", - wixVar.getKey(), wixVar.getValue())).forEachOrdered( - cmdline::add); + addWixVariblesToCommandLine(wixSource.variables, cmdline); execute(cmdline); @@ -131,8 +200,8 @@ private Path compile(WixSource wixSource) throws IOException { } private void execute(List<String> cmdline) throws IOException { - Executor.of(new ProcessBuilder(cmdline).directory( - workDir != null ? workDir.toFile() : null)).executeExpectSuccess(); + Executor.of(new ProcessBuilder(cmdline).directory(workDir.toFile())). + executeExpectSuccess(); } private static final class WixSource { @@ -140,7 +209,7 @@ private static final class WixSource { Map<String, String> variables; } - private Map<WixTool, Path> toolset; + private WixToolset toolset; private Map<String, String> wixVariables; private List<String> lightOptions; private Path wixObjDir; diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java new file mode 100644 index 00000000000..7786d64a786 --- /dev/null +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.internal; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import javax.xml.XMLConstants; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stax.StAXResult; +import javax.xml.transform.stream.StreamSource; +import jdk.jpackage.internal.WixToolset.WixToolsetType; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * Converts WiX v3 source file into WiX v4 format. + */ +final class WixSourceConverter { + + enum Status { + SavedAsIs, + SavedAsIsMalfromedXml, + Transformed, + } + + WixSourceConverter(Path resourceDir) throws IOException { + var buf = new ByteArrayOutputStream(); + + new OverridableResource("wix3-to-wix4-conv.xsl") + .setPublicName("wix-conv.xsl") + .setResourceDir(resourceDir) + .setCategory(I18N.getString("resource.wix-src-conv")) + .saveToStream(buf); + + var xslt = new StreamSource(new ByteArrayInputStream(buf.toByteArray())); + + var tf = TransformerFactory.newInstance(); + try { + this.transformer = tf.newTransformer(xslt); + } catch (TransformerException ex) { + // Should never happen + throw new RuntimeException(ex); + } + + this.outputFactory = XMLOutputFactory.newInstance(); + } + + Status appyTo(OverridableResource resource, Path resourceSaveAsFile) throws IOException { + // Save the resource into DOM tree and read xml namespaces from it. + // If some namespaces are not recognized by this converter, save the resource as is. + // If all detected namespaces are recognized, run transformation of the DOM tree and save + // output into destination file. + + var buf = saveResourceInMemory(resource); + + Document inputXmlDom; + try { + inputXmlDom = IOUtils.initDocumentBuilder().parse(new ByteArrayInputStream(buf)); + } catch (SAXException ex) { + // Malformed XML, don't run converter, save as is. + resource.saveToFile(resourceSaveAsFile); + return Status.SavedAsIsMalfromedXml; + } + + try { + var nc = new NamespaceCollector(); + TransformerFactory.newInstance().newTransformer(). + transform(new DOMSource(inputXmlDom), new StAXResult((XMLStreamWriter) Proxy. + newProxyInstance(XMLStreamWriter.class.getClassLoader(), + new Class<?>[]{XMLStreamWriter.class}, nc))); + if (!nc.isOnlyKnownNamespacesUsed()) { + // Unsupported namespaces detected in input XML, don't run converter, save as is. + resource.saveToFile(resourceSaveAsFile); + return Status.SavedAsIs; + } + } catch (TransformerException ex) { + // Should never happen + throw new RuntimeException(ex); + } + + Supplier<Source> inputXml = () -> { + // Should be "new DOMSource(inputXmlDom)", but no transfromation is applied in this case! + return new StreamSource(new ByteArrayInputStream(buf)); + }; + + var nc = new NamespaceCollector(); + try { + // Run transfomation to collect namespaces from the output XML. + transformer.transform(inputXml.get(), new StAXResult((XMLStreamWriter) Proxy. + newProxyInstance(XMLStreamWriter.class.getClassLoader(), + new Class<?>[]{XMLStreamWriter.class}, nc))); + } catch (TransformerException ex) { + // Should never happen + throw new RuntimeException(ex); + } + + try (var outXml = new ByteArrayOutputStream()) { + transformer.transform(inputXml.get(), new StAXResult((XMLStreamWriter) Proxy. + newProxyInstance(XMLStreamWriter.class.getClassLoader(), + new Class<?>[]{XMLStreamWriter.class}, new NamespaceCleaner(nc. + getPrefixToUri(), outputFactory.createXMLStreamWriter(outXml))))); + Files.createDirectories(IOUtils.getParent(resourceSaveAsFile)); + Files.copy(new ByteArrayInputStream(outXml.toByteArray()), resourceSaveAsFile, + StandardCopyOption.REPLACE_EXISTING); + } catch (TransformerException | XMLStreamException ex) { + // Should never happen + throw new RuntimeException(ex); + } + + return Status.Transformed; + } + + private static byte[] saveResourceInMemory(OverridableResource resource) throws IOException { + var buf = new ByteArrayOutputStream(); + resource.saveToStream(buf); + return buf.toByteArray(); + } + + final static class ResourceGroup { + + ResourceGroup(WixToolsetType wixToolsetType) { + this.wixToolsetType = wixToolsetType; + } + + void addResource(OverridableResource resource, Path resourceSaveAsFile) { + resources.put(resourceSaveAsFile, resource); + } + + void saveResources() throws IOException { + switch (wixToolsetType) { + case Wix3 -> { + for (var e : resources.entrySet()) { + e.getValue().saveToFile(e.getKey()); + } + } + case Wix4 -> { + var resourceDir = resources.values().stream().filter(res -> { + return null != res.getResourceDir(); + }).findAny().map(OverridableResource::getResourceDir).orElse(null); + var conv = new WixSourceConverter(resourceDir); + for (var e : resources.entrySet()) { + conv.appyTo(e.getValue(), e.getKey()); + } + } + default -> { + throw new IllegalArgumentException(); + } + } + } + + private final Map<Path, OverridableResource> resources = new HashMap<>(); + private final WixToolsetType wixToolsetType; + } + + // + // Default JDK XSLT v1.0 processor is not handling well default namespace mappings. + // Running generic template: + // + // <xsl:template match="wix3loc:*"> + // <xsl:element name="{local-name()}" namespace="http://wixtoolset.org/schemas/v4/wxl"> + // <xsl:apply-templates select="@*|node()"/> + // </xsl:element> + // </xsl:template> + // + // produces: + // + // <ns0:WixLocalization xmlns:ns0="http://wixtoolset.org/schemas/v4/wxl" Culture="en-us" Codepage="1252"> + // <ns1:String xmlns:ns1="http://wixtoolset.org/schemas/v4/wxl" Value="The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?" Id="message.install.dir.exist"/> + // <ns2:String xmlns:ns2="http://wixtoolset.org/schemas/v4/wxl" Value="Main Feature" Id="MainFeatureTitle"/> + // ... + // <ns12:String xmlns:ns12="http://wixtoolset.org/schemas/v4/wxl" Value="Open with [ProductName]" Id="ContextMenuCommandLabel"/> + // </ns0:WixLocalization> + // + // which is conformant XML but WiX4 doesn't like it: + // + // wix.exe : error WIX0202: The {http://wixtoolset.org/schemas/v4/wxl}String element contains an unsupported extension attribute '{http://www.w3.org/2000/xmlns/}ns1'. The {http://wixtoolset.org/schemas/v4/wxl}String element does not currently support extension attributes. Is the {http://www.w3.org/2000/xmlns/}ns1 attribute using the correct XML namespace? + // wix.exe : error WIX0202: The {http://wixtoolset.org/schemas/v4/wxl}String element contains an unsupported extension attribute '{http://www.w3.org/2000/xmlns/}ns2'. The {http://wixtoolset.org/schemas/v4/wxl}String element does not currently support extension attributes. Is the {http://www.w3.org/2000/xmlns/}ns2 attribute using the correct XML namespace? + // wix.exe : error WIX0202: The {http://wixtoolset.org/schemas/v4/wxl}String element contains an unsupported extension attribute '{http://www.w3.org/2000/xmlns/}ns3'. The {http://wixtoolset.org/schemas/v4/wxl}String element does not currently support extension attributes. Is the {http://www.w3.org/2000/xmlns/}ns3 attribute using the correct XML namespace? + // + // Someone hit this issue long ago - https://stackoverflow.com/questions/26904623/replace-default-namespace-using-xsl and they suggested to use different XSLT processor. + // Two online XSLT processors used in testing produce clean XML with this template indeed: + // + // <WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Codepage="1252" Culture="en-us"> + // <String Value="The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?" Id="message.install.dir.exist"/> + // <String Value="Main Feature" Id="MainFeatureTitle"/> + // ... + // <String Value="Open with [ProductName]" Id="ContextMenuCommandLabel"/> + // </WixLocalization> + // + // To workaround default JDK's XSLT processor limitations we do additionl postprocessing of output XML with NamespaceCleaner class. + // + private static class NamespaceCleaner implements InvocationHandler { + + NamespaceCleaner(Map<String, String> prefixToUri, XMLStreamWriter target) { + this.uriToPrefix = prefixToUri.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getValue, e -> { + return new Prefix(e.getKey()); + }, (x, y) -> x)); + this.prefixToUri = prefixToUri; + this.target = target; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + switch (method.getName()) { + case "writeNamespace" -> { + final String uri = (String) args[1]; + var prefixObj = uriToPrefix.get(uri); + if (!prefixObj.written) { + prefixObj.written = true; + target.writeNamespace(prefixObj.name, uri); + } + return null; + } + case "writeStartElement", "writeEmptyElement" -> { + final String name; + switch (args.length) { + case 1 -> + name = (String) args[0]; + case 2, 3 -> + name = (String) args[1]; + default -> + throw new IllegalArgumentException(); + } + + final String prefix; + final String localName; + final String[] tokens = name.split(":", 2); + if (tokens.length == 2) { + prefix = tokens[0]; + localName = tokens[1]; + } else { + localName = name; + switch (args.length) { + case 3 -> + prefix = (String) args[0]; + case 2 -> + prefix = uriToPrefix.get((String) args[0]).name; + default -> + prefix = null; + } + } + + if (prefix != null && !XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) { + final String uri = prefixToUri.get(prefix); + var prefixObj = uriToPrefix.get(uri); + if (prefixObj.written) { + var writeName = String.join(":", prefixObj.name, localName); + if ("writeStartElement".equals(method.getName())) { + target.writeStartElement(writeName); + } else { + target.writeEmptyElement(writeName); + } + return null; + } else { + prefixObj.written = (args.length > 1); + args = Arrays.copyOf(args, args.length, Object[].class); + if (localName.equals(name)) { + // No prefix in the name + if (args.length == 3) { + args[0] = prefixObj.name; + } + } else { + var writeName = String.join(":", prefixObj.name, localName); + switch (args.length) { + case 1 -> + args[0] = writeName; + case 2 -> { + args[0] = uri; + args[1] = writeName; + } + case 3 -> { + args[0] = prefixObj.name; + args[1] = writeName; + args[2] = uri; + } + } + } + } + } + } + } + + return method.invoke(target, args); + } + + static class Prefix { + + Prefix(String name) { + this.name = name; + } + + private final String name; + private boolean written; + } + + private final Map<String, Prefix> uriToPrefix; + private final Map<String, String> prefixToUri; + private final XMLStreamWriter target; + } + + private static class NamespaceCollector implements InvocationHandler { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + switch (method.getName()) { + case "setPrefix", "writeNamespace" -> { + var prefix = (String) args[0]; + var namespace = prefixToUri.computeIfAbsent(prefix, k -> createValue(args[1])); + if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) { + namespace.setValue(true); + } + } + case "writeStartElement", "writeEmptyElement" -> { + switch (args.length) { + case 3 -> + prefixToUri.computeIfAbsent((String) args[0], k -> createValue( + (String) args[2])).setValue(true); + case 2 -> + initFromElementName((String) args[1], (String) args[0]); + case 1 -> + initFromElementName((String) args[0], null); + } + } + } + return null; + } + + boolean isOnlyKnownNamespacesUsed() { + return prefixToUri.values().stream().filter(namespace -> { + return namespace.getValue(); + }).allMatch(namespace -> { + if (!namespace.getValue()) { + return true; + } else { + return KNOWN_NAMESPACES.contains(namespace.getKey()); + } + }); + } + + Map<String, String> getPrefixToUri() { + return prefixToUri.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, + e -> { + return e.getValue().getKey(); + })); + } + + private void initFromElementName(String name, String namespace) { + final String[] tokens = name.split(":", 2); + if (tokens.length == 2) { + if (namespace != null) { + prefixToUri.computeIfAbsent(tokens[0], k -> createValue(namespace)).setValue( + true); + } else { + prefixToUri.computeIfPresent(tokens[0], (k, v) -> { + v.setValue(true); + return v; + }); + } + } + } + + private Map.Entry<String, Boolean> createValue(Object prefix) { + return new AbstractMap.SimpleEntry<String, Boolean>((String) prefix, false); + } + + private final Map<String, Map.Entry<String, Boolean>> prefixToUri = new HashMap<>(); + } + + private final Transformer transformer; + private final XMLOutputFactory outputFactory; + + // The list of WiX v3 namespaces this converter can handle + private final static Set<String> KNOWN_NAMESPACES = Set.of( + "http://schemas.microsoft.com/wix/2006/localization", + "http://schemas.microsoft.com/wix/2006/wi"); +} diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java index 68104444b3c..f16b28edf24 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.jpackage.internal; import java.io.IOException; @@ -32,105 +31,198 @@ import java.nio.file.Path; import java.nio.file.PathMatcher; import java.text.MessageFormat; -import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; -import java.util.function.Supplier; +import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.jpackage.internal.WixToolset.WixToolsetType; /** * WiX tool. */ public enum WixTool { - Candle, Light; + Candle3("candle", DottedVersion.lazy("3.0")), + Light3("light", DottedVersion.lazy("3.0")), + Wix4("wix", DottedVersion.lazy("4.0.4")); + + WixTool(String commandName, DottedVersion minimalVersion) { + this.toolFileName = IOUtils.addSuffix(Path.of(commandName), ".exe"); + this.minimalVersion = minimalVersion; + } static final class ToolInfo { + ToolInfo(Path path, String version) { this.path = path; - this.version = new DottedVersion(version); + this.version = DottedVersion.lazy(version); } final Path path; final DottedVersion version; } - static Map<WixTool, ToolInfo> toolset() throws ConfigException { - Map<WixTool, ToolInfo> toolset = new HashMap<>(); - for (var tool : values()) { - toolset.put(tool, tool.find()); - } - return toolset; - } + static WixToolset createToolset() throws ConfigException { + Function<List<ToolLookupResult>, Map<WixTool, ToolInfo>> conv = lookupResults -> { + return lookupResults.stream().filter(ToolLookupResult::isValid).collect(Collectors. + groupingBy(lookupResult -> { + return lookupResult.getInfo().version.toString(); + })).values().stream().filter(sameVersionLookupResults -> { + Set<WixTool> sameVersionTools = sameVersionLookupResults.stream().map( + ToolLookupResult::getTool).collect(Collectors.toSet()); + if (sameVersionTools.equals(Set.of(Candle3)) || sameVersionTools.equals(Set.of( + Light3))) { + // There is only one tool from WiX v3 toolset of some version available. Discard it. + return false; + } else { + return true; + } + }).flatMap(List::stream).collect(Collectors.toMap(ToolLookupResult::getTool, + ToolLookupResult::getInfo, (ToolInfo x, ToolInfo y) -> { + return Stream.of(x, y).sorted(Comparator.comparing((ToolInfo toolInfo) -> { + return toolInfo.version.toComponentsString(); + }).reversed()).findFirst().get(); + })); + }; - ToolInfo find() throws ConfigException { - final Path toolFileName = IOUtils.addSuffix( - Path.of(name().toLowerCase()), ".exe"); + Function<List<ToolLookupResult>, Optional<WixToolset>> createToolset = lookupResults -> { + var tools = conv.apply(lookupResults); + // Try to build a toolset found in the PATH and in known locations. + return Stream.of(WixToolsetType.values()).map(toolsetType -> { + return WixToolset.create(toolsetType.getTools(), tools); + }).filter(Objects::nonNull).findFirst(); + }; - String[] version = new String[1]; - ConfigException reason = createToolValidator(toolFileName, version).get(); - if (version[0] != null) { - if (reason == null) { - // Found in PATH. - return new ToolInfo(toolFileName, version[0]); - } + var toolsInPath = Stream.of(values()).map(tool -> { + return new ToolLookupResult(tool, null); + }).toList(); - // Found in PATH, but something went wrong. - throw reason; + // Try to build a toolset from tools in the PATH first. + var toolset = createToolset.apply(toolsInPath); + if (toolset.isPresent()) { + return toolset.get(); } - for (var dir : findWixInstallDirs()) { - Path path = dir.resolve(toolFileName); - if (Files.exists(path)) { - reason = createToolValidator(path, version).get(); - if (reason != null) { - throw reason; + // Look up for WiX tools in known locations. + var toolsInKnownWiXDirs = findWixInstallDirs().stream().map(dir -> { + return Stream.of(values()).map(tool -> { + return new ToolLookupResult(tool, dir); + }); + }).flatMap(Function.identity()).toList(); + + // Build a toolset found in the PATH and in known locations. + var allFoundTools = Stream.of(toolsInPath, toolsInKnownWiXDirs).flatMap(List::stream).filter( + ToolLookupResult::isValid).toList(); + toolset = createToolset.apply(allFoundTools); + if (toolset.isPresent()) { + return toolset.get(); + } else if (allFoundTools.isEmpty()) { + throw new ConfigException(I18N.getString("error.no-wix-tools"), I18N.getString( + "error.no-wix-tools.advice")); + } else { + var toolOldVerErr = allFoundTools.stream().map(lookupResult -> { + if (lookupResult.versionTooOld) { + return new ConfigException(MessageFormat.format(I18N.getString( + "message.wrong-tool-version"), lookupResult.getInfo().path, + lookupResult.getInfo().version, lookupResult.getTool().minimalVersion), + I18N.getString("error.no-wix-tools.advice")); + } else { + return null; } - return new ToolInfo(path, version[0]); + }).filter(Objects::nonNull).findAny(); + if (toolOldVerErr.isPresent()) { + throw toolOldVerErr.get(); + } else { + throw new ConfigException(I18N.getString("error.no-wix-tools"), I18N.getString( + "error.no-wix-tools.advice")); } } - - throw reason; } - private static Supplier<ConfigException> createToolValidator(Path toolPath, - String[] versionCtnr) { - return new ToolValidator(toolPath) - .setCommandLine("/?") - .setMinimalVersion(MINIMAL_VERSION) - .setToolNotFoundErrorHandler( - (name, ex) -> new ConfigException( - I18N.getString("error.no-wix-tools"), - I18N.getString("error.no-wix-tools.advice"))) - .setToolOldVersionErrorHandler( - (name, version) -> new ConfigException( - MessageFormat.format(I18N.getString( - "message.wrong-tool-version"), name, - version, MINIMAL_VERSION), - I18N.getString("error.no-wix-tools.advice"))) - .setVersionParser(output -> { - versionCtnr[0] = ""; + private static class ToolLookupResult { + + ToolLookupResult(WixTool tool, Path lookupDir) { + + final Path toolPath = Optional.ofNullable(lookupDir).map(p -> p.resolve( + tool.toolFileName)).orElse(tool.toolFileName); + + final boolean[] tooOld = new boolean[1]; + final String[] parsedVersion = new String[1]; + + final var validator = new ToolValidator(toolPath).setMinimalVersion(tool.minimalVersion). + setToolNotFoundErrorHandler((name, ex) -> { + return new ConfigException("", ""); + }).setToolOldVersionErrorHandler((name, version) -> { + tooOld[0] = true; + return null; + }); + + final Function<Stream<String>, String> versionParser; + + if (Set.of(Candle3, Light3).contains(tool)) { + validator.setCommandLine("/?"); + versionParser = output -> { String firstLineOfOutput = output.findFirst().orElse(""); int separatorIdx = firstLineOfOutput.lastIndexOf(' '); if (separatorIdx == -1) { return null; } - versionCtnr[0] = firstLineOfOutput.substring(separatorIdx + 1); - return versionCtnr[0]; - })::validate; - } + return firstLineOfOutput.substring(separatorIdx + 1); + }; + } else { + validator.setCommandLine("--version"); + versionParser = output -> { + return output.findFirst().orElse(""); + }; + } - private static final DottedVersion MINIMAL_VERSION = DottedVersion.lazy("3.0"); + validator.setVersionParser(output -> { + parsedVersion[0] = versionParser.apply(output); + return parsedVersion[0]; + }); - static Path getSystemDir(String envVar, String knownDir) { + this.tool = tool; + if (validator.validate() == null) { + // Tool found + this.versionTooOld = tooOld[0]; + this.info = new ToolInfo(toolPath, parsedVersion[0]); + } else { + this.versionTooOld = false; + this.info = null; + } + } + + WixTool getTool() { + return tool; + } + + ToolInfo getInfo() { + return info; + } + + boolean isValid() { + return info != null && !versionTooOld; + } + + boolean isVersionTooOld() { + return versionTooOld; + } + + private final WixTool tool; + private final ToolInfo info; + private final boolean versionTooOld; + } + + private static Path getSystemDir(String envVar, String knownDir) { return Optional .ofNullable(getEnvVariableAsPath(envVar)) .orElseGet(() -> Optional - .ofNullable(getEnvVariableAsPath("SystemDrive")) - .orElseGet(() -> Path.of("C:")).resolve(knownDir)); + .ofNullable(getEnvVariableAsPath("SystemDrive")) + .orElseGet(() -> Path.of("C:")).resolve(knownDir)); } private static Path getEnvVariableAsPath(String envVar) { @@ -147,8 +239,22 @@ private static Path getEnvVariableAsPath(String envVar) { } private static List<Path> findWixInstallDirs() { - PathMatcher wixInstallDirMatcher = FileSystems.getDefault().getPathMatcher( - "glob:WiX Toolset v*"); + return Stream.of(findWixCurrentInstallDirs(), findWix3InstallDirs()). + flatMap(List::stream).toList(); + } + + private static List<Path> findWixCurrentInstallDirs() { + return Stream.of(getEnvVariableAsPath("USERPROFILE"), Optional.ofNullable(System. + getProperty("user.home")).map(Path::of).orElse(null)).filter(Objects::nonNull).map( + path -> { + return path.resolve(".dotnet/tools"); + }).filter(Files::isDirectory).distinct().toList(); + } + + private static List<Path> findWix3InstallDirs() { + PathMatcher wixInstallDirMatcher = FileSystems.getDefault(). + getPathMatcher( + "glob:WiX Toolset v*"); Path programFiles = getSystemDir("ProgramFiles", "\\Program Files"); Path programFilesX86 = getSystemDir("ProgramFiles(x86)", @@ -157,18 +263,20 @@ private static List<Path> findWixInstallDirs() { // Returns list of WiX install directories ordered by WiX version number. // Newer versions go first. return Stream.of(programFiles, programFilesX86).map(path -> { - List<Path> result; try (var paths = Files.walk(path, 1)) { - result = paths.toList(); + return paths.toList(); } catch (IOException ex) { Log.verbose(ex); - result = Collections.emptyList(); + List<Path> empty = List.of(); + return empty; } - return result; }).flatMap(List::stream) - .filter(path -> wixInstallDirMatcher.matches(path.getFileName())) - .sorted(Comparator.comparing(Path::getFileName).reversed()) - .map(path -> path.resolve("bin")) - .toList(); + .filter(path -> wixInstallDirMatcher.matches(path.getFileName())). + sorted(Comparator.comparing(Path::getFileName).reversed()) + .map(path -> path.resolve("bin")) + .toList(); } + + private final Path toolFileName; + private final DottedVersion minimalVersion; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java new file mode 100644 index 00000000000..ab433616f44 --- /dev/null +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixToolset.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.internal; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +final class WixToolset { + + static enum WixToolsetType { + // Wix v4+ + Wix4(WixTool.Wix4), + // Wix v3+ + Wix3(WixTool.Candle3, WixTool.Light3); + + WixToolsetType(WixTool... tools) { + this.tools = Set.of(tools); + } + + Set<WixTool> getTools() { + return tools; + } + + private final Set<WixTool> tools; + } + + private WixToolset(Map<WixTool, WixTool.ToolInfo> tools) { + this.tools = tools; + } + + WixToolsetType getType() { + return Stream.of(WixToolsetType.values()).filter(toolsetType -> { + return toolsetType.getTools().equals(tools.keySet()); + }).findAny().get(); + } + + Path getToolPath(WixTool tool) { + return tools.get(tool).path; + } + + DottedVersion getVersion() { + return tools.values().iterator().next().version; + } + + static WixToolset create(Set<WixTool> requiredTools, Map<WixTool, WixTool.ToolInfo> allTools) { + var filteredTools = allTools.entrySet().stream().filter(e -> { + return requiredTools.contains(e.getKey()); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + if (filteredTools.keySet().equals(requiredTools)) { + return new WixToolset(filteredTools); + } else { + return null; + } + } + + private final Map<WixTool, WixTool.ToolInfo> tools; +} diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java index 8d20d6432bf..4f39a65e3b6 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixUiFragmentBuilder.java @@ -43,6 +43,7 @@ import static jdk.jpackage.internal.OverridableResource.createResource; import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE; import jdk.jpackage.internal.WixAppImageFragmentBuilder.ShortcutsFolder; +import jdk.jpackage.internal.WixToolset.WixToolsetType; /** * Creates UI WiX fragment. @@ -100,7 +101,13 @@ void configureWixPipeline(WixPipeline wixPipeline) { super.configureWixPipeline(wixPipeline); if (withShortcutPromptDlg || withInstallDirChooserDlg || withLicenseDlg) { - wixPipeline.addLightOptions("-ext", "WixUIExtension"); + final String extName; + switch (getWixType()) { + case Wix3 -> extName = "WixUIExtension"; + case Wix4 -> extName = "WixToolset.UI.wixext"; + default -> throw new IllegalArgumentException(); + } + wixPipeline.addLightOptions("-ext", extName); } // Only needed if we using CA dll, so Wix can find it @@ -148,15 +155,14 @@ private void addUI(XMLStreamWriter xml) throws XMLStreamException, xml.writeEndElement(); // WixVariable } - xml.writeStartElement("UI"); - xml.writeAttribute("Id", "JpUI"); - var ui = getUI(); if (ui != null) { - ui.write(this, xml); + ui.write(getWixType(), this, xml); + } else { + xml.writeStartElement("UI"); + xml.writeAttribute("Id", "JpUI"); + xml.writeEndElement(); } - - xml.writeEndElement(); // UI } private UI getUI() { @@ -187,12 +193,43 @@ private enum UI { this.dialogPairsSupplier = dialogPairsSupplier; } - void write(WixUiFragmentBuilder outer, XMLStreamWriter xml) throws - XMLStreamException, IOException { - xml.writeStartElement("UIRef"); - xml.writeAttribute("Id", wixUIRef); - xml.writeEndElement(); // UIRef + void write(WixToolsetType wixType, WixUiFragmentBuilder outer, XMLStreamWriter xml) throws XMLStreamException, IOException { + switch (wixType) { + case Wix3 -> {} + case Wix4 -> { + // https://wixtoolset.org/docs/fourthree/faqs/#converting-custom-wixui-dialog-sets + xml.writeProcessingInstruction("foreach WIXUIARCH in X86;X64;A64"); + writeWix4UIRef(xml, wixUIRef, "JpUIInternal_$(WIXUIARCH)"); + xml.writeProcessingInstruction("endforeach"); + writeWix4UIRef(xml, "JpUIInternal", "JpUI"); + } + default -> { + throw new IllegalArgumentException(); + } + } + + xml.writeStartElement("UI"); + switch (wixType) { + case Wix3 -> { + xml.writeAttribute("Id", "JpUI"); + xml.writeStartElement("UIRef"); + xml.writeAttribute("Id", wixUIRef); + xml.writeEndElement(); // UIRef + } + case Wix4 -> { + xml.writeAttribute("Id", "JpUIInternal"); + } + default -> { + throw new IllegalArgumentException(); + } + } + writeContents(wixType, outer, xml); + xml.writeEndElement(); // UI + } + + private void writeContents(WixToolsetType wixType, WixUiFragmentBuilder outer, + XMLStreamWriter xml) throws XMLStreamException, IOException { if (dialogIdsSupplier != null) { List<Dialog> dialogIds = dialogIdsSupplier.apply(outer); Map<DialogPair, List<Publish>> dialogPairs = dialogPairsSupplier.get(); @@ -210,7 +247,7 @@ void write(WixUiFragmentBuilder outer, XMLStreamWriter xml) throws DialogPair pair = new DialogPair(firstId, secondId); for (var curPair : List.of(pair, pair.flip())) { for (var publish : dialogPairs.get(curPair)) { - writePublishDialogPair(xml, publish, curPair); + writePublishDialogPair(wixType, xml, publish, curPair); } } firstId = secondId; @@ -218,6 +255,17 @@ void write(WixUiFragmentBuilder outer, XMLStreamWriter xml) throws } } + private static void writeWix4UIRef(XMLStreamWriter xml, String uiRef, String id) throws XMLStreamException, IOException { + // https://wixtoolset.org/docs/fourthree/faqs/#referencing-the-standard-wixui-dialog-sets + xml.writeStartElement("UI"); + xml.writeAttribute("Id", id); + xml.writeStartElement("ui:WixUI"); + xml.writeAttribute("Id", uiRef); + xml.writeNamespace("ui", "http://wixtoolset.org/schemas/v4/wxs/ui"); + xml.writeEndElement(); // UIRef + xml.writeEndElement(); // UI + } + private final String wixUIRef; private final Function<WixUiFragmentBuilder, List<Dialog>> dialogIdsSupplier; private final Supplier<Map<DialogPair, List<Publish>>> dialogPairsSupplier; @@ -441,9 +489,8 @@ private static PublishBuilder buildPublish(Publish publish) { return new PublishBuilder(publish); } - private static void writePublishDialogPair(XMLStreamWriter xml, - Publish publish, DialogPair dialogPair) throws IOException, - XMLStreamException { + private static void writePublishDialogPair(WixToolsetType wixType, XMLStreamWriter xml, + Publish publish, DialogPair dialogPair) throws IOException, XMLStreamException { xml.writeStartElement("Publish"); xml.writeAttribute("Dialog", dialogPair.firstId); xml.writeAttribute("Control", publish.control); @@ -452,7 +499,11 @@ private static void writePublishDialogPair(XMLStreamWriter xml, if (publish.order != 0) { xml.writeAttribute("Order", String.valueOf(publish.order)); } - xml.writeCharacters(publish.condition); + switch (wixType) { + case Wix3 -> xml.writeCharacters(publish.condition); + case Wix4 -> xml.writeAttribute("Condition", publish.condition); + default -> throw new IllegalArgumentException(); + } xml.writeEndElement(); } @@ -463,9 +514,8 @@ private final class CustomDialog { this.wxsFileName = wxsFileName; this.wixVariables = new WixVariables(); - addResource( - createResource(wxsFileName, params).setCategory(category), - wxsFileName); + addResource(createResource(wxsFileName, params).setCategory(category).setPublicName( + wxsFileName), wxsFileName); } void addToWixPipeline(WixPipeline wixPipeline) { diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/InstallDirNotEmptyDlg.wxs b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/InstallDirNotEmptyDlg.wxs index 936984b1fff..755b2a0aab9 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/InstallDirNotEmptyDlg.wxs +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/InstallDirNotEmptyDlg.wxs @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,9 +41,7 @@ <Control Id="No" Type="PushButton" X="150" Y="55" Width="50" Height="15" Default="yes" Cancel="yes" Text="!(loc.WixUINo)"> <Publish Event="NewDialog" Value="InstallDirDlg">1</Publish> </Control> - <Control Id="Text" Type="Text" X="25" Y="15" Width="250" Height="30" TabSkip="no"> - <Text>!(loc.message.install.dir.exist)</Text> - </Control> + <Control Id="Text" Type="Text" X="25" Y="15" Width="250" Height="30" TabSkip="no" Text="!(loc.InstallDirNotEmptyDlgInstallDirExistMessage)"/> </Dialog> <Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="JpCheckInstallDir" Order="3">1</Publish> diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl index 94c2696a6ca..31be69aa5d0 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl @@ -1,6 +1,5 @@ <?xml version = '1.0' encoding = 'utf-8'?> <WixLocalization Culture="de-de" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="1252"> - <String Id="message.install.dir.exist">Der Ordner [INSTALLDIR] ist bereits vorhanden. Möchten Sie diesen Ordner trotzdem installieren?</String> <String Id="MainFeatureTitle">Hauptfeature</String> <String Id="DowngradeErrorMessage">Eine höhere Version von [ProductName] ist bereits installiert. Downgrades sind deaktiviert. Setup wird jetzt beendet.</String> <String Id="DisallowUpgradeErrorMessage">Eine niedrigere Version von [ProductName] ist bereits installiert. Upgrades sind deaktiviert. Setup wird jetzt beendet.</String> @@ -11,6 +10,9 @@ <String Id="ShortcutPromptDlgDescription">Wählen Sie die zu erstellenden Verknüpfungen aus.</String> <String Id="ShortcutPromptDlgDesktopShortcutControlLabel">Desktopverknüpfung(en) erstellen</String> <String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">Startmenüverknüpfung(en) erstellen</String> + <String Id="InstallDirNotEmptyDlg_Title">[ProductName]-Setup</String> + <String Id="InstallDirNotEmptyDlgInstallDirExistMessage">Der Ordner [INSTALLDIR] ist bereits vorhanden. Möchten Sie diesen Ordner trotzdem installieren?</String> + <String Id="ContextMenuCommandLabel">Mit [ProductName] öffnen</String> </WixLocalization> diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_en.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_en.wxl index bc081fefe5b..070e46621fb 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_en.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_en.wxl @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="1252"> - <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String> <String Id="MainFeatureTitle">Main Feature</String> <String Id="DowngradeErrorMessage">A higher version of [ProductName] is already installed. Downgrades disabled. Setup will now exit.</String> <String Id="DisallowUpgradeErrorMessage">A lower version of [ProductName] is already installed. Upgrades disabled. Setup will now exit.</String> @@ -11,6 +10,9 @@ <String Id="ShortcutPromptDlgDescription">Select shortcuts to create.</String> <String Id="ShortcutPromptDlgDesktopShortcutControlLabel">Create desktop shortcut(s)</String> <String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">Create start menu shortcut(s)</String> + <String Id="InstallDirNotEmptyDlg_Title">[ProductName] Setup</String> + <String Id="InstallDirNotEmptyDlgInstallDirExistMessage">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String> + <String Id="ContextMenuCommandLabel">Open with [ProductName]</String> </WixLocalization> diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl index 20ee895ae19..32a57433829 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl @@ -1,6 +1,5 @@ <?xml version = '1.0' encoding = 'utf-8'?> <WixLocalization Culture="ja-jp" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="932"> - <String Id="message.install.dir.exist">フォルダ[INSTALLDIR]はすでに存在します。そのフォルダにインストールしますか?</String> <String Id="MainFeatureTitle">主な機能</String> <String Id="DowngradeErrorMessage">[ProductName]のより上位のバージョンがすでにインストールされています。ダウングレードは無効です。セットアップを終了します。</String> <String Id="DisallowUpgradeErrorMessage">[ProductName]のより下位のバージョンがすでにインストールされています。アップグレードは無効です。セットアップを終了します。</String> @@ -11,6 +10,9 @@ <String Id="ShortcutPromptDlgDescription">作成するショートカットを選択します。</String> <String Id="ShortcutPromptDlgDesktopShortcutControlLabel">デスクトップ・ショートカットの作成</String> <String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">スタート・メニューのショートカットの作成</String> + <String Id="InstallDirNotEmptyDlg_Title">[ProductName]セットアップ</String> + <String Id="InstallDirNotEmptyDlgInstallDirExistMessage">フォルダ[INSTALLDIR]はすでに存在します。そのフォルダにインストールしますか?</String> + <String Id="ContextMenuCommandLabel">[ProductName]で開く</String> </WixLocalization> diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl index 138aa856510..978f74a1546 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl @@ -1,6 +1,5 @@ <?xml version = '1.0' encoding = 'utf-8'?> <WixLocalization Culture="zh-cn" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="936"> - <String Id="message.install.dir.exist">文件夹 [INSTALLDIR] 已存在。是否仍要安装到该文件夹?</String> <String Id="MainFeatureTitle">主要功能</String> <String Id="DowngradeErrorMessage">已安装更高版本的 [ProductName]。降级已禁用。现在将退出安装。</String> <String Id="DisallowUpgradeErrorMessage">已安装更低版本的 [ProductName]。升级已禁用。现在将退出安装。</String> @@ -11,6 +10,9 @@ <String Id="ShortcutPromptDlgDescription">选择要创建的快捷方式。</String> <String Id="ShortcutPromptDlgDesktopShortcutControlLabel">创建桌面快捷方式</String> <String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">创建开始菜单快捷方式</String> + <String Id="InstallDirNotEmptyDlg_Title">[ProductName] 安装程序</String> + <String Id="InstallDirNotEmptyDlgInstallDirExistMessage">文件夹 [INSTALLDIR] 已存在。是否仍要安装到该文件夹?</String> + <String Id="ContextMenuCommandLabel">使用 [ProductName] 打开</String> </WixLocalization> diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties index cdbf04e7464..5843a750ade 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ resource.overrides-wix-file=Overrides WiX project file resource.shortcutpromptdlg-wix-file=Shortcut prompt dialog WiX project file resource.installdirnotemptydlg-wix-file=Not empty install directory dialog WiX project file resource.launcher-as-service-wix-file=Service installer WiX project file +resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format -error.no-wix-tools=Can not find WiX tools (light.exe, candle.exe) +error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found error.no-wix-tools.advice=Download WiX 3.0 or later from https://wixtoolset.org and add it to the PATH. error.version-string-wrong-format.advice=Set value of --app-version parameter to a valid Windows Installer ProductVersion. error.msi-product-version-components=Version string [{0}] must have between 2 and 4 components. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties index 6bdb9b06e09..dce4a911fe1 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ resource.overrides-wix-file=Überschreibt WiX-Projektdatei resource.shortcutpromptdlg-wix-file=Dialogfeld für Verknüpfungs-Prompt der WiX-Projektdatei resource.installdirnotemptydlg-wix-file=Nicht leeres Installationsverzeichnis in Dialogfeld für WiX-Projektdatei resource.launcher-as-service-wix-file=WiX-Projektdatei für Serviceinstallationsprogramm +resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format -error.no-wix-tools=WiX-Tools (light.exe, candle.exe) nicht gefunden +error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found error.no-wix-tools.advice=Laden Sie WiX 3.0 oder höher von https://wixtoolset.org herunter, und fügen Sie es zu PATH hinzu. error.version-string-wrong-format.advice=Setzen Sie den Wert des --app-version-Parameters auf eine gültige ProductVersion des Windows-Installationsprogramms. error.msi-product-version-components=Versionszeichenfolge [{0}] muss zwischen 2 und 4 Komponenten aufweisen. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties index 6a89e8cbf5a..e0bcd18c811 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ resource.overrides-wix-file=WiXプロジェクト・ファイルのオーバー resource.shortcutpromptdlg-wix-file=ショートカット・プロンプト・ダイアログWiXプロジェクト・ファイル resource.installdirnotemptydlg-wix-file=インストール・ディレクトリ・ダイアログのWiXプロジェクト・ファイルが空ではありません resource.launcher-as-service-wix-file=サービス・インストーラWiXプロジェクト・ファイル +resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format -error.no-wix-tools=WiXツール(light.exe、candle.exe)が見つかりません +error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found error.no-wix-tools.advice=WiX 3.0以降をhttps://wixtoolset.orgからダウンロードし、PATHに追加します。 error.version-string-wrong-format.advice=--app-versionパラメータの値を有効なWindows Installer ProductVersionに設定します。 error.msi-product-version-components=バージョン文字列[{0}]には、2から4つのコンポーネントが含まれている必要があります。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties index f786b00155d..e2b8bd37135 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ resource.overrides-wix-file=覆盖 WiX 项目文件 resource.shortcutpromptdlg-wix-file=快捷方式提示对话框 WiX 项目文件 resource.installdirnotemptydlg-wix-file=安装目录对话框 WiX 项目文件非空 resource.launcher-as-service-wix-file=服务安装程序 WiX 项目文件 +resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format -error.no-wix-tools=找不到 WiX 工具 (light.exe, candle.exe) +error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found error.no-wix-tools.advice=从 https://wixtoolset.org 下载 WiX 3.0 或更高版本,然后将其添加到 PATH。 error.version-string-wrong-format.advice=将 --app-version 参数的值设置为有效的 Windows Installer ProductVersion。 error.msi-product-version-components=版本字符串 [{0}] 必须包含 2 到 4 个组成部分。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/overrides.wxi b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/overrides.wxi index d8c8f16438f..c2faa850563 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/overrides.wxi +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/overrides.wxi @@ -28,4 +28,4 @@ to disable (the value doesn't matter). Should be defined to enable upgrades and undefined to disable upgrades. By default it is defined, use <?undef JpAllowUpgrades?> to disable. --> -<Include/> +<Include xmlns="http://schemas.microsoft.com/wix/2006/wi"/> diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/wix3-to-wix4-conv.xsl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/wix3-to-wix4-conv.xsl new file mode 100644 index 00000000000..382ed731b5a --- /dev/null +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/wix3-to-wix4-conv.xsl @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +--> + +<!-- + This stylesheet can be applied to Wix3 .wxl, .wxs, and .wsi source files. +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:wix3loc="http://schemas.microsoft.com/wix/2006/localization" + xmlns:wix3="http://schemas.microsoft.com/wix/2006/wi" +> + <!-- Wix4 complains about xml declaration in input files. Turn it off --> + <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> + + <!-- + Remap xmlns="http://schemas.microsoft.com/wix/2006/localization" + to xmlns="http://wixtoolset.org/schemas/v4/wxl" + --> + + <xsl:template match="wix3loc:*"> + <xsl:element name="{local-name()}" namespace="http://wixtoolset.org/schemas/v4/wxl"> + <xsl:apply-templates select="@*|node()"/> + </xsl:element> + </xsl:template> + + <!-- + Remap xmlns="http://schemas.microsoft.com/wix/2006/localization" + to xmlns="http://wixtoolset.org/schemas/v4/wxs" + --> + + <xsl:template match="wix3:*"> + <xsl:element name="{local-name()}" namespace="http://wixtoolset.org/schemas/v4/wxs"> + <xsl:apply-templates select="@*|node()"/> + </xsl:element> + </xsl:template> + + + <!-- + From <String Id="foo">Bar</String> to <String Id="foo" Value="Bar"/> + --> + <xsl:template match="wix3loc:WixLocalization/wix3loc:String"> + <xsl:element name="{local-name()}" namespace="http://wixtoolset.org/schemas/v4/wxl"> + <xsl:attribute name="Value"> + <xsl:value-of select="text()"/> + </xsl:attribute> + <xsl:apply-templates select="@*"/> + </xsl:element> + </xsl:template> + + + <!-- + Wix3 Product (https://wixtoolset.org/docs/v3/xsd/wix/product/): + Id + Codepage + Language + Manufacturer + Name + UpgradeCode + Version + + Wix3 Package (https://wixtoolset.org/docs/v3/xsd/wix/package/): + AdminImage + Comments + Compressed + Description + Id + InstallerVersion + InstallPrivileges + InstallScope + Keywords + Languages + Manufacturer + Platform + Platforms + ReadOnly + ShortNames + SummaryCodepage + + Wix4 Package (https://wixtoolset.org/docs/schema/wxs/package/): + Codepage <- Wix3:Product/@Codepage + Compressed <- Wix3:@Compressed + InstallerVersion <- Wix3:@InstallerVersion + Language <- Wix3:Product/@Language + Manufacturer <- Wix3:Product/@Manufacturer + Name <- Wix3:Product/@Name + ProductCode <- Wix3:Product/@Id + Scope <- Wix3:@InstallScope + ShortNames <- Wix3:@ShortNames + UpgradeCode <- Wix3:Product/@UpgradeCode + UpgradeStrategy <- + Version <- Wix3:Product/@Version + + Wix4 SummaryInformation (https://wixtoolset.org/docs/schema/wxs/summaryinformation/): + Codepage <- Wix3:Product/@Codepage + Comments <- Wix3:@Comments + Description <- Wix3:@Description + Keywords <- Wix3:@Keywords + Manufacturer <- Wix3:Product/@Manufacturer + --> + + <xsl:template match="wix3:Product"> + <xsl:element name="Package" namespace="http://wixtoolset.org/schemas/v4/wxs"> + <xsl:apply-templates select="@Codepage|wix3:Package/@Compressed|wix3:Package/@InstallerVersion|@Language|@Manufacturer|@Name|@Id|wix3:Package/@InstallScope|wix3:Package/@ShortNames|@UpgradeCode|@Version"/> + <xsl:if test="@Id"> + <xsl:attribute name="ProductCode"> + <xsl:value-of select="@Id"/> + </xsl:attribute> + </xsl:if> + <xsl:if test="wix3:Package/@InstallScope"> + <xsl:attribute name="Scope"> + <xsl:value-of select="wix3:Package/@InstallScope"/> + </xsl:attribute> + </xsl:if> + <xsl:element name="SummaryInformation" namespace="http://wixtoolset.org/schemas/v4/wxs"> + <xsl:apply-templates select="@Codepage|wix3:Package/@Comments|wix3:Package/@Description|wix3:Package/@Keywords|@Manufacturer"/> + </xsl:element> + <xsl:apply-templates select="node()"/> + </xsl:element> + </xsl:template> + + <xsl:template match="wix3:Package|wix3:Product/@Id|wix3:Package/@InstallScope"/> + + + <xsl:template match="wix3:CustomAction/@BinaryKey"> + <xsl:attribute name="BinaryRef"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:template> + + + <xsl:template match="wix3:Custom|wix3:Publish"> + <xsl:element name="{local-name()}" namespace="http://wixtoolset.org/schemas/v4/wxs"> + <xsl:apply-templates select="@*"/> + <xsl:if test="text()"> + <xsl:attribute name="Condition"> + <xsl:value-of select="text()"/> + </xsl:attribute> + </xsl:if> + <xsl:apply-templates select="node()"/> + </xsl:element> + </xsl:template> + + <xsl:template match="wix3:Custom/text()|wix3:Publish/text()"/> + + + <xsl:template match="wix3:Directory[@Id='TARGETDIR']"/> + + + <!-- + Identity transform + --> + <xsl:template match="@*|node()"> + <xsl:copy> + <xsl:apply-templates select="@*|node()"/> + </xsl:copy> + </xsl:template> + +</xsl:stylesheet> diff --git a/src/jdk.jshell/share/man/jshell.1 b/src/jdk.jshell/share/man/jshell.1 index 28160bb49fd..6f478e57442 100644 --- a/src/jdk.jshell/share/man/jshell.1 +++ b/src/jdk.jshell/share/man/jshell.1 @@ -36,7 +36,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JSHELL" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JSHELL" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jstatd/share/man/jstatd.1 b/src/jdk.jstatd/share/man/jstatd.1 index cbbaeaf49f2..4bd90104624 100644 --- a/src/jdk.jstatd/share/man/jstatd.1 +++ b/src/jdk.jstatd/share/man/jstatd.1 @@ -35,7 +35,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JSTATD" "1" "2024" "JDK 23-ea" "JDK Commands" +.TH "JSTATD" "1" "2025" "JDK 24-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/utils/LogCompilation/Makefile b/src/utils/LogCompilation/Makefile index 5f9ca083842..6ab946abc20 100644 --- a/src/utils/LogCompilation/Makefile +++ b/src/utils/LogCompilation/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -19,7 +19,7 @@ # 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. -# +# # PKGLIST = \ com.sun.hotspot.tools.compiler @@ -49,7 +49,7 @@ SRC_DIR = src BUILD_DIR = build OUTPUT_DIR = $(BUILD_DIR)/classes -# gnumake 3.78.1 does not accept the *s, +# gnumake 3.78.1 does not accept the *s, # so use the shell to expand them ALLFILES := $(patsubst %,$(SRC_DIR)/%,$(FILELIST)) ALLFILES := $(shell /bin/ls $(ALLFILES)) diff --git a/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp b/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp index 1d756854755..60999f2bf34 100644 --- a/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp +++ b/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,8 +28,10 @@ #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.hpp" #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" +#include "nativeInst_aarch64.hpp" #include "unittest.hpp" #define __ _masm. @@ -81,4 +83,376 @@ TEST_VM(AssemblerAArch64, validate) { BufferBlob::free(b); } +constexpr uint32_t test_encode_dmb_ld = 0xd50339bf; +constexpr uint32_t test_encode_dmb_st = 0xd5033abf; +constexpr uint32_t test_encode_dmb = 0xd5033bbf; +constexpr uint32_t test_encode_nop = 0xd503201f; + +static void asm_dump(address start, address end) { + ResourceMark rm; + stringStream ss; + ss.print_cr("Insns:"); + Disassembler::decode(start, end, &ss); + printf("%s\n", ss.as_string()); +} + +void test_merge_dmb() { + BufferBlob* b = BufferBlob::create("aarch64Test", 400); + CodeBuffer code(b); + MacroAssembler _masm(&code); + + { + // merge with same type + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ nop(); + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ nop(); + // merge with high rank + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::AnyAny); + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ nop(); + // merge with different type + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ membar(Assembler::Membar_mask_bits::LoadStore); + __ membar(Assembler::Membar_mask_bits::StoreStore); + } + asm_dump(code.insts()->start(), code.insts()->end()); + // AlwaysMergeDMB + static const unsigned int insns1[] = { + test_encode_dmb_st, + test_encode_nop, + test_encode_dmb_ld, + test_encode_nop, + test_encode_dmb, + test_encode_nop, + test_encode_dmb, + }; + // !AlwaysMergeDMB + static const unsigned int insns2[] = { + test_encode_dmb_st, + test_encode_nop, + test_encode_dmb_ld, + test_encode_nop, + test_encode_dmb, + test_encode_nop, + test_encode_dmb_ld, + test_encode_dmb_st, + }; + if (AlwaysMergeDMB) { + EXPECT_EQ(code.insts()->size(), (CodeSection::csize_t)(sizeof insns1)); + asm_check((const unsigned int *)code.insts()->start(), insns1, sizeof insns1 / sizeof insns1[0]); + } else { + EXPECT_EQ(code.insts()->size(), (CodeSection::csize_t)(sizeof insns2)); + asm_check((const unsigned int *)code.insts()->start(), insns2, sizeof insns2 / sizeof insns2[0]); + } + + BufferBlob::free(b); +} + +TEST_VM(AssemblerAArch64, merge_dmb_1) { + FlagSetting fs(AlwaysMergeDMB, true); + test_merge_dmb(); +} + +TEST_VM(AssemblerAArch64, merge_dmb_2) { + FlagSetting fs(AlwaysMergeDMB, false); + test_merge_dmb(); +} + +TEST_VM(AssemblerAArch64, merge_dmb_block_by_label) { + BufferBlob* b = BufferBlob::create("aarch64Test", 400); + CodeBuffer code(b); + MacroAssembler _masm(&code); + + { + Label l; + // merge can not cross the label + __ membar(Assembler::Membar_mask_bits::StoreStore); + __ bind(l); + __ membar(Assembler::Membar_mask_bits::StoreStore); + } + asm_dump(code.insts()->start(), code.insts()->end()); + static const unsigned int insns[] = { + 0xd5033abf, // dmb.ishst + 0xd5033abf, // dmb.ishst + }; + EXPECT_EQ(code.insts()->size(), (CodeSection::csize_t)(sizeof insns)); + asm_check((const unsigned int *)code.insts()->start(), insns, sizeof insns / sizeof insns[0]); + + BufferBlob::free(b); +} + +TEST_VM(AssemblerAArch64, merge_dmb_after_expand) { + ResourceMark rm; + BufferBlob* b = BufferBlob::create("aarch64Test", 400); + CodeBuffer code(b); + code.set_blob(b); + MacroAssembler _masm(&code); + + { + __ membar(Assembler::Membar_mask_bits::StoreStore); + code.insts()->maybe_expand_to_ensure_remaining(50000); + __ membar(Assembler::Membar_mask_bits::StoreStore); + } + asm_dump(code.insts()->start(), code.insts()->end()); + static const unsigned int insns[] = { + 0xd5033abf, // dmb.ishst + }; + EXPECT_EQ(code.insts()->size(), (CodeSection::csize_t)(sizeof insns)); + asm_check((const unsigned int *)code.insts()->start(), insns, sizeof insns / sizeof insns[0]); +} + +void expect_dmbld(void* addr) { + if (*((uint32_t *) addr) != test_encode_dmb_ld) { + tty->print_cr("Expected dmb.ld"); + FAIL(); + } +} + +void expect_dmbst(void* addr) { + if (*((uint32_t *) addr) != test_encode_dmb_st) { + tty->print_cr("Expected dmb.st"); + FAIL(); + } +} + +void expect_dmb(void* addr) { + if (*((uint32_t *) addr) != test_encode_dmb) { + tty->print_cr("Expected dmb"); + FAIL(); + } +} + +void expect_any_dmb(void* addr) { + uint32_t encode = *((uint32_t *) addr); + if (encode != test_encode_dmb && encode != test_encode_dmb_ld && encode != test_encode_dmb_st) { + tty->print_cr("Expected a dmb.* instruction"); + FAIL(); + } +} + +void expect_different_dmb_kind(void* addr) { + uint32_t pos1 = *((uint32_t *) addr); + uint32_t pos2 = *(((uint32_t *) addr) + 1); + if (pos1 == pos2) { + tty->print_cr("Expected different dmb kind"); + FAIL(); + } +} + +void expect_dmb_at_least_one(void* addr) { + uint32_t pos1 = *((uint32_t *) addr); + uint32_t pos2 = *(((uint32_t *) addr) + 1); + if (pos1 != test_encode_dmb && pos2 != test_encode_dmb) { + tty->print_cr("Expected at least one dmb"); + FAIL(); + } +} + +void expect_dmb_none(void* addr) { + uint32_t pos1 = *((uint32_t *) addr); + uint32_t pos2 = *(((uint32_t *) addr) + 1); + if (pos1 == test_encode_dmb || pos2 == test_encode_dmb) { + tty->print_cr("Expected no dmb"); + FAIL(); + } +} + +void test_merge_dmb_all_kinds() { + BufferBlob* b = BufferBlob::create("aarch64Test", 20000); + CodeBuffer code(b); + MacroAssembler _masm(&code); + + constexpr int count = 5; + struct { + const char* label; + Assembler::Membar_mask_bits flavor; + // Two groups of two bits describing the ordering, can be OR-ed to figure out composite semantics. + // First group describes ops before the barrier. Second group describes ops after the barrier. + // "01" means "load", "10" means "store", "100" means "any". + int mask; + } kind[count] = { + {"storestore", Assembler::StoreStore, 0b010010}, + {"loadstore", Assembler::LoadStore, 0b001010}, + {"loadload", Assembler::LoadLoad, 0b001001}, + {"storeload", Assembler::StoreLoad, 0b100100}, // quirk: StoreLoad is as powerful as AnyAny + {"anyany", Assembler::AnyAny, 0b100100}, + }; + + for (int b1 = 0; b1 < count; b1++) { + for (int b2 = 0; b2 < count; b2++) { + for (int b3 = 0; b3 < count; b3++) { + for (int b4 = 0; b4 < count; b4++) { + // tty->print_cr("%s + %s + %s + %s", kind[b1].label, kind[b2].label, kind[b3].label, kind[b4].label); + + address start = __ pc(); + __ membar(kind[b1].flavor); + __ membar(kind[b2].flavor); + __ membar(kind[b3].flavor); + __ membar(kind[b4].flavor); + address end = __ pc(); + __ nop(); + + size_t size = pointer_delta(end, start, 1); + if (AlwaysMergeDMB) { + // Expect only a single barrier. + EXPECT_EQ(size, (size_t) NativeMembar::instruction_size); + } else { + EXPECT_LE(size, (size_t) NativeMembar::instruction_size * 2); + } + + // Composite ordering for this group of barriers. + int composite_mask = kind[b1].mask | kind[b2].mask | kind[b3].mask | kind[b4].mask; + + if (size == NativeMembar::instruction_size) { + // If there is a single barrier, we can easily test its type. + switch (composite_mask) { + case 0b001001: + case 0b001010: + case 0b001011: + case 0b001101: + case 0b001110: + case 0b001111: + // Any combination of Load(Load|Store|Any) gets dmb.ld + expect_dmbld(start); + break; + case 0b010010: + // Only StoreStore gets dmb.st + expect_dmbst(start); + break; + default: + // Everything else gets folded into full dmb + expect_dmb(start); + break; + } + } else if (size == 2 * NativeMembar::instruction_size) { + // There are two barriers. Make a few sanity checks. + // They must be different kind + expect_any_dmb(start); + expect_any_dmb(start + NativeMembar::instruction_size); + expect_different_dmb_kind(start); + if ((composite_mask & 0b100100) != 0) { + // There was "any" barrier in the group, a full dmb is expected + expect_dmb_at_least_one(start); + } else { + // Otherwise expect no full dmb + expect_dmb_none(start); + } + } else { + // Merging code does not produce this result. + FAIL(); + } + } + } + } + } + + BufferBlob::free(b); +} + +TEST_VM(AssemblerAArch64, merge_dmb_all_kinds_1) { + FlagSetting fs(AlwaysMergeDMB, true); + test_merge_dmb_all_kinds(); +} + +TEST_VM(AssemblerAArch64, merge_dmb_all_kinds_2) { + FlagSetting fs(AlwaysMergeDMB, false); + test_merge_dmb_all_kinds(); +} + +TEST_VM(AssemblerAArch64, merge_ldst) { + BufferBlob* b = BufferBlob::create("aarch64Test", 400); + CodeBuffer code(b); + MacroAssembler _masm(&code); + + { + Label l; + // merge ld/st into ldp/stp + __ ldr(r0, Address(sp, 8)); + __ ldr(r1, Address(sp, 0)); + __ nop(); + __ str(r0, Address(sp, 0)); + __ str(r1, Address(sp, 8)); + __ nop(); + __ ldrw(r0, Address(sp, 0)); + __ ldrw(r1, Address(sp, 4)); + __ nop(); + __ strw(r0, Address(sp, 4)); + __ strw(r1, Address(sp, 0)); + __ nop(); + // can not merge + __ ldrw(r0, Address(sp, 4)); + __ ldr(r1, Address(sp, 8)); + __ nop(); + __ ldrw(r0, Address(sp, 0)); + __ ldrw(r1, Address(sp, 8)); + __ nop(); + __ str(r0, Address(sp, 0)); + __ bind(l); // block by label + __ str(r1, Address(sp, 8)); + __ nop(); + } + asm_dump(code.insts()->start(), code.insts()->end()); + static const unsigned int insns1[] = { + 0xa94003e1, // ldp x1, x0, [sp] + 0xd503201f, // nop + 0xa90007e0, // stp x0, x1, [sp] + 0xd503201f, // nop + 0x294007e0, // ldp w0, w1, [sp] + 0xd503201f, // nop + 0x290003e1, // stp w1, w0, [sp] + 0xd503201f, // nop + 0xb94007e0, // ldr w0, [sp, 4] + 0xf94007e1, // ldr x1, [sp, 8] + 0xd503201f, // nop + 0xb94003e0, // ldr w0, [sp] + 0xb9400be1, // ldr w1, [sp, 8] + 0xd503201f, // nop + 0xf90003e0, // str x0, [sp] + 0xf90007e1, // str x1, [sp, 8] + 0xd503201f, // nop + }; + EXPECT_EQ(code.insts()->size(), (CodeSection::csize_t)(sizeof insns1)); + asm_check((const unsigned int *)code.insts()->start(), insns1, sizeof insns1 / sizeof insns1[0]); + + BufferBlob::free(b); +} + +TEST_VM(AssemblerAArch64, merge_ldst_after_expand) { + ResourceMark rm; + BufferBlob* b = BufferBlob::create("aarch64Test", 400); + CodeBuffer code(b); + code.set_blob(b); + MacroAssembler _masm(&code); + + { + __ ldr(r0, Address(sp, 8)); + code.insts()->maybe_expand_to_ensure_remaining(10000); + __ ldr(r1, Address(sp, 0)); + __ nop(); + __ str(r0, Address(sp, 0)); + code.insts()->maybe_expand_to_ensure_remaining(100000); + __ str(r1, Address(sp, 8)); + __ nop(); + } + asm_dump(code.insts()->start(), code.insts()->end()); + static const unsigned int insns[] = { + 0xa94003e1, // ldp x1, x0, [sp] + 0xd503201f, // nop + 0xa90007e0, // stp x0, x1, [sp] + 0xd503201f, // nop + }; + EXPECT_EQ(code.insts()->size(), (CodeSection::csize_t)(sizeof insns)); + asm_check((const unsigned int *)code.insts()->start(), insns, sizeof insns / sizeof insns[0]); +} + #endif // AARCH64 diff --git a/test/hotspot/gtest/gc/parallel/test_psParallelCompact.cpp b/test/hotspot/gtest/gc/parallel/test_psParallelCompact.cpp deleted file mode 100644 index 4820a01cc57..00000000000 --- a/test/hotspot/gtest/gc/parallel/test_psParallelCompact.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "precompiled.hpp" -#include "gc/parallel/parMarkBitMap.inline.hpp" -#include "gc/parallel/psCompactionManager.inline.hpp" -#include "gc/parallel/psParallelCompact.hpp" -#include "unittest.hpp" - -#ifndef PRODUCT - -class PSParallelCompactTest : public ::testing::Test { - public: - static void print_generic_summary_data(ParallelCompactData& summary_data, - HeapWord* const beg_addr, - HeapWord* const end_addr) { - PSParallelCompact::print_generic_summary_data(summary_data, - beg_addr, end_addr); - } -}; - -// @requires UseParallelGC -TEST_VM(PSParallelCompact, print_generic_summary_data) { - if (!UseParallelGC) { - return; - } - // Check that print_generic_summary_data() does not print the - // end region by placing a bad value in the destination of the - // end region. The end region should not be printed because it - // corresponds to the space after the end of the heap. - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - HeapWord* begin_heap = - (HeapWord*) heap->old_gen()->virtual_space()->low_boundary(); - HeapWord* end_heap = - (HeapWord*) heap->young_gen()->virtual_space()->high_boundary(); - - PSParallelCompactTest::print_generic_summary_data(PSParallelCompact::summary_data(), - begin_heap, end_heap); -} - -#endif diff --git a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp index 40df20ba964..102ede42de6 100644 --- a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp +++ b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp @@ -212,18 +212,6 @@ class TestGenCollectorPolicy { // depends on so many other configurable variables. These tests only try to // verify that there are some basic rules for NewSize honored by the policies. -// If NewSize has been ergonomically set, the collector policy -// should use it for min -// This test doesn't work with 64k pages. See JDK-8331675. -#if !defined(PPC) -TEST_VM(CollectorPolicy, young_min_ergo) { - TestGenCollectorPolicy::SetNewSizeErgo setter(20 * M); - TestGenCollectorPolicy::CheckYoungMin checker(20 * M); - - TestGenCollectorPolicy::TestWrapper::test(&setter, &checker); -} -#endif - // If NewSize has been ergonomically set, the collector policy // should use it for min but calculate the initial young size // using NewRatio. diff --git a/test/hotspot/gtest/utilities/test_ostream.cpp b/test/hotspot/gtest/utilities/test_ostream.cpp index 270ba59212a..5d25c51f3f9 100644 --- a/test/hotspot/gtest/utilities/test_ostream.cpp +++ b/test/hotspot/gtest/utilities/test_ostream.cpp @@ -104,6 +104,56 @@ TEST_VM(ostream, bufferedStream_dynamic_small) { } } +static void test_autoindent(bool on) { + stringStream ss; + const bool prior = ss.set_autoindent(on); + EXPECT_FALSE(prior); + { + streamIndentor si(&ss, 5); + ss.print("ABC"); + ss.print("DEF"); + ss.cr(); + ss.print_cr("0123"); + { + streamIndentor si(&ss, 5); + ss.print_cr("4567"); + ss.print_raw("89AB"); + ss.print_raw("CDEXXXX", 3); + ss.print_raw_cr("XYZ"); + } + ss.print("%u", 100); + ss.print_raw("KB"); + ss.cr(); + } + ss.print("end"); + + if (on) { + EXPECT_STREQ(ss.base(), + " ABCDEF\n" + " 0123\n" + " 4567\n" + " 89ABCDEXYZ\n" + " 100KB\n" + "end" + ); + } else { + // no autoindent: calls should work as always without indentation + EXPECT_STREQ(ss.base(), + "ABCDEF\n" + "0123\n" + "4567\n" + "89ABCDEXYZ\n" + "100KB\n" + "end" + ); + } + bool prior2 = ss.set_autoindent(prior); + EXPECT_EQ(prior2, on); +} + +TEST_VM(ostream, autoindent_on) { test_autoindent(true); } +TEST_VM(ostream, autoindent_off) { test_autoindent(false); } + /* Activate to manually test bufferedStream dynamic cap. TEST_VM(ostream, bufferedStream_dynamic_large) { diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index 2364d601cd7..9a52a731039 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -28,8 +28,6 @@ ############################################################################# vmTestbase/nsk/jvmti/AttachOnDemand/attach020/TestDescription.java 8287324 generic-all -vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java 8205957 generic-all -vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/TestDescription.java 8205957 linux-x64,windows-x64 vmTestbase/nsk/jvmti/scenarios/sampling/SP07/sp07t002/TestDescription.java 8245680 windows-x64 vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java 8265295 linux-x64,windows-x64 diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index b6cc0489485..5290a9bb626 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -51,18 +51,6 @@ compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x compiler/loopopts/TestUnreachableInnerLoop.java 8288981 linux-s390x -compiler/rtm/locking/TestRTMAbortRatio.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMAbortThreshold.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMLockingCalculationDelay.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMLockingThreshold.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestRTMSpinLoopCount.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestUseRTMDeopt.java 8183263 generic-x64,generic-i586 -compiler/rtm/locking/TestUseRTMXendForLockBusy.java 8183263 generic-x64,generic-i586 -compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java 8183263 generic-x64,generic-i586 - compiler/c2/Test8004741.java 8235801 generic-all compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all @@ -79,8 +67,6 @@ compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 compiler/startup/StartupOutput.java 8326615 generic-x64 -compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java 8332369 generic-all - compiler/codecache/CodeCacheFullCountTest.java 8332954 generic-all ############################################################################# @@ -118,11 +104,6 @@ runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 runtime/Thread/TestAlwaysPreTouchStacks.java 8324781 linux-all -applications/jcstress/accessAtomic.java 8325984 generic-all -applications/jcstress/acqrel.java 8325984 generic-all -applications/jcstress/atomicity.java 8325984 generic-all -applications/jcstress/coherence.java 8325984 generic-all - applications/jcstress/copy.java 8229852 linux-all containers/docker/TestJcmd.java 8278102 linux-all @@ -139,6 +120,7 @@ serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all serviceability/jvmti/vthread/GetThreadStateMountedTest/GetThreadStateMountedTest.java 8318090,8318729 generic-all serviceability/jvmti/vthread/GetSetLocalTest/GetSetLocalTest.java 8286836 generic-all +serviceability/jvmti/vthread/CarrierThreadEventNotification/CarrierThreadEventNotification.java 8333681 generic-all serviceability/dcmd/gc/RunFinalizationTest.java 8227120 generic-all serviceability/sa/ClhsdbCDSCore.java 8267433 macosx-x64 @@ -185,7 +167,7 @@ vmTestbase/vm/mlvm/meth/stress/jdi/breakpointInCompiledCode/Test.java 8257761 ge vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_a/TestDescription.java 8013267 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_b/TestDescription.java 8013267 generic-all vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java 8013267 generic-all -vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id1 8325905 generic-all +vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id1 8324756 generic-all vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 78db6d01775..ecded09f4cc 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -254,7 +254,6 @@ tier2_compiler = \ compiler/parsing/ \ compiler/rangechecks/ \ compiler/reflection/ \ - compiler/rtm/ \ compiler/runtime/Test6826736.java \ compiler/stable/ \ compiler/stringopts/ \ diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index 55594650219..0e86045618b 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -33,7 +33,7 @@ /* * @test - * @bug 8318446 8331054 + * @bug 8318446 8331054 8331311 * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / @@ -42,7 +42,7 @@ /* * @test - * @bug 8318446 8331054 + * @bug 8318446 8331054 8331311 * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / @@ -112,16 +112,32 @@ public TestMergeStores() { testGroups.get("test2").put("test2b", (_,_) -> { return test2b(aB.clone(), offset1, vL1); }); testGroups.get("test2").put("test2c", (_,_) -> { return test2c(aB.clone(), offset1, vL1); }); testGroups.get("test2").put("test2d", (_,_) -> { return test2d(aB.clone(), offset1, vL1); }); - testGroups.get("test2").put("test2e", (_,_) -> { return test2d(aB.clone(), offset1, vL1); }); + testGroups.get("test2").put("test2e", (_,_) -> { return test2e(aB.clone(), offset1, vL1); }); + + testGroups.put("test2BE", new HashMap<String,TestFunction>()); + testGroups.get("test2BE").put("test2RBE", (_,_) -> { return test2RBE(aB.clone(), offset1, vL1); }); + testGroups.get("test2BE").put("test2aBE", (_,_) -> { return test2aBE(aB.clone(), offset1, vL1); }); + testGroups.get("test2BE").put("test2bBE", (_,_) -> { return test2bBE(aB.clone(), offset1, vL1); }); + testGroups.get("test2BE").put("test2cBE", (_,_) -> { return test2cBE(aB.clone(), offset1, vL1); }); + testGroups.get("test2BE").put("test2dBE", (_,_) -> { return test2dBE(aB.clone(), offset1, vL1); }); + testGroups.get("test2BE").put("test2eBE", (_,_) -> { return test2eBE(aB.clone(), offset1, vL1); }); testGroups.put("test3", new HashMap<String,TestFunction>()); testGroups.get("test3").put("test3R", (_,_) -> { return test3R(aB.clone(), offset1, vL1); }); testGroups.get("test3").put("test3a", (_,_) -> { return test3a(aB.clone(), offset1, vL1); }); + testGroups.put("test3BE", new HashMap<String,TestFunction>()); + testGroups.get("test3BE").put("test3RBE", (_,_) -> { return test3RBE(aB.clone(), offset1, vL1); }); + testGroups.get("test3BE").put("test3aBE", (_,_) -> { return test3aBE(aB.clone(), offset1, vL1); }); + testGroups.put("test4", new HashMap<String,TestFunction>()); testGroups.get("test4").put("test4R", (_,_) -> { return test4R(aB.clone(), offset1, vL1, vI1, vS1, vB1); }); testGroups.get("test4").put("test4a", (_,_) -> { return test4a(aB.clone(), offset1, vL1, vI1, vS1, vB1); }); + testGroups.put("test4BE", new HashMap<String,TestFunction>()); + testGroups.get("test4BE").put("test4RBE", (_,_) -> { return test4RBE(aB.clone(), offset1, vL1, vI1, vS1, vB1); }); + testGroups.get("test4BE").put("test4aBE", (_,_) -> { return test4aBE(aB.clone(), offset1, vL1, vI1, vS1, vB1); }); + testGroups.put("test5", new HashMap<String,TestFunction>()); testGroups.get("test5").put("test5R", (_,_) -> { return test5R(aB.clone(), offset1); }); testGroups.get("test5").put("test5a", (_,_) -> { return test5a(aB.clone(), offset1); }); @@ -134,6 +150,10 @@ public TestMergeStores() { testGroups.get("test7").put("test7R", (_,_) -> { return test7R(aB.clone(), offset1, vI1); }); testGroups.get("test7").put("test7a", (_,_) -> { return test7a(aB.clone(), offset1, vI1); }); + testGroups.put("test7BE", new HashMap<String,TestFunction>()); + testGroups.get("test7BE").put("test7RBE", (_,_) -> { return test7RBE(aB.clone(), offset1, vI1); }); + testGroups.get("test7BE").put("test7aBE", (_,_) -> { return test7aBE(aB.clone(), offset1, vI1); }); + testGroups.put("test100", new HashMap<String,TestFunction>()); testGroups.get("test100").put("test100R", (_,_) -> { return test100R(aS.clone(), offset1); }); testGroups.get("test100").put("test100a", (_,_) -> { return test100a(aS.clone(), offset1); }); @@ -146,6 +166,10 @@ public TestMergeStores() { testGroups.get("test102").put("test102R", (_,_) -> { return test102R(aS.clone(), offset1, vL1, vI1, vS1); }); testGroups.get("test102").put("test102a", (_,_) -> { return test102a(aS.clone(), offset1, vL1, vI1, vS1); }); + testGroups.put("test102BE", new HashMap<String,TestFunction>()); + testGroups.get("test102BE").put("test102RBE", (_,_) -> { return test102RBE(aS.clone(), offset1, vL1, vI1, vS1); }); + testGroups.get("test102BE").put("test102aBE", (_,_) -> { return test102aBE(aS.clone(), offset1, vL1, vI1, vS1); }); + testGroups.put("test200", new HashMap<String,TestFunction>()); testGroups.get("test200").put("test200R", (_,_) -> { return test200R(aI.clone(), offset1); }); testGroups.get("test200").put("test200a", (_,_) -> { return test200a(aI.clone(), offset1); }); @@ -158,6 +182,10 @@ public TestMergeStores() { testGroups.get("test202").put("test202R", (_,_) -> { return test202R(aI.clone(), offset1, vL1, vI1); }); testGroups.get("test202").put("test202a", (_,_) -> { return test202a(aI.clone(), offset1, vL1, vI1); }); + testGroups.put("test202BE", new HashMap<String,TestFunction>()); + testGroups.get("test202BE").put("test202RBE", (_,_) -> { return test202RBE(aI.clone(), offset1, vL1, vI1); }); + testGroups.get("test202BE").put("test202aBE", (_,_) -> { return test202aBE(aI.clone(), offset1, vL1, vI1); }); + testGroups.put("test300", new HashMap<String,TestFunction>()); testGroups.get("test300").put("test300R", (_,_) -> { return test300R(aI.clone()); }); testGroups.get("test300").put("test300a", (_,_) -> { return test300a(aI.clone()); }); @@ -184,6 +212,24 @@ public TestMergeStores() { // First use something in range, and after warmup randomize going outside the range. // Consequence: all RangeChecks stay in the final compilation. + testGroups.put("test500BE", new HashMap<String,TestFunction>()); + testGroups.get("test500BE").put("test500RBE", (_,_) -> { return test500RBE(aB.clone(), offset1, vL1); }); + testGroups.get("test500BE").put("test500aBE", (_,_) -> { return test500aBE(aB.clone(), offset1, vL1); }); + + testGroups.put("test501BE", new HashMap<String,TestFunction>()); + testGroups.get("test501BE").put("test500RBE", (_,i) -> { return test500RBE(aB.clone(), RANGE - 20 + (i % 30), vL1); }); + testGroups.get("test501BE").put("test501aBE", (_,i) -> { return test501aBE(aB.clone(), RANGE - 20 + (i % 30), vL1); }); + // +-------------------+ + // Create offsets that are sometimes going to pass all RangeChecks, and sometimes one, and sometimes none. + // Consequence: all RangeChecks stay in the final compilation. + + testGroups.put("test502BE", new HashMap<String,TestFunction>()); + testGroups.get("test502BE").put("test500RBE", (w,i) -> { return test500RBE(aB.clone(), w ? offset1 : RANGE - 20 + (i % 30), vL1); }); + testGroups.get("test502BE").put("test502aBE", (w,i) -> { return test502aBE(aB.clone(), w ? offset1 : RANGE - 20 + (i % 30), vL1); }); + // +-----+ +-------------------+ + // First use something in range, and after warmup randomize going outside the range. + // Consequence: all RangeChecks stay in the final compilation. + testGroups.put("test600", new HashMap<String,TestFunction>()); testGroups.get("test600").put("test600R", (_,i) -> { return test600R(aB.clone(), aI.clone(), i); }); testGroups.get("test600").put("test600a", (_,i) -> { return test600a(aB.clone(), aI.clone(), i); }); @@ -191,6 +237,14 @@ public TestMergeStores() { testGroups.put("test700", new HashMap<String,TestFunction>()); testGroups.get("test700").put("test700R", (_,i) -> { return test700R(aI.clone(), i); }); testGroups.get("test700").put("test700a", (_,i) -> { return test700a(aI.clone(), i); }); + + testGroups.put("test800", new HashMap<String,TestFunction>()); + testGroups.get("test800").put("test800R", (_,_) -> { return test800R(aB.clone(), offset1, vL1); }); + testGroups.get("test800").put("test800a", (_,_) -> { return test800a(aB.clone(), offset1, vL1); }); + + testGroups.put("test800BE", new HashMap<String,TestFunction>()); + testGroups.get("test800BE").put("test800RBE", (_,_) -> { return test800RBE(aB.clone(), offset1, vL1); }); + testGroups.get("test800BE").put("test800aBE", (_,_) -> { return test800aBE(aB.clone(), offset1, vL1); }); } @Warmup(100) @@ -208,24 +262,39 @@ public TestMergeStores() { "test2c", "test2d", "test2e", + "test2aBE", + "test2bBE", + "test2cBE", + "test2dBE", + "test2eBE", "test3a", + "test3aBE", "test4a", + "test4aBE", "test5a", "test6a", "test7a", + "test7aBE", "test100a", "test101a", "test102a", + "test102aBE", "test200a", "test201a", "test202a", + "test202aBE", "test300a", "test400a", "test500a", "test501a", "test502a", + "test500aBE", + "test501aBE", + "test502aBE", "test600a", - "test700a"}) + "test700a", + "test800a", + "test800aBE"}) public void runTests(RunInfo info) { // Repeat many times, so that we also have multiple iterations for post-warmup to potentially recompile int iters = info.isWarmUp() ? 1_000 : 50_000; @@ -412,6 +481,39 @@ static void storeLongLE(byte[] bytes, int offset, long value) { (byte)(value >> 56)); } + // ------------------------------------------- + // ------- Big-Endian API ---------- + // ------------------------------------------- + + // Store a short BE into an array using store bytes in an array + @ForceInline + static void storeShortBE(byte[] bytes, int offset, short value) { + storeBytes(bytes, offset, (byte)(value >> 8), + (byte)(value >> 0)); + } + + // Store an int BE into an array using store bytes in an array + @ForceInline + static void storeIntBE(byte[] bytes, int offset, int value) { + storeBytes(bytes, offset, (byte)(value >> 24), + (byte)(value >> 16), + (byte)(value >> 8 ), + (byte)(value >> 0 )); + } + + // Store an int BE into an array using store bytes in an array + @ForceInline + static void storeLongBE(byte[] bytes, int offset, long value) { + storeBytes(bytes, offset, (byte)(value >> 56), + (byte)(value >> 48), + (byte)(value >> 40), + (byte)(value >> 32), + (byte)(value >> 24), + (byte)(value >> 16), + (byte)(value >> 8 ), + (byte)(value >> 0 )); + } + // Store 2 bytes into an array @ForceInline static void storeBytes(byte[] bytes, int offset, byte b0, byte b1) { @@ -476,7 +578,7 @@ static Object[] test1a(byte[] a) { static Object[] test1b(byte[] a) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store if (a == null) {return null;} - UNSAFE.putLongUnaligned(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET, 0xdeadbeefbaadbabeL); + UNSAFE.putLongUnaligned(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET, 0xdeadbeefbaadbabeL, false /* bigEndian */); return new Object[]{ a }; } @@ -589,7 +691,13 @@ static Object[] test2R(byte[] a, int offset, long v) { @Test @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test2a(byte[] a, int offset, long v) { a[offset + 0] = (byte)(v >> 0); a[offset + 1] = (byte)(v >> 8); @@ -608,13 +716,19 @@ static Object[] test2a(byte[] a, int offset, long v) { static Object[] test2b(byte[] a, int offset, long v) { // Add custom null check, to ensure the unsafe access always recognizes its type as an array store if (a == null) {return null;} - UNSAFE.putLongUnaligned(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset, v); + UNSAFE.putLongUnaligned(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset, v, false /* bigEndian */); return new Object[]{ a }; } @Test @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test2c(byte[] a, int offset, long v) { storeLongLE(a, offset, v); return new Object[]{ a }; @@ -638,6 +752,82 @@ static Object[] test2e(byte[] a, int offset, long v) { return new Object[]{ a }; } + @DontCompile + static Object[] test2RBE(byte[] a, int offset, long v) { + a[offset + 0] = (byte)(v >> 56); + a[offset + 1] = (byte)(v >> 48); + a[offset + 2] = (byte)(v >> 40); + a[offset + 3] = (byte)(v >> 32); + a[offset + 4] = (byte)(v >> 24); + a[offset + 5] = (byte)(v >> 16); + a[offset + 6] = (byte)(v >> 8); + a[offset + 7] = (byte)(v >> 0); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test2aBE(byte[] a, int offset, long v) { + a[offset + 0] = (byte)(v >> 56); + a[offset + 1] = (byte)(v >> 48); + a[offset + 2] = (byte)(v >> 40); + a[offset + 3] = (byte)(v >> 32); + a[offset + 4] = (byte)(v >> 24); + a[offset + 5] = (byte)(v >> 16); + a[offset + 6] = (byte)(v >> 8); + a[offset + 7] = (byte)(v >> 0); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + applyIf = {"UseUnalignedAccesses", "true"}) + static Object[] test2bBE(byte[] a, int offset, long v) { + // Add custom null check, to ensure the unsafe access always recognizes its type as an array store + if (a == null) {return null;} + UNSAFE.putLongUnaligned(a, UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset, v, true /* bigEndian */); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test2cBE(byte[] a, int offset, long v) { + storeLongBE(a, offset, v); + return new Object[]{ a }; + } + + @Test + // No optimization, casting long -> int -> byte does not work + static Object[] test2dBE(byte[] a, int offset, long v) { + storeIntBE(a, offset + 0, (int)(v >> 32)); + storeIntBE(a, offset + 4, (int)(v >> 0)); + return new Object[]{ a }; + } + + @Test + // No optimization, casting long -> short -> byte does not work + static Object[] test2eBE(byte[] a, int offset, long v) { + storeShortBE(a, offset + 0, (short)(v >> 48)); + storeShortBE(a, offset + 2, (short)(v >> 32)); + storeShortBE(a, offset + 4, (short)(v >> 16)); + storeShortBE(a, offset + 6, (short)(v >> 0)); + return new Object[]{ a }; + } + @DontCompile static Object[] test3R(byte[] a, int offset, long v) { a[offset + 0] = (byte)(v >> 0); @@ -653,7 +843,13 @@ static Object[] test3R(byte[] a, int offset, long v) { @Test @IR(counts = {IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test3a(byte[] a, int offset, long v) { a[offset + 0] = (byte)(v >> 0); a[offset + 1] = (byte)(v >> 8); @@ -666,6 +862,40 @@ static Object[] test3a(byte[] a, int offset, long v) { return new Object[]{ a }; } + @DontCompile + static Object[] test3RBE(byte[] a, int offset, long v) { + a[offset + 0] = (byte)(v >> 24); + a[offset + 1] = (byte)(v >> 16); + a[offset + 2] = (byte)(v >> 8); + a[offset + 3] = (byte)(v >> 0); + a[offset + 4] = (byte)(v >> 24); + a[offset + 5] = (byte)(v >> 16); + a[offset + 6] = (byte)(v >> 8); + a[offset + 7] = (byte)(v >> 0); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test3aBE(byte[] a, int offset, long v) { + a[offset + 0] = (byte)(v >> 24); + a[offset + 1] = (byte)(v >> 16); + a[offset + 2] = (byte)(v >> 8); + a[offset + 3] = (byte)(v >> 0); + a[offset + 4] = (byte)(v >> 24); + a[offset + 5] = (byte)(v >> 16); + a[offset + 6] = (byte)(v >> 8); + a[offset + 7] = (byte)(v >> 0); + return new Object[]{ a }; + } + @DontCompile static Object[] test4R(byte[] a, int offset, long v1, int v2, short v3, byte v4) { a[offset + 0] = (byte)0x00; @@ -693,7 +923,14 @@ static Object[] test4R(byte[] a, int offset, long v1, int v2, short v3, byte v4) IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test4a(byte[] a, int offset, long v1, int v2, short v3, byte v4) { a[offset + 0] = (byte)0x00; // individual load expected to go into state of RC a[offset + 1] = (byte)0xFF; @@ -715,6 +952,62 @@ static Object[] test4a(byte[] a, int offset, long v1, int v2, short v3, byte v4) return new Object[]{ a }; } + @DontCompile + static Object[] test4RBE(byte[] a, int offset, long v1, int v2, short v3, byte v4) { + a[offset + 0] = (byte)0x00; + a[offset + 1] = (byte)0xFF; + a[offset + 2] = v4; + a[offset + 3] = (byte)0x42; + a[offset + 4] = (byte)(v1 >> 8); + a[offset + 5] = (byte)(v1 >> 0); + a[offset + 6] = (byte)0xAB; + a[offset + 7] = (byte)0xCD; + a[offset + 8] = (byte)0xEF; + a[offset + 9] = (byte)0x01; + a[offset + 10] = (byte)(v2 >> 24); + a[offset + 11] = (byte)(v2 >> 16); + a[offset + 12] = (byte)(v2 >> 8); + a[offset + 13] = (byte)(v2 >> 0); + a[offset + 14] = (byte)(v3 >> 8); + a[offset + 15] = (byte)(v3 >> 0); + a[offset + 16] = (byte)0xEF; + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+ 1 for uncommon trap) + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test4aBE(byte[] a, int offset, long v1, int v2, short v3, byte v4) { + a[offset + 0] = (byte)0x00; // individual load expected to go into state of RC + a[offset + 1] = (byte)0xFF; + a[offset + 2] = v4; + a[offset + 3] = (byte)0x42; + a[offset + 4] = (byte)(v1 >> 8); + a[offset + 5] = (byte)(v1 >> 0); + a[offset + 6] = (byte)0xAB; + a[offset + 7] = (byte)0xCD; + a[offset + 8] = (byte)0xEF; + a[offset + 9] = (byte)0x01; + a[offset + 10] = (byte)(v2 >> 24); + a[offset + 11] = (byte)(v2 >> 16); + a[offset + 12] = (byte)(v2 >> 8); + a[offset + 13] = (byte)(v2 >> 0); + a[offset + 14] = (byte)(v3 >> 8); + a[offset + 15] = (byte)(v3 >> 0); + a[offset + 16] = (byte)0xEF; + return new Object[]{ a }; + } + @DontCompile static Object[] test5R(byte[] a, int offset) { a[offset + 0] = (byte)0x01; @@ -810,6 +1103,26 @@ static Object[] test7a(byte[] a, int offset1, int v1) { return new Object[]{ a }; } + @DontCompile + static Object[] test7RBE(byte[] a, int offset1, int v1) { + a[offset1 + 1] = (byte)(v1 >> 24); + a[offset1 + 2] = (byte)(v1 >> 16); + a[offset1 + 3] = (byte)(v1 >> 8); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + static Object[] test7aBE(byte[] a, int offset1, int v1) { + a[offset1 + 1] = (byte)(v1 >> 24); + a[offset1 + 2] = (byte)(v1 >> 16); + a[offset1 + 3] = (byte)(v1 >> 8); + return new Object[]{ a }; + } + @DontCompile static Object[] test100R(short[] a, int offset) { a[offset + 0] = (short)0x0100; @@ -925,7 +1238,14 @@ static Object[] test102R(short[] a, int offset, long v1, int v2, short v3) { IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+1 that goes into RC) IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", + IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged + IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test102a(short[] a, int offset, long v1, int v2, short v3) { a[offset + 0] = (short)0x0000; // store goes into RC a[offset + 1] = (short)0xFFFF; @@ -947,6 +1267,62 @@ static Object[] test102a(short[] a, int offset, long v1, int v2, short v3) { return new Object[]{ a }; } + @DontCompile + static Object[] test102RBE(short[] a, int offset, long v1, int v2, short v3) { + a[offset + 0] = (short)0x0000; + a[offset + 1] = (short)0xFFFF; + a[offset + 2] = v3; + a[offset + 3] = (short)0x4242; + a[offset + 4] = (short)(v1 >> 16); + a[offset + 5] = (short)(v1 >> 0); + a[offset + 6] = (short)0xAB11; + a[offset + 7] = (short)0xCD36; + a[offset + 8] = (short)0xEF89; + a[offset + 9] = (short)0x0156; + a[offset + 10] = (short)(v1 >> 48); + a[offset + 11] = (short)(v1 >> 32); + a[offset + 12] = (short)(v1 >> 16); + a[offset + 13] = (short)(v1 >> 0); + a[offset + 14] = (short)(v2 >> 16); + a[offset + 15] = (short)(v2 >> 0); + a[offset + 16] = (short)0xEFEF; + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "12", + IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // Stores of constants can be merged + IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_C_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4", // 3 (+1 that goes into RC) + IRNode.STORE_I_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "3", + IRNode.STORE_L_OF_CLASS, "short\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test102aBE(short[] a, int offset, long v1, int v2, short v3) { + a[offset + 0] = (short)0x0000; // store goes into RC + a[offset + 1] = (short)0xFFFF; + a[offset + 2] = v3; + a[offset + 3] = (short)0x4242; + a[offset + 4] = (short)(v1 >> 16); + a[offset + 5] = (short)(v1 >> 0); + a[offset + 6] = (short)0xAB11; + a[offset + 7] = (short)0xCD36; + a[offset + 8] = (short)0xEF89; + a[offset + 9] = (short)0x0156; + a[offset + 10] = (short)(v1 >> 48); + a[offset + 11] = (short)(v1 >> 32); + a[offset + 12] = (short)(v1 >> 16); + a[offset + 13] = (short)(v1 >> 0); + a[offset + 14] = (short)(v2 >> 16); + a[offset + 15] = (short)(v2 >> 0); + a[offset + 16] = (short)0xEFEF; + return new Object[]{ a }; + } + @DontCompile static Object[] test200R(int[] a, int offset) { a[offset + 0] = 0x01001236; @@ -1062,7 +1438,14 @@ static Object[] test202R(int[] a, int offset, long v1, int v2) { IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", // 5 (+1 that goes into RC) IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6"}, - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "10", + IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4"}, // Stores of constants can be merged + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test202a(int[] a, int offset, long v1, int v2) { a[offset + 0] = 0x00000000; // merged with store below, but also kept unchanged for RC a[offset + 1] = 0xFFFFFFFF; @@ -1075,7 +1458,7 @@ static Object[] test202a(int[] a, int offset, long v1, int v2) { a[offset + 8] = 0xEF890173; a[offset + 9] = 0x01560124; a[offset + 10] = (int)(v1 >> 0); - a[offset + 11] = (int)(v1 >> 32); + a[offset + 11] = (int)(v1 >> 32); // Stores to +11 and +12 can be merged also on big-endian a[offset + 12] = (int)(v1 >> 0); a[offset + 13] = (int)(v1 >> 32); a[offset + 14] = v2; @@ -1084,6 +1467,62 @@ static Object[] test202a(int[] a, int offset, long v1, int v2) { return new Object[]{ a }; } + @DontCompile + static Object[] test202RBE(int[] a, int offset, long v1, int v2) { + a[offset + 0] = 0x00000000; + a[offset + 1] = 0xFFFFFFFF; + a[offset + 2] = v2; + a[offset + 3] = 0x42424242; + a[offset + 4] = (int)(v1 >> 32); + a[offset + 5] = (int)(v1 >> 0); + a[offset + 6] = 0xAB110129; + a[offset + 7] = 0xCD360183; + a[offset + 8] = 0xEF890173; + a[offset + 9] = 0x01560124; + a[offset + 10] = (int)(v1 >> 32); + a[offset + 11] = (int)(v1 >> 0); + a[offset + 12] = (int)(v1 >> 32); + a[offset + 13] = (int)(v1 >> 0); + a[offset + 14] = v2; + a[offset + 15] = v2; + a[offset + 16] = 0xEFEFEFEF; + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "10", + IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "4"}, // Stores of constants can be merged + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", // 5 (+1 that goes into RC) + IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test202aBE(int[] a, int offset, long v1, int v2) { + a[offset + 0] = 0x00000000; // merged with store below, but also kept unchanged for RC + a[offset + 1] = 0xFFFFFFFF; + a[offset + 2] = v2; + a[offset + 3] = 0x42424242; + a[offset + 4] = (int)(v1 >> 32); + a[offset + 5] = (int)(v1 >> 0); + a[offset + 6] = 0xAB110129; + a[offset + 7] = 0xCD360183; + a[offset + 8] = 0xEF890173; + a[offset + 9] = 0x01560124; + a[offset + 10] = (int)(v1 >> 32); + a[offset + 11] = (int)(v1 >> 0); // Stores to +11 and +12 can be merged also on little-endian + a[offset + 12] = (int)(v1 >> 32); + a[offset + 13] = (int)(v1 >> 0); + a[offset + 14] = v2; + a[offset + 15] = v2; + a[offset + 16] = 0xEFEFEFEF; + return new Object[]{ a }; + } + @DontCompile static Object[] test300R(int[] a) { a[2] = 42; @@ -1175,7 +1614,13 @@ static Object[] test500R(byte[] a, int offset, long v) { IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // expect merged - applyIf = {"UseUnalignedAccesses", "true"}) + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"big-endian", "true"}) static Object[] test500a(byte[] a, int offset, long v) { int idx = 0; try { @@ -1255,6 +1700,140 @@ static Object[] test502a(byte[] a, int offset, long v) { return new Object[]{ a, new int[]{ idx } }; } + @DontCompile + // The 500-series has all the same code, but is executed with different inputs: + // 500a: never violate a RangeCheck -> expect will always merge stores + // 501a: randomly violate RangeCheck, also during warmup -> never merge stores + // 502a: during warmup never violate RangeCheck -> compile once with merged stores + // but then after warmup violate RangeCheck -> recompile without merged stores + static Object[] test500RBE(byte[] a, int offset, long v) { + int idx = 0; + try { + a[offset + 0] = (byte)(v >> 56); + idx = 1; + a[offset + 1] = (byte)(v >> 48); + idx = 2; + a[offset + 2] = (byte)(v >> 40); + idx = 3; + a[offset + 3] = (byte)(v >> 32); + idx = 4; + a[offset + 4] = (byte)(v >> 24); + idx = 5; + a[offset + 5] = (byte)(v >> 16); + idx = 6; + a[offset + 6] = (byte)(v >> 8); + idx = 7; + a[offset + 7] = (byte)(v >> 0); + idx = 8; + } catch (ArrayIndexOutOfBoundsException _) {} + return new Object[]{ a, new int[]{ idx } }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", // for RangeCheck trap + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1"}, // expect merged + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test500aBE(byte[] a, int offset, long v) { + int idx = 0; + try { + a[offset + 0] = (byte)(v >> 56); + idx = 1; + a[offset + 1] = (byte)(v >> 48); + idx = 2; + a[offset + 2] = (byte)(v >> 40); + idx = 3; + a[offset + 3] = (byte)(v >> 32); + idx = 4; + a[offset + 4] = (byte)(v >> 24); + idx = 5; + a[offset + 5] = (byte)(v >> 16); + idx = 6; + a[offset + 6] = (byte)(v >> 8); + idx = 7; + a[offset + 7] = (byte)(v >> 0); + idx = 8; + } catch (ArrayIndexOutOfBoundsException _) {} + return new Object[]{ a, new int[]{ idx } }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test501aBE(byte[] a, int offset, long v) { + int idx = 0; + try { + a[offset + 0] = (byte)(v >> 56); + idx = 1; + a[offset + 1] = (byte)(v >> 48); + idx = 2; + a[offset + 2] = (byte)(v >> 40); + idx = 3; + a[offset + 3] = (byte)(v >> 32); + idx = 4; + a[offset + 4] = (byte)(v >> 24); + idx = 5; + a[offset + 5] = (byte)(v >> 16); + idx = 6; + a[offset + 6] = (byte)(v >> 8); + idx = 7; + a[offset + 7] = (byte)(v >> 0); + idx = 8; + } catch (ArrayIndexOutOfBoundsException _) {} + return new Object[]{ a, new int[]{ idx } }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "8", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "7", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test502aBE(byte[] a, int offset, long v) { + int idx = 0; + try { + a[offset + 0] = (byte)(v >> 56); + idx = 1; + a[offset + 1] = (byte)(v >> 48); + idx = 2; + a[offset + 2] = (byte)(v >> 40); + idx = 3; + a[offset + 3] = (byte)(v >> 32); + idx = 4; + a[offset + 4] = (byte)(v >> 24); + idx = 5; + a[offset + 5] = (byte)(v >> 16); + idx = 6; + a[offset + 6] = (byte)(v >> 8); + idx = 7; + a[offset + 7] = (byte)(v >> 0); + idx = 8; + } catch (ArrayIndexOutOfBoundsException _) {} + return new Object[]{ a, new int[]{ idx } }; + } + @DontCompile static Object[] test600R(byte[] aB, int[] aI, int i) { Object a = null; @@ -1319,4 +1898,69 @@ static Object[] test700a(int[] a, long v1) { a[1] = (int)(v1 >> -2); return new Object[]{ a }; } + + @DontCompile + static Object[] test800R(byte[] a, int offset, long v) { + a[offset + 0] = (byte)(v >> 0); + a[offset + 1] = (byte)(v >> 8); + a[offset + 2] = (byte)(v >> 16); + a[offset + 3] = (byte)(v >> 24); + a[offset + 4] = (byte)(v >> 32); + a[offset + 5] = (byte)(v >> 40); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}) + static Object[] test800a(byte[] a, int offset, long v) { + // Merge attempts begin at the lowest store in the Memory chain. + // Candidates are found following the chain. The list is trimmed to a + // power of 2 length by removing higher stores. + a[offset + 0] = (byte)(v >> 0); // Removed from candidate list + a[offset + 1] = (byte)(v >> 8); // Removed from candidate list + a[offset + 2] = (byte)(v >> 16); // The 4 following stores are on the candidate list. + a[offset + 3] = (byte)(v >> 24); // The current logic does not merge them + a[offset + 4] = (byte)(v >> 32); // since it would require shifting the input. + a[offset + 5] = (byte)(v >> 40); + return new Object[]{ a }; + } + + @DontCompile + static Object[] test800RBE(byte[] a, int offset, long v) { + a[offset + 0] = (byte)(v >> 40); + a[offset + 1] = (byte)(v >> 32); + a[offset + 2] = (byte)(v >> 24); + a[offset + 3] = (byte)(v >> 16); + a[offset + 4] = (byte)(v >> 8); + a[offset + 5] = (byte)(v >> 0); + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "6", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIfPlatform = {"little-endian", "true"}) + @IR(counts = {IRNode.STORE_B_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2", + IRNode.STORE_C_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0", + IRNode.STORE_I_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "1", + IRNode.STORE_L_OF_CLASS, "byte\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"}, + applyIf = {"UseUnalignedAccesses", "true"}, + applyIfPlatform = {"big-endian", "true"}) + static Object[] test800aBE(byte[] a, int offset, long v) { + // Merge attempts begin at the lowest store in the Memory chain. + // Candidates are found following the chain. The list is trimmed to a + // power of 2 length by removing higher stores. + a[offset + 0] = (byte)(v >> 40); // Removed from candidate list + a[offset + 1] = (byte)(v >> 32); // Removed from candidate list + a[offset + 2] = (byte)(v >> 24); // The 4 following stores are on the candidate list + a[offset + 3] = (byte)(v >> 16); // and they are successfully merged on big endian platforms. + a[offset + 4] = (byte)(v >> 8); + a[offset + 5] = (byte)(v >> 0); + return new Object[]{ a }; + } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestArrLenCheckOptimization.java b/test/hotspot/jtreg/compiler/c2/irTests/TestArrLenCheckOptimization.java new file mode 100644 index 00000000000..cb955bf14e7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestArrLenCheckOptimization.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024, Arm Limited. All rights reserved. + * 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 compiler.c2.irTests; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Asserts; + +/* + * @test + * @bug 8321308 + * @summary AArch64: Fix matching predication for cbz/cbnz + * @requires os.arch=="aarch64" + * @library /test/lib / + * @run driver compiler.c2.irTests.TestArrLenCheckOptimization + */ + +public class TestArrLenCheckOptimization { + + int result = 0; + + @Test + @IR(counts = {IRNode.CBZW_LS, "1"}) + void test_le_int(int ia[]) { + result += ia[0]; + } + + @Test + @IR(counts = {IRNode.CBNZW_HI, "1"}) + void test_gt_int(int ia[]) { + if (ia.length > 0) { + result += 0x88; + } else { + result -= 1; + } + } + + @Test + @IR(counts = {IRNode.CBZ_LS, "1"}) + void test_le_long(int ia[]) { + if (Long.compareUnsigned(ia.length, 0) > 0) { + result += 0x80; + } else { + result -= 1; + } + } + + @Test + @IR(counts = {IRNode.CBZ_HI, "1"}) + void test_gt_long(int ia[]) { + if (Long.compareUnsigned(ia.length, 0) > 0) { + result += 0x82; + } else { + result -= 1; + } + } + + @Run(test = {"test_le_int", "test_gt_int", "test_le_long", "test_gt_long"}, + mode = RunMode.STANDALONE) + public void test_runner() { + for (int i = 0; i < 10_000; i++) { + test_le_int(new int[1]); + test_gt_int(new int[0]); + test_le_long(new int[1]); + test_gt_long(new int[0]); + } + } + + public static void main(String [] args) { + TestFramework.run(); + } + } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 1fb68439afb..efa7ccadfda 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -378,6 +378,26 @@ public class IRNode { beforeMatchingNameRegex(CAST_LL, "CastLL"); } + public static final String CBNZW_HI = PREFIX + "CBNZW_HI" + POSTFIX; + static { + optoOnly(CBNZW_HI, "cbwhi"); + } + + public static final String CBZW_LS = PREFIX + "CBZW_LS" + POSTFIX; + static { + optoOnly(CBZW_LS, "cbwls"); + } + + public static final String CBZ_LS = PREFIX + "CBZ_LS" + POSTFIX; + static { + optoOnly(CBZ_LS, "cbls"); + } + + public static final String CBZ_HI = PREFIX + "CBZ_HI" + POSTFIX; + static { + optoOnly(CBZ_HI, "cbhi"); + } + public static final String CHECKCAST_ARRAY = PREFIX + "CHECKCAST_ARRAY" + POSTFIX; static { String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*:|.*(?i:mov|mv|or).*precise \\[.*:.*\\R.*(cmp|CMP|CLR))" + END; diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index 82d4a398ab6..fc46712bb43 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -31,6 +31,7 @@ import jdk.test.whitebox.WhiteBox; import java.lang.reflect.Method; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -74,7 +75,10 @@ public class IREncodingPrinter { "x86", // corresponds to vm.bits "32-bit", - "64-bit" + "64-bit", + // java.nio.ByteOrder + "little-endian", + "big-endian" )); // Please verify new CPU features before adding them. If we allow non-existent features @@ -359,7 +363,9 @@ private boolean checkPlatform(String platform, String value) { arch = "x86"; } - String currentPlatform = os + " " + arch + " " + (Platform.is32bit() ? "32-bit" : "64-bit"); + String endianess = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN)? "big-endian" : "little-endian"; + + String currentPlatform = os + " " + arch + " " + (Platform.is32bit() ? "32-bit" : "64-bit") + " " + endianess; return (trueValue && currentPlatform.contains(platform)) || (falseValue && !currentPlatform.contains(platform)); } diff --git a/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelAtUnsignedTestsNegativeLimit.java b/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelAtUnsignedTestsNegativeLimit.java new file mode 100644 index 00000000000..7809f79ce9d --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelAtUnsignedTestsNegativeLimit.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * 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 id=Xbatch + * @bug 8332920 + * @summary Tests partial peeling at unsigned tests with limit being negative in exit tests "i >u limit". + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileOnly=*TestPartialPeel*::original*,*TestPartialPeel*::test* + * compiler.loopopts.TestPartialPeelAtUnsignedTestsNegativeLimit + */ + +/* + * @test id=Xcomp-run-inline + * @bug 8332920 + * @summary Tests partial peeling at unsigned tests with limit being negative in exit tests "i >u limit". + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileOnly=*TestPartialPeel*::original*,*TestPartialPeel*::run*,*TestPartialPeel*::test* + * -XX:CompileCommand=inline,*TestPartialPeelAtUnsignedTestsNegativeLimit::test* + * -XX:CompileCommand=dontinline,*TestPartialPeelAtUnsignedTestsNegativeLimit::check + * compiler.loopopts.TestPartialPeelAtUnsignedTestsNegativeLimit + */ + +/* + * @test id=Xcomp-compile-test + * @bug 8332920 + * @summary Tests partial peeling at unsigned tests with limit being negative in exit tests "i >u limit". + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=*TestPartialPeel*::original*,*TestPartialPeel*::test* + * compiler.loopopts.TestPartialPeelAtUnsignedTestsNegativeLimit + */ + +/* + * @test id=vanilla + * @bug 8332920 + * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4) + * @summary Tests partial peeling at unsigned tests with limit being negative in exit tests "i >u limit". + * Only run this test with C2 since it is time-consuming and only tests a C2 issue. + * @run main compiler.loopopts.TestPartialPeelAtUnsignedTestsNegativeLimit + */ + +package compiler.loopopts; + +import java.util.Random; + +import static java.lang.Integer.*; + +public class TestPartialPeelAtUnsignedTestsNegativeLimit { + static int iFld = 10000; + static int iterations = 0; + static int iFld2; + static boolean flag; + final static Random RANDOM = new Random(); + + public static void main(String[] args) { + compareUnsigned(3, 3); // Load Integer class for -Xcomp + for (int i = 0; i < 2; i++) { + if (!originalTest()) { + throw new RuntimeException("originalTest() failed"); + } + } + + for (int i = 0; i < 2000; i++) { + // For profiling + iFld = -1; + originalTestVariation1(); + + // Actual run + iFld = MAX_VALUE - 100_000; + if (!originalTestVariation1()) { + throw new RuntimeException("originalTestVariation1() failed"); + } + } + + for (int i = 0; i < 2000; ++i) { + // For profiling + iFld = MAX_VALUE; + originalTestVariation2(); + + // Actual run + iFld = MIN_VALUE + 100000; + if (!originalTestVariation2()) { + throw new RuntimeException("originalTestVariation2() failed"); + } + } + + runWhileLTIncr(); + runWhileLTDecr(); + } + + // Originally reported simplified regression test with 2 variations (see below). + public static boolean originalTest() { + for (int i = MAX_VALUE - 50_000; compareUnsigned(i, -1) < 0; i++) { + if (compareUnsigned(MIN_VALUE, i) < 0) { + return true; + } + } + return false; + } + + public static boolean originalTestVariation1() { + int a = 0; + for (int i = iFld; compareUnsigned(i, -1) < 0; ++i) { // i <u -1 + + if (i >= Integer.MIN_VALUE + 1 && i <= 100) { // Transformed to unsigned test. + return true; + } + a *= 23; + } + return false; + } + + public static boolean originalTestVariation2() { + int a = 0; + for (int i = iFld; compareUnsigned(i, -1000) < 0; i--) { // i <u -1 + if (compareUnsigned(MAX_VALUE - 20, i) > 0) { + return true; + } + a = i; + } + System.out.println(a); + return false; + } + + + public static void testWhileLTIncr(int init, int limit) { + int i = init; + while (true) { + // <Peeled Section> + + // Found as loop head in ciTypeFlow, but both paths inside loop -> head not cloned. + // As a result, this head has the safepoint as backedge instead of the loop exit test + // and we cannot create a counted loop (yet). We first need to partial peel. + if (flag) { + } + + iFld2++; + + // Loop exit test i >=u limit (i.e. "while (i <u limit)") to partial peel with. + // insert_cmpi_loop_exit() changes this exit condition into a signed and an unsigned test: + // i >= limit && i >=u limit + // where the signed condition can be used as proper loop exit condition for a counted loop + // (we cannot use an unsigned counted loop exit condition). + // + // After Partial Peeling, we have: + // if (i >= limit) goto Exit + // Loop: + // if (i >=u limit) goto Exit + // ... + // i++; + // if (i >= limit) goto Exit + // goto Loop + // Exit: + // ... + // + // If init = MAX_VALUE and limit = MIN_VALUE: + // i >= limit + // MAX_VALUE >= MIN_VALUE + // which is true where + // i >=u limit + // MAX_VALUE >=u MIN_VALUE + // MAX_VALUE >=u (uint)(MAX_INT + 1) + // is false and we wrongly never enter the loop even though we should have. + // This results in a wrong execution. + if (compareUnsigned(i, limit) >= 0) { + return; + } + // <-- Partial Peeling CUT --> + // Safepoint + // <Unpeeled Section> + iterations++; + i++; + } + } + + // Same as testWhileLTIncr() but with decrement instead. + public static void testWhileLTDecr(int init, int limit) { + int i = init; + while (true) { + if (flag) { + } + + // Loop exit test. + if (compareUnsigned(i, limit) >= 0) { // While (i <u limit) + return; + } + + iterations++; + i--; + } + } + + public static void runWhileLTIncr() { + // Currently works: + testWhileLTIncr(MAX_VALUE, -1); + check(MIN_VALUE); // MAX_VALUE + 1 iterations + testWhileLTIncr(-1, 1); + check(0); + testWhileLTIncr(0, 0); + check(0); + checkIncrWithRandom(0, 0); // Sanity check this method. + flag = !flag; // Change profiling + testWhileLTIncr(MAX_VALUE - 2000, MAX_VALUE); + check(2000); + testWhileLTIncr(MAX_VALUE - 1990, MAX_VALUE); + check(1990); + testWhileLTIncr(MAX_VALUE - 1, MAX_VALUE); + check(1); + testWhileLTIncr(MIN_VALUE, MIN_VALUE + 2000); + check(2000); + testWhileLTIncr(MIN_VALUE, MIN_VALUE + 1990); + check(1990); + testWhileLTIncr(MIN_VALUE, MIN_VALUE + 1); + check(1); + + flag = !flag; + // Overflow currently does not work with negative limit and is fixed with patch: + testWhileLTIncr(MAX_VALUE, MIN_VALUE); + check(1); + testWhileLTIncr(MAX_VALUE - 2000, MIN_VALUE); + check(2001); + testWhileLTIncr(MAX_VALUE, MIN_VALUE + 2000); + check(2001); + testWhileLTIncr(MAX_VALUE - 2000, MIN_VALUE + 2000); + check(4001); + + // Random values + int init = RANDOM.nextInt(0, MAX_VALUE); + int limit = RANDOM.nextInt(MIN_VALUE, 0); + testWhileLTIncr(init, limit); + checkIncrWithRandom(init, limit); + } + + public static void runWhileLTDecr() { + // Currently works: + testWhileLTDecr(1, -1); + check(2); + testWhileLTDecr(-1, 1); + check(0); + testWhileLTDecr(0, 0); + check(0); + checkDecrWithRandom(0, 0); // Sanity check this method. + flag = !flag; + testWhileLTDecr(MAX_VALUE, MIN_VALUE); + check(MIN_VALUE); // MAX_VALUE + 1 iterations + testWhileLTDecr(MAX_VALUE, -1); + check(MIN_VALUE); // MAX_VALUE + 1 iterations + testWhileLTDecr(MAX_VALUE, MIN_VALUE); + check(MIN_VALUE); // MAX_VALUE + 1 iterations + testWhileLTDecr(MIN_VALUE, 0); + check(0); + testWhileLTDecr(MIN_VALUE, 1); + check(0); + flag = !flag; + + // Underflow currently does not work with negative limit and is fixed with patch: + testWhileLTDecr(MIN_VALUE, -1); + check(MIN_VALUE + 1); // MAX_VALUE + 2 iterations + testWhileLTDecr(MIN_VALUE, -2000); + check(MIN_VALUE + 1); // MAX_VALUE + 2 iterations + testWhileLTDecr(MIN_VALUE, MIN_VALUE + 1); + check(MIN_VALUE + 1); // MAX_VALUE + 2 iterations + testWhileLTDecr(MIN_VALUE + 2000, -1); + check(MIN_VALUE + 2001); // MAX_VALUE + 2002 iterations + testWhileLTDecr(MIN_VALUE + 2000, -2000); + check(MIN_VALUE + 2001); // MAX_VALUE + 2002 iterations + testWhileLTDecr(MIN_VALUE + 2000, MIN_VALUE + 2001); + check(MIN_VALUE + 2001); // MAX_VALUE + 2002 iterations + + // Random values + int r1 = RANDOM.nextInt(MIN_VALUE, 0); + int r2 = RANDOM.nextInt(MIN_VALUE, 0); + int init = Math.min(r1, r2); + int limit = Math.max(r1, r2); + testWhileLTDecr(init, limit); + checkDecrWithRandom(init, limit); + } + + static void check(int expectedIterations) { + if (expectedIterations != iterations) { + throw new RuntimeException("Expected " + expectedIterations + " iterations but only got " + iterations); + } + iterations = 0; // Reset + } + + static void checkIncrWithRandom(long init, long limit) { + long expectedIterations = ((long)(MAX_VALUE) - init) + (limit - (long)MIN_VALUE) + 1; + if ((int)expectedIterations != iterations) { + String error = "Expected %d iterations but only got %d, init: %d, limit: %d" + .formatted(expectedIterations, iterations, init, limit); + throw new RuntimeException(error); + } + iterations = 0; // Reset + } + + static void checkDecrWithRandom(long init, long limit) { + long expectedIterations = init + MIN_VALUE + MAX_VALUE + 2; + if (init == limit) { + expectedIterations = 0; + } + if ((int)expectedIterations != iterations) { + String error = "Expected %d iterations but only got %d, init: %d, limit: %d" + .formatted(expectedIterations, iterations, init, limit); + throw new RuntimeException(error); + } + iterations = 0; // Reset + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java index 7526d180952..e27feb36e86 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java @@ -30,7 +30,6 @@ * @requires vm.compiler2.enabled * @key randomness * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions - * -XX:CompileCommand=MemLimit,*.*,0 * -XX:LoopUnrollLimit=250 * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* * compiler.loopopts.superword.TestAlignVectorFuzzer @@ -45,7 +44,6 @@ * @requires vm.compiler2.enabled * @key randomness * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions - * -XX:CompileCommand=MemLimit,*.*,0 * -XX:+AlignVector -XX:+VerifyAlignVector * -XX:LoopUnrollLimit=250 * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* @@ -62,7 +60,6 @@ * @requires vm.bits == 64 * @key randomness * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions - * -XX:CompileCommand=MemLimit,*.*,0 * -XX:+AlignVector -XX:+VerifyAlignVector * -XX:LoopUnrollLimit=250 * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* @@ -79,7 +76,6 @@ * @requires vm.compiler2.enabled * @key randomness * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions - * -XX:CompileCommand=MemLimit,*.*,0 * -XX:+AlignVector -XX:+VerifyAlignVector * -XX:LoopUnrollLimit=250 * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java new file mode 100644 index 00000000000..e1aa91369d4 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * 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 compiler.loopopts.superword; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Utils; +import jdk.test.whitebox.WhiteBox; +import java.lang.reflect.Array; +import java.util.Map; +import java.util.HashMap; +import java.util.Random; +import java.nio.ByteOrder; + +/* + * @test + * @bug 8325155 + * @summary Test some cases that vectorize after the removal of the alignment boundaries code. + * Now, we instead check if use-def connections have compatible type size. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestCompatibleUseDefTypeSize + */ + +public class TestCompatibleUseDefTypeSize { + static int RANGE = 1024*8; + private static final Random RANDOM = Utils.getRandomInstance(); + + // Inputs + byte[] aB; + byte[] bB; + short[] aS; + short[] bS; + char[] aC; + char[] bC; + int[] aI; + int[] bI; + long[] aL; + long[] bL; + float[] aF; + float[] bF; + double[] aD; + double[] bD; + + // List of tests + Map<String,TestFunction> tests = new HashMap<String,TestFunction>(); + + // List of gold, the results from the first run before compilation + Map<String,Object[]> golds = new HashMap<String,Object[]>(); + + interface TestFunction { + Object[] run(); + } + + public static void main(String[] args) { + TestFramework.run(); + } + + public TestCompatibleUseDefTypeSize() { + // Generate input once + aB = generateB(); + bB = generateB(); + aS = generateS(); + bS = generateS(); + aC = generateC(); + bC = generateC(); + aI = generateI(); + bI = generateI(); + aL = generateL(); + bL = generateL(); + aF = generateF(); + bF = generateF(); + aD = generateD(); + bD = generateD(); + + // Add all tests to list + tests.put("test0", () -> { return test0(aB.clone(), bC.clone()); }); + tests.put("test1", () -> { return test1(aB.clone(), bC.clone()); }); + tests.put("test2", () -> { return test2(aB.clone(), bC.clone()); }); + tests.put("test3", () -> { return test3(aI.clone(), bI.clone()); }); + tests.put("test4", () -> { return test4(aI.clone(), bI.clone()); }); + tests.put("test5", () -> { return test5(aI.clone(), bF.clone()); }); + tests.put("test6", () -> { return test6(aI.clone(), bF.clone()); }); + tests.put("test7", () -> { return test7(aI.clone(), bF.clone()); }); + tests.put("test8", () -> { return test8(aL.clone(), bD.clone()); }); + tests.put("test9", () -> { return test9(aL.clone(), bD.clone()); }); + tests.put("test10", () -> { return test10(aL.clone(), bD.clone()); }); + tests.put("test11", () -> { return test11(aC.clone()); }); + + // Compute gold value for all test methods before compilation + for (Map.Entry<String,TestFunction> entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + Object[] gold = test.run(); + golds.put(name, gold); + } + } + + @Warmup(100) + @Run(test = {"test0", + "test1", + "test2", + "test3", + "test4", + "test5", + "test6", + "test7", + "test8", + "test9", + "test10", + "test11"}) + public void runTests() { + for (Map.Entry<String,TestFunction> entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + // Recall gold value from before compilation + Object[] gold = golds.get(name); + // Compute new result + Object[] result = test.run(); + // Compare gold and new result + verify(name, gold, result); + } + } + + static byte[] generateB() { + byte[] a = new byte[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = (byte)RANDOM.nextInt(); + } + return a; + } + + static short[] generateS() { + short[] a = new short[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = (short)RANDOM.nextInt(); + } + return a; + } + + static char[] generateC() { + char[] a = new char[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = (char)RANDOM.nextInt(); + } + return a; + } + + static int[] generateI() { + int[] a = new int[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = RANDOM.nextInt(); + } + return a; + } + + static long[] generateL() { + long[] a = new long[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = RANDOM.nextLong(); + } + return a; + } + + static float[] generateF() { + float[] a = new float[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = Float.intBitsToFloat(RANDOM.nextInt()); + } + return a; + } + + static double[] generateD() { + double[] a = new double[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = Double.longBitsToDouble(RANDOM.nextLong()); + } + return a; + } + + static void verify(String name, Object[] gold, Object[] result) { + if (gold.length != result.length) { + throw new RuntimeException("verify " + name + ": not the same number of outputs: gold.length = " + + gold.length + ", result.length = " + result.length); + } + for (int i = 0; i < gold.length; i++) { + Object g = gold[i]; + Object r = result[i]; + if (g.getClass() != r.getClass() || !g.getClass().isArray() || !r.getClass().isArray()) { + throw new RuntimeException("verify " + name + ": must both be array of same type:" + + " gold[" + i + "].getClass() = " + g.getClass().getSimpleName() + + " result[" + i + "].getClass() = " + r.getClass().getSimpleName()); + } + if (g == r) { + throw new RuntimeException("verify " + name + ": should be two separate arrays (with identical content):" + + " gold[" + i + "] == result[" + i + "]"); + } + if (Array.getLength(g) != Array.getLength(r)) { + throw new RuntimeException("verify " + name + ": arrays must have same length:" + + " gold[" + i + "].length = " + Array.getLength(g) + + " result[" + i + "].length = " + Array.getLength(r)); + } + Class c = g.getClass().getComponentType(); + if (c == byte.class) { + verifyB(name, i, (byte[])g, (byte[])r); + } else if (c == short.class) { + verifyS(name, i, (short[])g, (short[])r); + } else if (c == char.class) { + verifyC(name, i, (char[])g, (char[])r); + } else if (c == int.class) { + verifyI(name, i, (int[])g, (int[])r); + } else if (c == long.class) { + verifyL(name, i, (long[])g, (long[])r); + } else if (c == float.class) { + verifyF(name, i, (float[])g, (float[])r); + } else if (c == double.class) { + verifyD(name, i, (double[])g, (double[])r); + } else { + throw new RuntimeException("verify " + name + ": array type not supported for verify:" + + " gold[" + i + "].getClass() = " + g.getClass().getSimpleName() + + " result[" + i + "].getClass() = " + r.getClass().getSimpleName()); + } + } + } + + static void verifyB(String name, int i, byte[] g, byte[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyS(String name, int i, short[] g, short[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyC(String name, int i, char[] g, char[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyI(String name, int i, int[] g, int[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyL(String name, int i, long[] g, long[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyF(String name, int i, float[] g, float[] r) { + for (int j = 0; j < g.length; j++) { + if (Float.floatToIntBits(g[j]) != Float.floatToIntBits(r[j])) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyD(String name, int i, double[] g, double[] r) { + for (int j = 0; j < g.length; j++) { + if (Double.doubleToLongBits(g[j]) != Double.doubleToLongBits(r[j])) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // "inflate" method: 1 byte -> 2 byte. + // Java scalar code has no explicit conversion. + // Vector code would need a conversion. We may add this in the future. + static Object[] test0(byte[] src, char[] dst) { + for (int i = 0; i < src.length; i++) { + dst[i] = (char)(src[i] & 0xff); + } + return new Object[]{ src, dst }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // "inflate" method: 1 byte -> 2 byte. + // Java scalar code has no explicit conversion. + // Vector code would need a conversion. We may add this in the future. + static Object[] test1(byte[] src, char[] dst) { + for (int i = 0; i < src.length; i++) { + dst[i] = (char)(src[i]); + } + return new Object[]{ src, dst }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // "deflate" method: 2 byte -> 1 byte. + // Java scalar code has no explicit conversion. + // Vector code would need a conversion. We may add this in the future. + static Object[] test2(byte[] src, char[] dst) { + for (int i = 0; i < src.length; i++) { + src[i] = (byte)(dst[i]); + } + return new Object[]{ src, dst }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Used to not vectorize because of "alignment boundaries". + // Assume 64 byte vector width: + // a[i+0:i+15] and a[i+1:i+16], each are 4 * 16 = 64 byte. + // The alignment boundary is every 64 byte, so one of the two vectors gets cut up. + static Object[] test3(int[] a, int[] b) { + for (int i = 0; i < a.length-1; i++) { + a[i] = (int)(b[i] + a[i+1]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // same as test3, but hand-unrolled + static Object[] test4(int[] a, int[] b) { + for (int i = 0; i < a.length-2; i+=2) { + a[i+0] = (int)(b[i+0] + a[i+1]); + a[i+1] = (int)(b[i+1] + a[i+2]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // In theory, one would expect this to be a simple 4byte -> 4byte conversion. + // But there is a CmpF and CMove here because we check for isNaN. Plus a MoveF2I. + // + // Would be nice to vectorize: Missing support for CmpF, CMove and MoveF2I. + static Object[] test5(int[] a, float[] b) { + for (int i = 0; i < a.length; i++) { + a[i] = Float.floatToIntBits(b[i]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Missing support for MoveF2I + static Object[] test6(int[] a, float[] b) { + for (int i = 0; i < a.length; i++) { + a[i] = Float.floatToRawIntBits(b[i]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Missing support for MoveI2F + static Object[] test7(int[] a, float[] b) { + for (int i = 0; i < a.length; i++) { + b[i] = Float.intBitsToFloat(a[i]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Missing support for Needs CmpD, CMove and MoveD2L + static Object[] test8(long[] a, double[] b) { + for (int i = 0; i < a.length; i++) { + a[i] = Double.doubleToLongBits(b[i]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Missing support for MoveD2L + static Object[] test9(long[] a, double[] b) { + for (int i = 0; i < a.length; i++) { + a[i] = Double.doubleToRawLongBits(b[i]); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + // Missing support for MoveL2D + static Object[] test10(long[] a, double[] b) { + for (int i = 0; i < a.length; i++) { + b[i] = Double.longBitsToDouble(a[i]); + } + return new Object[]{ a, b }; + } + + @Test + // MaxI reduction is with char type, but the MaxI char vector is not implemented. + static Object[] test11(char[] a) { + char m = 0; + for (int i = 0; i < a.length; i++) { + m = (char)Math.max(m, a[i]); + a[i] = 0; + } + return new Object[]{ a, new char[] { m } }; + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java index 4bc18e9abdb..a872dbc616b 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java @@ -390,9 +390,9 @@ static Object[] test1d(int[] a, int[] b, int mask) { @Test @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "> 0", - IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "= 0", + IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "> 0", IRNode.AND_VI, IRNode.VECTOR_SIZE_2, "> 0", - IRNode.AND_VI, IRNode.VECTOR_SIZE_4, "= 0", + IRNode.AND_VI, IRNode.VECTOR_SIZE_4, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIf = {"MaxVectorSize", ">=32"}, applyIfPlatform = {"64-bit", "true"}, @@ -405,8 +405,6 @@ static Object[] test1d(int[] a, int[] b, int mask) { // | | \ \ \ \ // 0 1 - - 4 5 6 7 // - // The 4-pack does not vectorize. This is a technical limitation that - // we can hopefully soon remove. Load and store offsets are different. static Object[] test2a(int[] a, int[] b, int mask) { for (int i = 0; i < RANGE; i+=8) { int b0 = a[i+0] & mask; @@ -428,9 +426,9 @@ static Object[] test2a(int[] a, int[] b, int mask) { } @Test - @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "= 0", + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "> 0", IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "> 0", - IRNode.AND_VI, IRNode.VECTOR_SIZE_2, "= 0", + IRNode.AND_VI, IRNode.VECTOR_SIZE_2, "> 0", IRNode.AND_VI, IRNode.VECTOR_SIZE_4, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIf = {"MaxVectorSize", ">=32"}, @@ -444,8 +442,6 @@ static Object[] test2a(int[] a, int[] b, int mask) { // | | | | \ \ // 0 1 2 3 -- 6 7 // - // The 2-pack does not vectorize. This is a technical limitation that - // we can hopefully soon remove. Load and store offsets are different. static Object[] test2b(int[] a, int[] b, int mask) { for (int i = 0; i < RANGE; i+=8) { int b0 = a[i+0] & mask; @@ -468,9 +464,9 @@ static Object[] test2b(int[] a, int[] b, int mask) { @Test @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "> 0", - IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "= 0", + IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "> 0", IRNode.AND_VI, IRNode.VECTOR_SIZE_2, "> 0", - IRNode.AND_VI, IRNode.VECTOR_SIZE_4, "= 0", + IRNode.AND_VI, IRNode.VECTOR_SIZE_4, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIf = {"MaxVectorSize", ">=32"}, applyIfPlatform = {"64-bit", "true"}, @@ -483,8 +479,6 @@ static Object[] test2b(int[] a, int[] b, int mask) { // | | / / / / // 0 1 2 3 4 5 - - // - // The 4-pack does not vectorize. This is a technical limitation that - // we can hopefully soon remove. Load and store offsets are different. static Object[] test2c(int[] a, int[] b, int mask) { for (int i = 0; i < RANGE; i+=8) { int b0 = a[i+0] & mask; @@ -506,9 +500,9 @@ static Object[] test2c(int[] a, int[] b, int mask) { } @Test - @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "= 0", + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "> 0", IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "> 0", - IRNode.AND_VI, IRNode.VECTOR_SIZE_2, "= 0", + IRNode.AND_VI, IRNode.VECTOR_SIZE_2, "> 0", IRNode.AND_VI, IRNode.VECTOR_SIZE_4, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIf = {"MaxVectorSize", ">=32"}, @@ -522,8 +516,6 @@ static Object[] test2c(int[] a, int[] b, int mask) { // | | | | / / // 0 1 2 3 4 5 - - // - // The 2-pack does not vectorize. This is a technical limitation that - // we can hopefully soon remove. Load and store offsets are different. static Object[] test2d(int[] a, int[] b, int mask) { for (int i = 0; i < RANGE; i+=8) { int b0 = a[i+0] & mask; diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestVectorFPReduction.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestVectorFPReduction.java new file mode 100644 index 00000000000..327e6e5e12d --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestVectorFPReduction.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024, Arm Limited. All rights reserved. + * 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 compiler.loopopts.superword; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8320725 + * @summary Ensure strictly ordered AddReductionVF/VD and MulReductionVF/VD nodes + are generated when these operations are auto-vectorized + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestVectorFPReduction + */ + +public class TestVectorFPReduction { + + final private static int SIZE = 1024; + + private static double[] da = new double[SIZE]; + private static double[] db = new double[SIZE]; + private static float[] fa = new float[SIZE]; + private static float[] fb = new float[SIZE]; + private static float fresult; + private static double dresult; + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @IR(failOn = {IRNode.ADD_REDUCTION_VF}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + @IR(counts = {"requires_strict_order", ">=1", IRNode.ADD_REDUCTION_VF, ">=1"}, + failOn = {"no_strict_order"}, + applyIfCPUFeatureOr = {"sve", "true", "sse2", "true"}, + phase = CompilePhase.PRINT_IDEAL) + private static void testAddReductionVF() { + float result = 1; + for (int i = 0; i < SIZE; i++) { + result += (fa[i] + fb[i]); + } + fresult += result; + } + + @Test + @IR(failOn = {IRNode.ADD_REDUCTION_VD}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + @IR(counts = {"requires_strict_order", ">=1", IRNode.ADD_REDUCTION_VD, ">=1"}, + failOn = {"no_strict_order"}, + applyIfCPUFeatureOr = {"sve", "true", "sse2", "true"}, + phase = CompilePhase.PRINT_IDEAL) + private static void testAddReductionVD() { + double result = 1; + for (int i = 0; i < SIZE; i++) { + result += (da[i] + db[i]); + } + dresult += result; + } + + @Test + @IR(failOn = {IRNode.MUL_REDUCTION_VF}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + @IR(counts = {"requires_strict_order", ">=1", IRNode.MUL_REDUCTION_VF, ">=1"}, + failOn = {"no_strict_order"}, + applyIfCPUFeatureOr = {"sve", "true", "sse2", "true"}, + phase = CompilePhase.PRINT_IDEAL) + private static void testMulReductionVF() { + float result = 1; + for (int i = 0; i < SIZE; i++) { + result *= (fa[i] + fb[i]); + } + fresult += result; + } + + @Test + @IR(failOn = {IRNode.MUL_REDUCTION_VD}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + @IR(counts = {"requires_strict_order", ">=1", IRNode.MUL_REDUCTION_VD, ">=1"}, + failOn = {"no_strict_order"}, + applyIfCPUFeatureOr = {"sve", "true", "sse2", "true"}, + phase = CompilePhase.PRINT_IDEAL) + private static void testMulReductionVD() { + double result = 1; + for (int i = 0; i < SIZE; i++) { + result *= (da[i] + db[i]); + } + dresult += result; + } +} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java b/test/hotspot/jtreg/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java deleted file mode 100644 index ffe510a0f32..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.Platform; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.function.BooleanSupplier; - -/** - * Base for all RTM-related CLI tests. - */ -public abstract class RTMGenericCommandLineOptionTest { - - protected static final String RTM_INSTR_ERROR - = "RTM instructions are not available on this CPU"; - protected static final String RTM_UNSUPPORTED_VM_ERROR - = "RTM locking optimization is not supported in this VM"; - protected static final String RTM_FOR_STACK_LOCKS_WARNING - = "UseRTMForStackLocks flag should be off when UseRTMLocking " - + "flag is off"; - protected static final String RTM_COUNT_INCR_WARNING - = "must be a power of 2, resetting it to 64"; - - protected final String optionName; - protected final String errorMessage; - protected final String experimentalOptionError; - protected final boolean isExperimental; - protected final boolean isBoolean; - protected final String defaultValue; - protected final String[] optionValues; - - /** - * Constructs new genetic RTM CLI test, for option {@code optionName} which - * has default value {@code defaultValue}. Test cases will use option's - * values passed via {@code optionValues} for verification of correct - * option processing. - * - * Test constructed using this ctor will be started on any cpu regardless - * it's architecture and supported/unsupported features. - * - * @param optionName name of option to be tested - * @param isBoolean {@code true} if option is binary - * @param isExperimental {@code true} if option is experimental - * @param defaultValue default value of tested option - * @param optionValues different option values - */ - public RTMGenericCommandLineOptionTest( - String optionName, boolean isBoolean, boolean isExperimental, - String defaultValue, String... optionValues) { - this.optionName = optionName; - this.isExperimental = isExperimental; - this.isBoolean = isBoolean; - this.defaultValue = defaultValue; - this.optionValues = optionValues; - this.errorMessage = CommandLineOptionTest. - getUnrecognizedOptionErrorMessage(optionName); - this.experimentalOptionError = CommandLineOptionTest. - getExperimentalOptionErrorMessage(optionName); - } - - public void runTestCases() throws Throwable { - if (Platform.isX86() || Platform.isX64()) { - if (Platform.isServer()) { - runX86SupportedVMTestCases(); - } else { - runX86UnsupportedVMTestCases(); - } - } else { - runNonX86TestCases(); - } - } - - /** - * Runs test cases on X86 CPU if VM supports RTM locking. - * @throws Throwable - */ - protected void runX86SupportedVMTestCases() throws Throwable { - runGenericX86TestCases(); - } - - /** - * Runs test cases on X86 CPU if VM does not support RTM locking. - * @throws Throwable - */ - protected void runX86UnsupportedVMTestCases() throws Throwable { - runGenericX86TestCases(); - } - - /** - * Runs test cases on non-X86 CPU. - * @throws Throwable - */ - protected void runNonX86TestCases() throws Throwable { - CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, - String.format("Option '%s' should be unknown on non-X86CPUs.%n" - + "JVM startup should fail", optionName), "", ExitCode.FAIL, - prepareOptionValue(defaultValue)); - } - - /** - * Runs generic X86 test cases. - * @throws Throwable - */ - protected void runGenericX86TestCases() throws Throwable { - verifyJVMStartup(); - verifyOptionValues(); - } - - protected void verifyJVMStartup() throws Throwable { - String optionValue = prepareOptionValue(defaultValue); - String shouldFailMessage = String.format("VM option '%s' is " - + "experimental.%nVM startup expected to fail without " - + "-XX:+UnlockExperimentalVMOptions option", optionName); - String shouldPassMessage = String.format("VM option '%s' is " - + "experimental%nVM startup should pass with " - + "-XX:+UnlockExperimentalVMOptions option", optionName); - if (isExperimental) { - // verify that option is experimental - CommandLineOptionTest.verifySameJVMStartup( - new String[] { experimentalOptionError }, - new String[] { errorMessage }, shouldFailMessage, - shouldFailMessage, ExitCode.FAIL, optionValue); - // verify that it could be passed if experimental options - // are unlocked - CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { - experimentalOptionError, - errorMessage - }, - shouldPassMessage, - "JVM should start without any warnings or errors", - ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - optionValue); - } else { - // verify that option could be passed - CommandLineOptionTest.verifySameJVMStartup(null, - new String[]{errorMessage}, - String.format("VM startup shuld pass with '%s' option", - optionName), - "JVM should start without any warnings or errors", - ExitCode.OK, optionValue); - } - } - - protected void verifyOptionValues() throws Throwable { - // verify default value - if (isExperimental) { - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue, - String.format("Option '%s' is expected to have '%s' " - + "default value", optionName, defaultValue), - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - } else { - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue, - String.format("Option '%s' is expected to have '%s' " - + "default value", optionName, defaultValue)); - } - // verify other specified option values - if (optionValues == null) { - return; - } - - for (String value : optionValues) { - if (isExperimental) { - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - value, - String.format("Option '%s' is set to have '%s' value", - optionName, value), - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - prepareOptionValue(value)); - } else { - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - value, - String.format("Option '%s' is set to have '%s' value", - optionName, value), prepareOptionValue(value)); - } - } - } - - protected String prepareOptionValue(String value) { - if (isBoolean) { - return CommandLineOptionTest.prepareBooleanFlag(optionName, - Boolean.valueOf(value)); - } else { - return String.format("-XX:%s=%s", optionName, value); - } - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/RTMLockingAwareTest.java b/test/hotspot/jtreg/compiler/rtm/cli/RTMLockingAwareTest.java deleted file mode 100644 index 394d73e2283..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/RTMLockingAwareTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2014, 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 compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.LinkedList; -import java.util.List; - -/** - * Base for all RTM-related CLI tests on options whose processing depends - * on UseRTMLocking value. - * - * Since UseRTMLocking option could be used when both CPU and VM supports RTM - * locking, this test will be skipped on all unsupported configurations. - */ -public abstract class RTMLockingAwareTest - extends RTMGenericCommandLineOptionTest { - protected final String warningMessage; - protected final String[] correctValues; - protected final String[] incorrectValues; - /** - * Constructs new test for option {@code optionName} that should be executed - * only on CPU with RTM support. - * Test will be executed using set of correct values from - * {@code correctValues} and set of incorrect values from - * {@code incorrectValues}. - * - * @param optionName name of option to be tested - * @param isBoolean {@code true} if tested option is binary - * @param isExperimental {@code true} if tested option is experimental - * @param defaultValue default value of tested option - * @param correctValues array with correct values, that should not emit - * {@code warningMessage} to VM output - * @param incorrectValues array with incorrect values, that should emit - * {@code waningMessage} to VM output - * @param warningMessage warning message associated with tested option - */ - protected RTMLockingAwareTest(String optionName, boolean isBoolean, - boolean isExperimental, String defaultValue, - String[] correctValues, String[] incorrectValues, - String warningMessage) { - super(optionName, isBoolean, isExperimental, defaultValue); - this.correctValues = correctValues; - this.incorrectValues = incorrectValues; - this.warningMessage = warningMessage; - } - - @Override - protected void verifyJVMStartup() throws Throwable { - // Run generic sanity checks - super.verifyJVMStartup(); - // Verify how option values will be processed depending on - // UseRTMLocking value. - if (correctValues != null) { - for (String correctValue : correctValues) { - // For correct values it is expected to see no warnings - // regardless to UseRTMLocking - verifyStartupWarning(correctValue, true, false); - verifyStartupWarning(correctValue, false, false); - } - } - - if (incorrectValues != null) { - for (String incorrectValue : incorrectValues) { - // For incorrect values it is expected to see warning - // only with -XX:+UseRTMLocking - verifyStartupWarning(incorrectValue, true, true); - verifyStartupWarning(incorrectValue, false, false); - } - } - } - - @Override - protected void verifyOptionValues() throws Throwable { - super.verifyOptionValues(); - // Verify how option values will be setup after processing - // depending on UseRTMLocking value - if (correctValues != null) { - for (String correctValue : correctValues) { - // Correct value could be set up regardless to UseRTMLocking - verifyOptionValues(correctValue, false, correctValue); - verifyOptionValues(correctValue, true, correctValue); - } - } - - if (incorrectValues != null) { - for (String incorrectValue : incorrectValues) { - // With -XX:+UseRTMLocking, incorrect value will be changed to - // default value. - verifyOptionValues(incorrectValue, false, incorrectValue); - verifyOptionValues(incorrectValue, true, defaultValue); - } - } - } - - private void verifyStartupWarning(String value, boolean useRTMLocking, - boolean isWarningExpected) throws Throwable { - String warnings[] = new String[] { warningMessage }; - List<String> options = new LinkedList<>(); - options.add(CommandLineOptionTest.prepareBooleanFlag("UseRTMLocking", - useRTMLocking)); - - if (isExperimental) { - options.add(CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - } - options.add(prepareOptionValue(value)); - - String errorString = String.format("JVM should start with option '%s'" - + "'%nWarnings should be shown: %s", optionName, - isWarningExpected); - CommandLineOptionTest.verifySameJVMStartup( - (isWarningExpected ? warnings : null), - (isWarningExpected ? null : warnings), - errorString, errorString, ExitCode.OK, - options.toArray(new String[options.size()])); - } - - private void verifyOptionValues(String value, boolean useRTMLocking, - String expectedValue) throws Throwable { - List<String> options = new LinkedList<>(); - options.add(CommandLineOptionTest.prepareBooleanFlag("UseRTMLocking", - useRTMLocking)); - - if (isExperimental) { - options.add(CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - } - options.add(prepareOptionValue(value)); - - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - expectedValue, String.format("Option '%s' should have '%s' " - + "value if '%s' flag set", - optionName, expectedValue, prepareOptionValue(value)), - options.toArray(new String[options.size()])); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java deleted file mode 100644 index 8cf31499047..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2014, 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 compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.Platform; -import jdk.test.lib.cli.CommandLineOptionTest; - -public abstract class TestPrintPreciseRTMLockingStatisticsBase - extends RTMGenericCommandLineOptionTest { - protected static final String DEFAULT_VALUE = "false"; - - protected TestPrintPreciseRTMLockingStatisticsBase() { - super("PrintPreciseRTMLockingStatistics", true, false, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE); - } - - @Override - protected void runNonX86TestCases() throws Throwable { - verifyJVMStartup(); - verifyOptionValues(); - } - - @Override - protected void verifyJVMStartup() throws Throwable { - if (Platform.isServer()) { - if (!Platform.isDebugBuild()) { - String shouldFailMessage = String.format("VM option '%s' is " - + "diagnostic%nJVM startup should fail without " - + "-XX:\\+UnlockDiagnosticVMOptions flag", optionName); - String shouldPassMessage = String.format("VM option '%s' is " - + "diagnostic%nJVM startup should pass with " - + "-XX:\\+UnlockDiagnosticVMOptions in debug build", - optionName); - String errorMessage = CommandLineOptionTest. - getDiagnosticOptionErrorMessage(optionName); - // verify that option is actually diagnostic - CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, shouldFailMessage, - shouldFailMessage, ExitCode.FAIL, - prepareOptionValue("true")); - - CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { errorMessage }, shouldPassMessage, - shouldPassMessage + "without any warnings", ExitCode.OK, - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - prepareOptionValue("true")); - } else { - String shouldPassMessage = String.format("JVM startup should " - + "pass with '%s' option in debug build", - optionName); - CommandLineOptionTest.verifySameJVMStartup(null, null, - shouldPassMessage, shouldPassMessage, - ExitCode.OK, prepareOptionValue("true")); - } - } else { - String errorMessage = CommandLineOptionTest. - getUnrecognizedOptionErrorMessage(optionName); - String shouldFailMessage = String.format("JVM startup should fail" - + " with '%s' option in not debug build", optionName); - CommandLineOptionTest.verifySameJVMStartup( - new String[]{errorMessage}, null, shouldFailMessage, - shouldFailMessage, ExitCode.FAIL, - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - prepareOptionValue("true")); - } - } - - @Override - protected void verifyOptionValues() throws Throwable { - if (Platform.isServer()) { - // Verify default value - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, - String.format("Option '%s' should have '%s' default value", - optionName, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE), - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS); - } - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java deleted file mode 100644 index b4a71cd21b6..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify PrintPreciseRTMLockingStatistics on CPUs and OSs with - * rtm support and on VM with rtm locking support, - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig - */ - -package compiler.rtm.cli; - -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig - extends TestPrintPreciseRTMLockingStatisticsBase { - - @Override - protected void verifyOptionValues() throws Throwable { - super.verifyOptionValues(); - // verify default value - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, - String.format("Option '%s' should have '%s' default value on" - + " supported CPU", optionName, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE), - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking"); - - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, - String.format("Option '%s' should have '%s' default value on" - + " supported CPU when -XX:-UseRTMLocking flag set", - optionName, - TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE), - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:-UseRTMLocking", prepareOptionValue("true")); - - // verify that option could be turned on - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", - String.format("Option '%s' should have 'true' value when set " - + "on supported CPU and -XX:+UseRTMLocking flag set", - optionName), - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking", prepareOptionValue("true")); - } - - public static void main(String args[]) throws Throwable { - new TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig() - .runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java deleted file mode 100644 index 274c3353637..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify PrintPreciseRTMLockingStatistics on CPUs or OSs without - * rtm support and/or unsupported VM. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires !vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig - */ - -package compiler.rtm.cli; - -public class TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig - extends TestPrintPreciseRTMLockingStatisticsBase { - - public static void main(String args[]) throws Throwable { - new TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig() - .runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java deleted file mode 100644 index 54690fec691..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify processing of RTMAbortThreshold option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.compiler - * @run driver compiler.rtm.cli.TestRTMAbortThresholdOption - */ - -package compiler.rtm.cli; - -public class TestRTMAbortThresholdOption - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "1000"; - - private TestRTMAbortThresholdOption() { - super("RTMAbortThreshold", false, true, - TestRTMAbortThresholdOption.DEFAULT_VALUE, - "0", "42", "100", "10000"); - } - - public static void main(String args[]) throws Throwable { - new TestRTMAbortThresholdOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java deleted file mode 100644 index bc6185f62b0..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify processing of RTMLockingCalculationDelay option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.compiler - * @run driver compiler.rtm.cli.TestRTMLockingCalculationDelayOption - */ - -package compiler.rtm.cli; - -public class TestRTMLockingCalculationDelayOption - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "0"; - - private TestRTMLockingCalculationDelayOption() { - super("RTMLockingCalculationDelay", false, - true, TestRTMLockingCalculationDelayOption.DEFAULT_VALUE); - } - - public static void main(String agrs[]) throws Throwable { - new TestRTMLockingCalculationDelayOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java deleted file mode 100644 index 0eb0cc24dc4..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify processing of RTMLockingThreshold option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.compiler - * @run driver compiler.rtm.cli.TestRTMLockingThresholdOption - */ - -package compiler.rtm.cli; - -public class TestRTMLockingThresholdOption - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "10000"; - - private TestRTMLockingThresholdOption() { - super("RTMLockingThreshold", false, true, - TestRTMLockingThresholdOption.DEFAULT_VALUE); - } - - public static void main(String args[]) throws Throwable { - new TestRTMLockingThresholdOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java deleted file mode 100644 index 79e32af0e52..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify processing of RTMRetryCount option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.compiler - * @run driver compiler.rtm.cli.TestRTMRetryCountOption - */ - -package compiler.rtm.cli; - -public class TestRTMRetryCountOption extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "5"; - - private TestRTMRetryCountOption() { - super("RTMRetryCount", false, false, - TestRTMRetryCountOption.DEFAULT_VALUE, - "0", "10", "100", "1000"); - } - - public static void main(String args[]) throws Throwable { - new TestRTMRetryCountOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java deleted file mode 100644 index e138b3372ff..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify processing of RTMSpinLoopCount option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.compiler - * @run driver compiler.rtm.cli.TestRTMSpinLoopCountOption - */ - -package compiler.rtm.cli; - -public class TestRTMSpinLoopCountOption - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "100"; - - private TestRTMSpinLoopCountOption() { - super("RTMSpinLoopCount", false, true, - TestRTMSpinLoopCountOption.DEFAULT_VALUE, - "0", "10", "42", "1000"); - } - - public static void main(String args[]) throws Throwable { - new TestRTMSpinLoopCountOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java deleted file mode 100644 index 929838dad06..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify RTMTotalCountIncrRate option processing on CPU and OS with - * rtm support and on VM with rtm locking support. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestRTMTotalCountIncrRateOptionOnSupportedConfig - */ - -package compiler.rtm.cli; - -public class TestRTMTotalCountIncrRateOptionOnSupportedConfig - extends RTMLockingAwareTest { - private static final String DEFAULT_VALUE = "64"; - - private TestRTMTotalCountIncrRateOptionOnSupportedConfig() { - super("RTMTotalCountIncrRate", false, true, - TestRTMTotalCountIncrRateOptionOnSupportedConfig.DEFAULT_VALUE, - /* correct values */ - new String[] { "1", "2", "128", "1024" }, - /* incorrect values */ - new String[] { "3", "5", "7", "42" }, - RTMGenericCommandLineOptionTest.RTM_COUNT_INCR_WARNING); - } - - public static void main(String args[]) throws Throwable { - new TestRTMTotalCountIncrRateOptionOnSupportedConfig().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java deleted file mode 100644 index cc9f93165d0..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMDeopt option processing on CPUs with rtm support - * when rtm locking is supported by VM. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMDeoptOptionOnSupportedConfig - */ - -package compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMDeoptOptionOnSupportedConfig { - private static final String DEFAULT_VALUE = "false"; - - public void runTestCases() throws Throwable { - String shouldPassMessage = " JVM should startup with option '" - + "-XX:+UseRTMDeopt' without any warnings"; - // verify that option could be turned on - CommandLineOptionTest.verifySameJVMStartup( - null, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, - "-XX:+UseRTMDeopt"); - shouldPassMessage = " JVM should startup with option '" - + "-XX:-UseRTMDeopt' without any warnings"; - // verify that option could be turned off - CommandLineOptionTest.verifySameJVMStartup( - null, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, - "-XX:-UseRTMDeopt"); - String defValMessage = String.format("UseRTMDeopt should have '%s'" - + "default value", - TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE); - // verify default value - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", - TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, - defValMessage); - // verify default value - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", - TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, - defValMessage, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking"); - // verify that option is off when UseRTMLocking is off - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", - "false", "UseRTMDeopt should be off when UseRTMLocking is off", - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:-UseRTMLocking", "-XX:+UseRTMDeopt"); - // verify that option could be turned on - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "true", - "UseRTMDeopt should be on when UseRTMLocking is on and " - + "'-XX:+UseRTMDeopt' flag set", - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking", "-XX:+UseRTMDeopt"); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMDeoptOptionOnSupportedConfig().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java deleted file mode 100644 index b018e8d078f..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMDeopt option processing on CPUs or OSs without rtm support - * or on VMs without rtm locking support. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires !vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMDeoptOptionOnUnsupportedConfig - */ - -package compiler.rtm.cli; - -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMDeoptOptionOnUnsupportedConfig - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "false"; - - private TestUseRTMDeoptOptionOnUnsupportedConfig() { - super("UseRTMDeopt", true, false, - TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, - "true"); - } - - @Override - protected void runX86SupportedVMTestCases() throws Throwable { - super.verifyJVMStartup(); - // verify default value - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue, String.format("'%s' should have '%s' " - + "default value on unsupported configs.", - optionName, DEFAULT_VALUE)); - // verify that until RTMLocking is not used, value - // will be set to default false. - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue, String.format("'%s' should be off on unsupported" - + " configs even if '-XX:+%s' flag set", optionName, - optionName), - "-XX:+UseRTMDeopt"); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMDeoptOptionOnUnsupportedConfig().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java deleted file mode 100644 index 37d8a6bcaaa..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMForStackLocks option processing on CPU and OS with - * rtm support when VM supports rtm locking. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMForStackLocksOptionOnSupportedConfig - */ - -package compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMForStackLocksOptionOnSupportedConfig { - private static final String DEFAULT_VALUE = "false"; - - public void runTestCases() throws Throwable { - String errorMessage - = CommandLineOptionTest.getExperimentalOptionErrorMessage( - "UseRTMForStackLocks"); - String warningMessage - = RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING; - - String shouldFailMessage = " VM option 'UseRTMForStackLocks' is " - + "experimental%nJVM startup should fail without " - + "-XX:+UnlockExperimentalVMOptions flag"; - - CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, shouldFailMessage, - shouldFailMessage + "%nError message expected", ExitCode.FAIL, - "-XX:+UseRTMForStackLocks"); - String shouldPassMessage = " VM option 'UseRTMForStackLocks'" - + " is experimental%nJVM startup should pass with " - + "-XX:+UnlockExperimentalVMOptions flag"; - // verify that we get a warning when trying to use rtm for stack - // lock, but not using rtm locking. - CommandLineOptionTest.verifySameJVMStartup( - new String[] { warningMessage }, null, shouldPassMessage, - "There should be warning when trying to use rtm for stack " - + "lock, but not using rtm locking", ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMForStackLocks", - "-XX:-UseRTMLocking"); - // verify that we don't get a warning when no using rtm for stack - // lock and not using rtm locking. - CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, shouldPassMessage, - "There should not be any warning when use both " - + "-XX:-UseRTMForStackLocks and -XX:-UseRTMLocking " - + "flags", - ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:-UseRTMForStackLocks", - "-XX:-UseRTMLocking"); - // verify that we don't get a warning when using rtm for stack - // lock and using rtm locking. - CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, shouldPassMessage, - "There should not be any warning when use both " - + "-XX:+UseRTMForStackLocks and -XX:+UseRTMLocking" - + " flags", - ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMForStackLocks", - "-XX:+UseRTMLocking"); - // verify that default value if false - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", - TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, - "Default value of option 'UseRTMForStackLocks' should be false", - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - // verify that default value is false even with +UseRTMLocking - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", - TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, - "Default value of option 'UseRTMForStackLocks' should be false", - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking"); - // verify that we can turn the option on - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", - "true", "Value of option 'UseRTMForStackLocks' should " - + "be able to be set as 'true' when both " - + "-XX:+UseRTMForStackLocks and " - + "-XX:+UseRTMLocking flags used", - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking", "-XX:+UseRTMForStackLocks"); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMForStackLocksOptionOnSupportedConfig().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java deleted file mode 100644 index 13159dbd895..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMForStackLocks option processing on CPUs or OSs without - * rtm support and/or on VMs without rtm locking support. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires !vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMForStackLocksOptionOnUnsupportedConfig - */ - -package compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMForStackLocksOptionOnUnsupportedConfig - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "false"; - - private TestUseRTMForStackLocksOptionOnUnsupportedConfig() { - super("UseRTMForStackLocks", true, true, - TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, - "true"); - } - - @Override - protected void runX86SupportedVMTestCases() throws Throwable { - String shouldFailMessage = String.format("VM option '%s' is " - + "experimental%nJVM startup should fail without " - + "-XX:+UnlockExperimentalVMOptions flag", optionName); - - // verify that option is experimental - CommandLineOptionTest.verifySameJVMStartup( - new String[] { experimentalOptionError }, null, - shouldFailMessage, shouldFailMessage + "%nError message " - + "should be shown", ExitCode.FAIL, - prepareOptionValue("true")); - - CommandLineOptionTest.verifySameJVMStartup( - new String[]{ experimentalOptionError }, null, - shouldFailMessage, shouldFailMessage + "%nError message " - + "should be shown", ExitCode.FAIL, - prepareOptionValue("false")); - - String shouldPassMessage = String.format("VM option '%s' is " - + " experimental%nJVM startup should pass with " - + "-XX:+UnlockExperimentalVMOptions flag", optionName); - // verify that if we turn it on, then VM output will contain - // warning saying that this option could be turned on only - // when we use rtm locking - CommandLineOptionTest.verifySameJVMStartup( - new String[]{ - RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING - }, null, shouldPassMessage, "There should be warning when try " - + "to use rtm for stack lock, but not using rtm locking", - ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - prepareOptionValue("true") - ); - // verify that options is turned off by default - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, - String.format("Default value of option '%s' should be '%s'", - optionName, DEFAULT_VALUE), - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - // verify that it could not be turned on without rtm locking - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, - String.format("Value of '%s' shouldn't able to be set to " - + "'true' without setting -XX:+UseRTMLocking flag", - optionName), - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - prepareOptionValue("true")); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMForStackLocksOptionOnUnsupportedConfig().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java deleted file mode 100644 index ff0a7623da0..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMLocking option processing on CPU and OS with rtm support and - * on VM with rtm locking support. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMLockingOptionOnSupportedConfig - */ - -package compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMLockingOptionOnSupportedConfig { - private static final String DEFAULT_VALUE = "false"; - - public void runTestCases() throws Throwable { - String unrecongnizedOption - = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( - "UseRTMLocking"); - String shouldPassMessage = "VM option 'UseRTMLocking' is experimental" - + "%nJVM startup should pass with " - + "-XX:+UnlockExperimentalVMOptions flag"; - // verify that there are no warning or error in VM output - CommandLineOptionTest.verifySameJVMStartup(null, - new String[]{ - RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, - unrecongnizedOption - }, shouldPassMessage, "There should not be any warning when use" - + "with -XX:+UnlockExperimentalVMOptions", ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking" - ); - - CommandLineOptionTest.verifySameJVMStartup(null, - new String[]{ - RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, - unrecongnizedOption - }, shouldPassMessage, "There should not be any warning when use" - + "with -XX:+UnlockExperimentalVMOptions", ExitCode.OK, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:-UseRTMLocking" - ); - // verify that UseRTMLocking is of by default - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, - String.format("Default value of option 'UseRTMLocking' should " - + "be '%s'", DEFAULT_VALUE), - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - // verify that we can change UseRTMLocking value - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, - String.format("Default value of option 'UseRTMLocking' should " - + "be '%s'", DEFAULT_VALUE), - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:-UseRTMLocking"); - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - "true", "Value of 'UseRTMLocking' should be set " - + "to 'true' if -XX:+UseRTMLocking flag set", - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking"); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMLockingOptionOnSupportedConfig().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java deleted file mode 100644 index 973c5cccbd9..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMLocking option processing on CPUs without - * rtm support. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires !vm.rtm.cpu & vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMLockingOptionOnUnsupportedCPU - */ - -package compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.Platform; -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMLockingOptionOnUnsupportedCPU { - private static final String DEFAULT_VALUE = "false"; - - public void runTestCases() throws Throwable { - String unrecognizedOption - = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( - "UseRTMLocking"); - String errorMessage = RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR; - - if (Platform.isX86() || Platform.isX64()) { - String shouldFailMessage = "JVM startup should fail with option " + - "-XX:+UseRTMLocking on unsupported CPU"; - - // verify that we get an error when use +UseRTMLocking - // on unsupported CPU - CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, - new String[] { unrecognizedOption }, shouldFailMessage, - shouldFailMessage + ". Error message should be shown.", - ExitCode.FAIL, "-XX:+UseRTMLocking"); - - String shouldPassMessage = "JVM startup should pass with option " - + "-XX:-UseRTMLocking even on unsupported CPU"; - // verify that we can pass -UseRTMLocking without - // getting any error messages - CommandLineOptionTest.verifySameJVMStartup(null, new String[] { - errorMessage, unrecognizedOption }, shouldPassMessage, - shouldPassMessage + " without any warnings", ExitCode.OK, - "-XX:-UseRTMLocking"); - - // verify that UseRTMLocking is false by default - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE, - String.format("Default value of option 'UseRTMLocking' " - +"should be '%s'", DEFAULT_VALUE)); - } else { - String shouldFailMessage = "RTMLocking should be unrecognized" - + " on non-x86 CPUs. JVM startup should fail." - + "Error message should be shown"; - // verify that on non-x86 CPUs RTMLocking could not be used - CommandLineOptionTest.verifySameJVMStartup( - new String[] { unrecognizedOption }, - null, shouldFailMessage, shouldFailMessage, - ExitCode.FAIL, "-XX:+UseRTMLocking"); - - CommandLineOptionTest.verifySameJVMStartup( - new String[] { unrecognizedOption }, - null, shouldFailMessage, shouldFailMessage, - ExitCode.FAIL, "-XX:-UseRTMLocking"); - } - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMLockingOptionOnUnsupportedCPU().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java deleted file mode 100644 index a26b8ffbad5..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify UseRTMLocking option processing on CPU with rtm support - * in case when VM should not support this option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.cpu & !(vm.flavor == "server" & !vm.emulatedClient) - * @run driver compiler.rtm.cli.TestUseRTMLockingOptionOnUnsupportedVM - */ - -package compiler.rtm.cli; - -import jdk.test.lib.process.ExitCode; -import jdk.test.lib.cli.CommandLineOptionTest; - -public class TestUseRTMLockingOptionOnUnsupportedVM { - private static final String DEFAULT_VALUE = "false"; - - public void runTestCases() throws Throwable { - String errorMessage - = RTMGenericCommandLineOptionTest.RTM_UNSUPPORTED_VM_ERROR; - String shouldFailMessage = "JVM startup should fail with option " - + "-XX:+UseRTMLocking even on unsupported VM. Error message" - + " should be shown"; - String shouldPassMessage = "JVM startup should pass with option " - + "-XX:-UseRTMLocking even on unsupported VM"; - // verify that we can't use +UseRTMLocking - CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, shouldFailMessage, - shouldFailMessage, ExitCode.FAIL, - "-XX:+UseRTMLocking"); - // verify that we can turn it off - CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { errorMessage }, shouldPassMessage, - shouldPassMessage + " without any warnings", ExitCode.OK, - "-XX:-UseRTMLocking"); - // verify that it is off by default - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE, - String.format("Default value of option 'UseRTMLocking' should" - + " be '%s'", DEFAULT_VALUE)); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMLockingOptionOnUnsupportedVM().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java deleted file mode 100644 index d38bf0a7f2b..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify processing of UseRTMXendForLockBusy option. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.flagless - * @requires vm.rtm.compiler - * @run driver compiler.rtm.cli.TestUseRTMXendForLockBusyOption - */ - -package compiler.rtm.cli; - -public class TestUseRTMXendForLockBusyOption - extends RTMGenericCommandLineOptionTest { - private static final String DEFAULT_VALUE = "true"; - - public TestUseRTMXendForLockBusyOption() { - super("UseRTMXendForLockBusy", true, true, - TestUseRTMXendForLockBusyOption.DEFAULT_VALUE, "true"); - } - - public static void main(String agrs[]) throws Throwable { - new TestUseRTMXendForLockBusyOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java deleted file mode 100644 index 20713301da5..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMAbortRatio affects amount of aborts before - * deoptimization. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMAbortRatio - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.XAbortProvoker; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that method will be deoptimized on high abort ratio - * as soon as abort ratio reaches RTMAbortRatio's value. - */ -public class TestRTMAbortRatio { - - protected void runTestCases() throws Throwable { - verifyAbortRatio(0, false); - verifyAbortRatio(10, false); - verifyAbortRatio(50, false); - verifyAbortRatio(100, false); - - verifyAbortRatio(0, true); - verifyAbortRatio(10, true); - verifyAbortRatio(50, true); - verifyAbortRatio(100, true); - } - - private void verifyAbortRatio(int abortRatio, boolean useStackLock) - throws Throwable { - CompilableTest test = new Test(); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - test, - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - "-XX:+UseRTMDeopt", - "-XX:RTMTotalCountIncrRate=1", - "-XX:RTMAbortThreshold=0", - CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", - 10 * Test.TOTAL_ITERATIONS), - CommandLineOptionTest.prepareNumericFlag("RTMAbortRatio", - abortRatio), - "-XX:+PrintPreciseRTMLockingStatistics", - test.getClass().getName(), - Boolean.toString(!useStackLock)); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, "VM output should contain " - + "exactly one RTM locking statistics entry."); - - RTMLockingStatistics lock = statistics.get(0); - int actualRatio; - - if (lock.getTotalAborts() == 1L) { - actualRatio = 0; - } else { - actualRatio = (int) (lock.getTotalLocks() - / (lock.getTotalAborts() - 1L)); - } - - Asserts.assertLTE(actualRatio, abortRatio, String.format( - "Actual abort ratio (%d) should lower or equal to " - + "specified (%d).", actualRatio, abortRatio)); - } - - /** - * Force abort after {@code Test.WARMUP_ITERATIONS} is done. - */ - public static class Test implements CompilableTest { - private static final int TOTAL_ITERATIONS = 10000; - private static final int WARMUP_ITERATIONS = 1000; - private final XAbortProvoker xabort = new XAbortProvoker(); - private final Object monitor = new Object(); - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::lock"; - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName(), "*.doAbort" }; - } - - public void lock(boolean abort) { - synchronized(monitor) { - if (abort) { - xabort.doAbort(); - } - } - } - - /** - * Usage: - * Test <inflate monitor> - */ - public static void main(String args[]) throws Throwable { - Asserts.assertGTE(args.length, 1, "One argument required."); - Test t = new Test(); - boolean shouldBeInflated = Boolean.valueOf(args[0]); - if (shouldBeInflated) { - AbortProvoker.inflateMonitor(t.monitor); - } - for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { - AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); - t.lock(i >= Test.WARMUP_ITERATIONS); - } - } - } - - public static void main(String args[]) throws Throwable { - new TestRTMAbortRatio().runTestCases(); - } -} - diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java deleted file mode 100644 index 4eddead8e5e..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMAbortThreshold option affects - * amount of aborts after which abort ratio is calculated. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMAbortThreshold - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that on RTMAbortThreshold option actually affects how soon - * method will be deoptimized on high abort ratio. - */ -public class TestRTMAbortThreshold { - - protected void runTestCases() throws Throwable { - verifyAbortThreshold(false, 1); - verifyAbortThreshold(false, 10); - verifyAbortThreshold(false, 1000); - - verifyAbortThreshold(true, 1); - verifyAbortThreshold(true, 10); - verifyAbortThreshold(true, 1000); - } - - private void verifyAbortThreshold(boolean useStackLock, - long abortThreshold) throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - provoker, - "-XX:+UseRTMDeopt", - "-XX:RTMAbortRatio=0", - CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", - abortThreshold), - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - AbortProvoker.class.getName(), - AbortType.XABORT.toString(), - Boolean.toString(!useStackLock)); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, "VM output should contain " - + "exactly one RTM locking statistics entry for method " - + provoker.getMethodWithLockName()); - - Asserts.assertEQ(statistics.get(0).getTotalLocks(), abortThreshold, - String.format("Expected that method with rtm lock elision was" - + " deoptimized after %d lock attempts", - abortThreshold)); - } - - public static void main(String args[]) throws Throwable { - new TestRTMAbortThreshold().runTestCases(); - } -} - diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java deleted file mode 100644 index 03f56769bff..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that if we use RTMDeopt, then deoptimization - * caused by reason other then rtm_state_change will reset - * method's RTM state. And if we don't use RTMDeopt, then - * RTM state remain the same after such deoptimization. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMAfterNonRTMDeopt - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.XAbortProvoker; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * To verify that with +UseRTMDeopt method's RTM state will be - * changed to ProfileRTM on deoptimization unrelated to - * rtm_state_change following sequence of events is used: - * <pre> - * - * rtm state ^ - * | - * UseRTM | ******| ****** - * | | - * ProfileRTM |******| |*****| - * | | | | - * 0-------|-----|-----|---------------------> time - * | | \ force abort - * | | - * | \ force deoptimization - * | - * \ force xabort - * </pre> - * When xabort is forced by native method call method should - * change it's state to UseRTM, because we use RTMAbortRatio=100 - * and low RTMLockingThreshold, so at this point actual abort - * ratio will be below 100% and there should be enough lock - * attempts to recompile method without RTM profiling. - */ -public class TestRTMAfterNonRTMDeopt { - private static final int ABORT_THRESHOLD = 1000; - private static final String RANGE_CHECK = "range_check"; - - protected void runTestCases() throws Throwable { - verifyRTMAfterDeopt(false, false); - verifyRTMAfterDeopt(true, false); - - verifyRTMAfterDeopt(false, true); - verifyRTMAfterDeopt(true, true); - } - - private void verifyRTMAfterDeopt(boolean useStackLock, - boolean useRTMDeopt) throws Throwable { - CompilableTest test = new Test(); - String logFile = String.format("rtm_%s_stack_lock_%s_deopt.xml", - (useStackLock ? "use" : "no"), (useRTMDeopt ? "use" : "no")); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFile, - test, - "-XX:CompileThreshold=1", - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - CommandLineOptionTest.prepareBooleanFlag("UseRTMDeopt", - useRTMDeopt), - "-XX:RTMAbortRatio=100", - CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", - TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD), - CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", - TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD / 2L), - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - Test.class.getName(), - Boolean.toString(!useStackLock) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int traps = RTMTestBase.firedRTMStateChangeTraps(logFile); - - if (useRTMDeopt) { - Asserts.assertEQ(traps, 2, "Two uncommon traps with " - + "reason rtm_state_change should be fired."); - } else { - Asserts.assertEQ(traps, 0, "No uncommon traps with " - + "reason rtm_state_change should be fired."); - } - - int rangeCheckTraps = RTMTestBase.firedUncommonTraps(logFile, - TestRTMAfterNonRTMDeopt.RANGE_CHECK); - - Asserts.assertEQ(rangeCheckTraps, 1, - "One range_check uncommon trap should be fired."); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - int expectedStatEntries = (useRTMDeopt ? 4 : 2); - - Asserts.assertEQ(statistics.size(), expectedStatEntries, - String.format("VM output should contain %d RTM locking " - + "statistics entries.", expectedStatEntries)); - } - - public static class Test implements CompilableTest { - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - private static final int ITERATIONS = 10000; - private static final int RANGE_CHECK_AT = ITERATIONS / 2; - private final XAbortProvoker xabort = new XAbortProvoker(); - private final Object monitor = new Object(); - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::forceAbort"; - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName(), - XAbortProvoker.class.getName() + "::doAbort()" }; - } - - public void forceAbort(int a[], boolean abort) { - try { - synchronized(monitor) { - a[0]++; - if (abort) { - Test.field = xabort.doAbort(); - } - } - } catch (Throwable t) { - // suppress any throwables - } - } - - /** - * Usage: - * Test <inflate monitor> - */ - public static void main(String args[]) throws Throwable { - Test t = new Test(); - - boolean shouldBeInflated = Boolean.valueOf(args[0]); - if (shouldBeInflated) { - AbortProvoker.inflateMonitor(t.monitor); - } - - int tmp[] = new int[1]; - - for (int i = 0; i < Test.ITERATIONS; i++ ) { - AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); - if (i == Test.RANGE_CHECK_AT) { - t.forceAbort(new int[0], false); - } else { - boolean isThreshold - = (i == TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD); - boolean isThresholdPlusRange - = (i == TestRTMAfterNonRTMDeopt.ABORT_THRESHOLD - + Test.RANGE_CHECK_AT); - t.forceAbort(tmp, isThreshold || isThresholdPlusRange); - } - } - } - } - - public static void main(String args[]) throws Throwable { - new TestRTMAfterNonRTMDeopt().runTestCases(); - } -} - diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java deleted file mode 100644 index 5faec082fc2..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that on high abort ratio method will be recompiled - * without rtm locking. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMDeoptOnHighAbortRatio - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that on high abort ratio method wil be deoptimized with - * <i>rtm_state_change</i> reason and after that RTM-based lock elision will not - * be used for that method. - * This test make asserts on total locks count done by compiled method, - * so in order to avoid issue with retriable locks -XX:RTMRetryCount=0 is used. - * For more details on that issue see {@link TestUseRTMAfterLockInflation}. - */ -public class TestRTMDeoptOnHighAbortRatio { - private static final long ABORT_THRESHOLD - = AbortProvoker.DEFAULT_ITERATIONS / 2L; - - protected void runTestCases() throws Throwable { - verifyDeopt(false); - verifyDeopt(true); - } - - private void verifyDeopt(boolean useStackLock) throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", - (useStackLock ? "use" : "no")); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFileName, - provoker, - "-XX:+UseRTMDeopt", - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - "-XX:RTMRetryCount=0", - CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", - TestRTMDeoptOnHighAbortRatio.ABORT_THRESHOLD), - "-XX:RTMAbortRatio=100", - "-XX:CompileThreshold=1", - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - AbortProvoker.class.getName(), - AbortType.XABORT.toString(), - Boolean.toString(!useStackLock) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); - - Asserts.assertEQ(firedTraps, 1, "Expected to get only one " - + "deoptimization due to rtm state change"); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, "VM output should contain " - + "exactly one RTM locking statistics entry for method " - + provoker.getMethodWithLockName()); - - Asserts.assertEQ(statistics.get(0).getTotalLocks(), - TestRTMDeoptOnHighAbortRatio.ABORT_THRESHOLD, - "After AbortThreshold was reached, method should be" - + " recompiled without rtm lock eliding."); - } - - public static void main(String args[]) throws Throwable { - new TestRTMDeoptOnHighAbortRatio().runTestCases(); - } -} - diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java deleted file mode 100644 index 404d076e5ca..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that on low abort ratio method will be recompiled. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMDeoptOnLowAbortRatio - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.XAbortProvoker; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that low abort ratio method will be deoptimized with - * <i>rtm_state_change</i> reason and will continue to use RTM-based lock - * elision after that. - * This test make asserts on total locks count done by compiled method, - * so in order to avoid issue with retriable locks -XX:RTMRetryCount=0 is used. - * For more details on that issue see {@link TestUseRTMAfterLockInflation}. - */ -public class TestRTMDeoptOnLowAbortRatio { - private static final long LOCKING_THRESHOLD = 100L; - private static final long ABORT_THRESHOLD = LOCKING_THRESHOLD / 2L; - - protected void runTestCases() throws Throwable { - verifyRTMDeopt(false); - verifyRTMDeopt(true); - } - - private void verifyRTMDeopt(boolean useStackLock) throws Throwable { - CompilableTest test = new Test(); - String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", - useStackLock ? "use" : "no"); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFileName, - test, - "-XX:+UseRTMDeopt", - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", - TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD), - CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", - TestRTMDeoptOnLowAbortRatio.ABORT_THRESHOLD), - "-XX:RTMAbortRatio=100", - "-XX:CompileThreshold=1", - "-XX:RTMRetryCount=0", - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - Test.class.getName(), - Boolean.toString(!useStackLock) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); - - Asserts.assertEQ(firedTraps, 1, - "Expected to get only one deoptimization due to rtm" - + " state change"); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 2, - "VM output should contain two RTM locking " - + "statistics entries for method " - + test.getMethodWithLockName()); - - RTMLockingStatistics statisticsBeforeDeopt = null; - - for (RTMLockingStatistics s : statistics) { - if (s.getTotalLocks() - == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD) { - Asserts.assertNull(statisticsBeforeDeopt, - "Only one abort was expected during test run"); - statisticsBeforeDeopt = s; - } - } - - Asserts.assertNotNull(statisticsBeforeDeopt, - "After LockThreshold was reached, method should be recompiled " - + "with rtm lock eliding."); - } - - public static class Test implements CompilableTest { - private final XAbortProvoker xabort = new XAbortProvoker(); - private final Object monitor = new Object(); - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::forceAbort"; - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName(), - XAbortProvoker.class.getName() + "::doAbort" }; - } - - public void forceAbort(boolean abort) { - synchronized(monitor) { - if (abort) { - xabort.doAbort(); - } - } - } - - /** - * Usage: - * Test <inflate monitor> - */ - public static void main(String args[]) throws Throwable { - Asserts.assertGTE(args.length, 1, "One argument required."); - Test t = new Test(); - boolean shouldBeInflated = Boolean.valueOf(args[0]); - if (shouldBeInflated) { - AbortProvoker.inflateMonitor(t.monitor); - } - for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { - AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); - t.forceAbort(i >= TestRTMDeoptOnLowAbortRatio.ABORT_THRESHOLD); - } - } - } - - public static void main(String args[]) throws Throwable { - new TestRTMDeoptOnLowAbortRatio().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java deleted file mode 100644 index 053e14d583f..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMLockingCalculationDelay affect when - * abort ratio calculation is started. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMLockingCalculationDelay - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -/** - * Test verifies that abort ratio calculation could be delayed using - * RTMLockingCalculationDelay option. - */ -public class TestRTMLockingCalculationDelay { - private static final boolean INFLATE_MONITOR = true; - - protected void runTestCases() throws Throwable { - // verify that calculation will be started immediately - verifyLockingCalculationDelay(0, 0, true); - - // verify that calculation will not be started during - // first 10 minutes, while test will be started immediately - verifyLockingCalculationDelay(600000, 0, false); - - // verify that calculation will be started after a second - verifyLockingCalculationDelay(1000, 1000, true); - } - - private void verifyLockingCalculationDelay(long delay, long testDelay, - boolean deoptExpected) throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - String logFileName = String.format("rtm_delay_%d_%d.xml", delay, - testDelay); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFileName, - provoker, - "-XX:+UseRTMDeopt", - CommandLineOptionTest.prepareNumericFlag( - "RTMLockingCalculationDelay", delay), - "-XX:RTMAbortRatio=0", - "-XX:RTMAbortThreshold=0", - AbortProvoker.class.getName(), - AbortType.XABORT.toString(), - Boolean.toString( - TestRTMLockingCalculationDelay.INFLATE_MONITOR), - Long.toString(AbortProvoker.DEFAULT_ITERATIONS), - Long.toString(testDelay) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int deopts = RTMTestBase.firedRTMStateChangeTraps(logFileName); - - if (deoptExpected) { - Asserts.assertGT(deopts, 0, "At least one deoptimization due to " - + "rtm_state_chage is expected"); - } else { - Asserts.assertEQ(deopts, 0, "No deoptimizations due to " - + "rtm_state_chage are expected"); - } - } - - public static void main(String args[]) throws Throwable { - new TestRTMLockingCalculationDelay().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java deleted file mode 100644 index 913fac3068b..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMLockingThreshold affects rtm state transition - * ProfileRTM => UseRTM. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMLockingThreshold - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.XAbortProvoker; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that RTMLockingThreshold option actually affects how soon - * method will be deoptimized on low abort ratio. - */ -public class TestRTMLockingThreshold { - - /** - * We use non-zero abort threshold to avoid abort related to - * interrupts, VMM calls, etc. during first lock attempt. - * - */ - private static final int MIN_ABORT_THRESHOLD = 10; - - protected void runTestCases() throws Throwable { - verifyLockingThreshold(0, false); - verifyLockingThreshold(100, false); - verifyLockingThreshold(1000, false); - - verifyLockingThreshold(0, true); - verifyLockingThreshold(100, true); - verifyLockingThreshold(1000, true); - } - - private void verifyLockingThreshold(int lockingThreshold, - boolean useStackLock) throws Throwable { - CompilableTest test = new Test(); - - int abortThreshold = Math.max(lockingThreshold / 2, - TestRTMLockingThreshold.MIN_ABORT_THRESHOLD); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - test, - "-XX:CompileThreshold=1", - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - "-XX:+UseRTMDeopt", - "-XX:RTMTotalCountIncrRate=1", - "-XX:RTMRetryCount=0", - CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold", - abortThreshold), - CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold", - lockingThreshold), - "-XX:RTMAbortRatio=100", - "-XX:+PrintPreciseRTMLockingStatistics", - Test.class.getName(), - Boolean.toString(!useStackLock), - Integer.toString(lockingThreshold) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 2, "VM output should contain two " - + "RTM locking statistics entries."); - - /** - * If RTMLockingThreshold==0, then we have to make at least 1 call. - */ - long expectedValue = lockingThreshold; - if (expectedValue == 0) { - expectedValue++; - } - - RTMLockingStatistics statBeforeDeopt = null; - for (RTMLockingStatistics s : statistics) { - if (s.getTotalLocks() == expectedValue) { - Asserts.assertNull(statBeforeDeopt, - "Only one statistics entry should contain aborts"); - statBeforeDeopt = s; - } - } - - Asserts.assertNotNull(statBeforeDeopt, "There should be exactly one " - + "statistics entry corresponding to ProfileRTM state."); - } - - public static class Test implements CompilableTest { - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - private static final int TOTAL_ITERATIONS = 10000; - private final XAbortProvoker xabort = new XAbortProvoker(); - private final Object monitor = new Object(); - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::lock"; - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName(), - XAbortProvoker.class.getName() + "::doAbort" }; - } - - public void lock(boolean abort) { - synchronized(monitor) { - if (abort) { - Test.field += xabort.doAbort(); - } - } - } - - /** - * Usage: - * Test <inflate monitor> - */ - public static void main(String args[]) throws Throwable { - Asserts.assertGTE(args.length, 2, "Two arguments required."); - Test t = new Test(); - boolean shouldBeInflated = Boolean.valueOf(args[0]); - int lockingThreshold = Integer.valueOf(args[1]); - if (shouldBeInflated) { - AbortProvoker.inflateMonitor(t.monitor); - } - for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { - AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); - t.lock(i >= lockingThreshold / 2); - } - } - } - - public static void main(String args[]) throws Throwable { - new TestRTMLockingThreshold().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java deleted file mode 100644 index ed09be05d21..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMRetryCount affects actual amount of retries. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMRetryCount - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.BusyLock; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that RTMRetryCount option actually affects amount of - * retries on lock busy. - */ -public class TestRTMRetryCount { - /** - * Time in ms, during which busy lock will be locked. - */ - private static final int LOCKING_TIME = 5000; - private static final boolean INFLATE_MONITOR = true; - - protected void runTestCases() throws Throwable { - verifyRTMRetryCount(0); - verifyRTMRetryCount(1); - verifyRTMRetryCount(5); - verifyRTMRetryCount(10); - } - - private void verifyRTMRetryCount(int retryCount) throws Throwable { - CompilableTest busyLock = new BusyLock(); - long expectedAborts = retryCount + 1L; - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - busyLock, - "-XX:-UseRTMXendForLockBusy", - "-XX:RTMTotalCountIncrRate=1", - CommandLineOptionTest.prepareNumericFlag("RTMRetryCount", - retryCount), - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - BusyLock.class.getName(), - Boolean.toString(TestRTMRetryCount.INFLATE_MONITOR), - Integer.toString(TestRTMRetryCount.LOCKING_TIME) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - busyLock.getMethodWithLockName(), outputAnalyzer.getStdout()); - - Asserts.assertEQ(statistics.size(), 1, "VM output should contain " - + "exactly one rtm locking statistics entry for method " - + busyLock.getMethodWithLockName()); - - Asserts.assertEQ(statistics.get(0).getTotalAborts(), expectedAborts, - String.format("It is expected to get %d aborts", - expectedAborts)); - } - - public static void main(String args[]) throws Throwable { - new TestRTMRetryCount().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java deleted file mode 100644 index 8702ae0b734..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMSpinLoopCount affects time spent - * between locking attempts. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMSpinLoopCount - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.BusyLock; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; -import jdk.test.lib.Platform; - -import java.util.List; - -/** - * Test verifies that RTMSpinLoopCount increase time spent between retries - * by comparing amount of retries done with different RTMSpinLoopCount's values. - */ -public class TestRTMSpinLoopCount { - private static final int LOCKING_TIME = 1000; - private static final int RTM_RETRY_COUNT = 1000; - private static final boolean INFLATE_MONITOR = true; - private static final long MAX_ABORTS = RTM_RETRY_COUNT + 1L; - private static int[] SPIN_LOOP_COUNTS; - - protected void runTestCases() throws Throwable { - - SPIN_LOOP_COUNTS = new int[] { 0, 100, 1_000, 10_000, 100_000 }; - - long[] aborts = new long[TestRTMSpinLoopCount.SPIN_LOOP_COUNTS.length]; - - for (int i = 0; i < TestRTMSpinLoopCount.SPIN_LOOP_COUNTS.length; i++) { - aborts[i] = getAbortsCountOnLockBusy( - TestRTMSpinLoopCount.SPIN_LOOP_COUNTS[i]); - } - - for (int i = 1; i < aborts.length; i++) { - Asserts.assertLTE(aborts[i], aborts[i - 1], "Increased spin loop " - + "count should not increase retries count."); - } - } - - private long getAbortsCountOnLockBusy(int spinLoopCount) throws Throwable { - CompilableTest test = new BusyLock(); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - test, - CommandLineOptionTest.prepareNumericFlag("RTMRetryCount", - TestRTMSpinLoopCount.RTM_RETRY_COUNT), - CommandLineOptionTest.prepareNumericFlag("RTMSpinLoopCount", - spinLoopCount), - "-XX:-UseRTMXendForLockBusy", - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - BusyLock.class.getName(), - Boolean.toString(TestRTMSpinLoopCount.INFLATE_MONITOR), - Integer.toString(TestRTMSpinLoopCount.LOCKING_TIME) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, - "VM output should contain exactly one entry for method " - + test.getMethodWithLockName()); - - RTMLockingStatistics lock = statistics.get(0); - - Asserts.assertLTE(lock.getTotalAborts(), - TestRTMSpinLoopCount.MAX_ABORTS, String.format("Total aborts " - + "count (%d) should be less or equal to %d", - lock.getTotalAborts(), - TestRTMSpinLoopCount.MAX_ABORTS)); - - return lock.getTotalAborts(); - } - - public static void main(String args[]) throws Throwable { - new TestRTMSpinLoopCount().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java deleted file mode 100644 index e0a8394570e..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that RTMTotalCountIncrRate option affects - * RTM locking statistics. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestRTMTotalCountIncrRate - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.XAbortProvoker; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that with RTMTotalCountIncrRate=1 RTM locking statistics - * contains precise information abort attempted locks and that with other values - * statistics contains information abort non-zero locking attempts. - * Since assert done for RTMTotalCountIncrRate=1 is pretty strict, test uses - * -XX:RTMRetryCount=0 to avoid issue with retriable aborts. For more details on - * that issue see {@link TestUseRTMAfterLockInflation}. - */ -public class TestRTMTotalCountIncrRate { - protected void runTestCases() throws Throwable { - verifyLocksCount(1, false); - verifyLocksCount(64, false); - verifyLocksCount(128, false); - verifyLocksCount(1, true); - verifyLocksCount(64, true); - verifyLocksCount(128, true); - } - - private void verifyLocksCount(int incrRate, boolean useStackLock) - throws Throwable{ - CompilableTest test = new Test(); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - test, - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - CommandLineOptionTest.prepareNumericFlag( - "RTMTotalCountIncrRate", incrRate), - "-XX:RTMRetryCount=0", - "-XX:+PrintPreciseRTMLockingStatistics", - Test.class.getName(), - Boolean.toString(!useStackLock) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, "VM output should contain " - + "exactly one RTM locking statistics entry for method " - + test.getMethodWithLockName()); - - RTMLockingStatistics lock = statistics.get(0); - if (incrRate == 1) { - Asserts.assertEQ(lock.getTotalLocks(), Test.TOTAL_ITERATIONS, - "Total locks should be exactly the same as amount of " - + "iterations."); - } - } - - public static class Test implements CompilableTest { - private static final long TOTAL_ITERATIONS = 10000L; - private final XAbortProvoker xabort = new XAbortProvoker(); - private final Object monitor = new Object(); - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::lock"; - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName(), "*.doAbort" }; - } - - public void lock(boolean forceAbort) { - synchronized(monitor) { - if (forceAbort) { - // We're calling native method in order to force - // abort. It's done by explicit xabort call emitted - // in SharedRuntime::generate_native_wrapper. - // If an actual JNI call will be replaced by - // intrinsic - we'll be in trouble, since xabort - // will be no longer called and test may fail. - xabort.doAbort(); - } - Test.field++; - } - } - - /** - * Usage: - * Test <inflate monitor> - */ - public static void main(String args[]) throws Throwable { - Asserts.assertGTE(args.length, 1, "One argument required."); - Test test = new Test(); - boolean shouldBeInflated = Boolean.valueOf(args[0]); - if (shouldBeInflated) { - AbortProvoker.inflateMonitor(test.monitor); - } - for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) { - AbortProvoker.verifyMonitorState(test.monitor, - shouldBeInflated); - // Force abort on first iteration to avoid rare case when - // there were no aborts and locks count was not incremented - // with RTMTotalCountIncrRate > 1 (in such case JVM won't - // print JVM locking statistics). - test.lock(i == 0); - } - } - } - - public static void main(String args[]) throws Throwable { - new TestRTMTotalCountIncrRate().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java deleted file mode 100644 index d99a59ab84f..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that rtm locking is used for stack locks before - * inflation and after it used for inflated locks. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestUseRTMAfterLockInflation - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; - -import java.util.List; - -/** - * Test verifies that RTM is used after lock inflation by executing compiled - * method with RTM-based lock elision using stack lock first, then that lock - * is inflated and the same compiled method invoked again. - * - * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before - * lock inflation and the same amount of times after inflation. - * As a result total locks count should be equal to - * {@code 2 * AbortProvoker.DEFAULT_ITERATIONS}. - * It is a pretty strict assertion which could fail if some retriable abort - * happened: it could be {@code AbortType.RETRIABLE} or - * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these - * reasons simultaneously. In order to avoid false negative failures related - * to incorrect aborts counting, -XX:RTMRetryCount=0 is used. - */ -public class TestUseRTMAfterLockInflation { - private static final long EXPECTED_LOCKS - = 2L * AbortProvoker.DEFAULT_ITERATIONS; - - protected void runTestCases() throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - long totalLocksCount = 0; - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - provoker, - "-XX:+UseRTMForStackLocks", - "-XX:RTMTotalCountIncrRate=1", - "-XX:RTMRetryCount=0", - "-XX:+PrintPreciseRTMLockingStatistics", - Test.class.getName(), - AbortType.XABORT.toString()); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 2, - "VM output should contain two rtm locking statistics entries " - + "for method " + provoker.getMethodWithLockName()); - - for (RTMLockingStatistics s : statistics) { - totalLocksCount += s.getTotalLocks(); - } - - Asserts.assertEQ(totalLocksCount, - TestUseRTMAfterLockInflation.EXPECTED_LOCKS, - "Total lock count should be greater or equal to " - + TestUseRTMAfterLockInflation.EXPECTED_LOCKS); - } - - public static class Test { - /** - * Usage: - * Test <provoker type> - */ - public static void main(String args[]) throws Throwable { - Asserts.assertGT(args.length, 0, - "AbortType name is expected as first argument."); - - AbortProvoker provoker - = AbortType.lookup(Integer.valueOf(args[0])).provoker(); - for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { - AbortProvoker.verifyMonitorState(provoker, false /*deflated*/); - provoker.forceAbort(); - } - provoker.inflateMonitor(); - for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { - AbortProvoker.verifyMonitorState(provoker, true /*inflated*/); - provoker.forceAbort(); - } - } - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMAfterLockInflation().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java deleted file mode 100644 index facf686739c..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that UseRTMDeopt affects uncommon trap installation in - * compiled methods with synchronized block. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestUseRTMDeopt - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -/** - * Test verifies that usage of UseRTMDeopt option affects uncommon traps usage - * for methods that use locking. - */ -public class TestUseRTMDeopt { - - protected void runTestCases() throws Throwable { - verifyUseRTMDeopt(false); - verifyUseRTMDeopt(true); - } - - private void verifyUseRTMDeopt(boolean useRTMDeopt) throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - String logFileName = String.format("rtm_%s_deopt.xml", - useRTMDeopt ? "use" : "no"); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFileName, - provoker, - CommandLineOptionTest.prepareBooleanFlag("UseRTMDeopt", - useRTMDeopt), - AbortProvoker.class.getName(), - AbortType.XABORT.toString() - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int expectedUncommonTraps = useRTMDeopt ? 1 : 0; - int installedUncommonTraps - = RTMTestBase.installedRTMStateChangeTraps(logFileName); - - Asserts.assertEQ(expectedUncommonTraps, installedUncommonTraps, - String.format("Expected to find %d uncommon traps " - + "installed with reason rtm_state_change.", - expectedUncommonTraps)); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMDeopt().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java deleted file mode 100644 index 0b5267a3ef6..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that rtm locking is used for inflated locks. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestUseRTMForInflatedLocks - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; - -import java.util.List; - -/** - * Test verifies that RTM-based lock elision could be used for inflated locks - * by calling compiled method that use RTM-based lock elision and using - * manually inflated lock. - * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times, - * so total locks count should be the same. - * This test could also be affected by retriable aborts, so -XX:RTMRetryCount=0 - * is used. For more information abort that issue see - * {@link TestUseRTMAfterLockInflation}. - */ -public class TestUseRTMForInflatedLocks { - - protected void runTestCases() throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - RTMLockingStatistics lock; - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - provoker, - "-XX:-UseRTMForStackLocks", - "-XX:RTMTotalCountIncrRate=1", - "-XX:RTMRetryCount=0", - "-XX:+PrintPreciseRTMLockingStatistics", - AbortProvoker.class.getName(), - AbortType.XABORT.toString()); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, - "VM output should contain exactly one rtm locking statistics " - + "entry for method " + provoker.getMethodWithLockName()); - - lock = statistics.get(0); - Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, - "Total lock count should be greater or equal to " - + AbortProvoker.DEFAULT_ITERATIONS); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMForInflatedLocks().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java deleted file mode 100644 index 720fedb613b..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that rtm locking is used for stack locks. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestUseRTMForStackLocks - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; - -import java.util.List; - -/** - * Test verifies that RTM-based lock elision could be used for stack locks - * by calling compiled method that use RTM-based lock elision and using - * stack lock. - * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times, - * so total locks count should be the same. - * This test could also be affected by retriable aborts, so -XX:RTMRetryCount=0 - * is used. For more information abort that issue see - * {@link TestUseRTMAfterLockInflation}. - */ -public class TestUseRTMForStackLocks { - private static final boolean INFLATE_MONITOR = false; - - protected void runTestCases() throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - RTMLockingStatistics lock; - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - provoker, - "-XX:+UseRTMForStackLocks", - "-XX:RTMTotalCountIncrRate=1", - "-XX:RTMRetryCount=0", - "-XX:+PrintPreciseRTMLockingStatistics", - AbortProvoker.class.getName(), - AbortType.XABORT.toString(), - Boolean.toString(TestUseRTMForStackLocks.INFLATE_MONITOR)); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, - "VM output should contain exactly one rtm locking statistics " - + "entry for method " + provoker.getMethodWithLockName()); - - lock = statistics.get(0); - Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, - "Total locks count should be greater or equal to " - + AbortProvoker.DEFAULT_ITERATIONS); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMForStackLocks().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java deleted file mode 100644 index 2eb3735855e..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that UseRTMXendForLockBusy option affects - * method behaviour if lock is busy. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.locking.TestUseRTMXendForLockBusy - */ - -package compiler.rtm.locking; - -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.BusyLock; -import compiler.testlibrary.rtm.CompilableTest; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that with +UseRTMXendForLockBusy there will be no aborts - * forced by the test. - */ -public class TestUseRTMXendForLockBusy { - private final static int LOCKING_TIME = 5000; - - protected void runTestCases() throws Throwable { - // inflated lock, xabort on lock busy - verifyXendForLockBusy(true, false); - // inflated lock, xend on lock busy - verifyXendForLockBusy(true, true); - // stack lock, xabort on lock busy - verifyXendForLockBusy(false, false); - // stack lock, xend on lock busy - verifyXendForLockBusy(false, true); - } - - private void verifyXendForLockBusy(boolean inflateMonitor, - boolean useXend) throws Throwable { - CompilableTest test = new BusyLock(); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - test, - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - !inflateMonitor), - CommandLineOptionTest.prepareBooleanFlag( - "UseRTMXendForLockBusy", - useXend), - "-XX:RTMRetryCount=0", - "-XX:RTMTotalCountIncrRate=1", - "-XX:+PrintPreciseRTMLockingStatistics", - BusyLock.class.getName(), - Boolean.toString(inflateMonitor), - Integer.toString(TestUseRTMXendForLockBusy.LOCKING_TIME) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - test.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, "VM output should contain " - + "exactly one rtm locking statistics entry for method " - + test.getMethodWithLockName()); - - long aborts = statistics.get(0).getAborts(AbortType.XABORT); - - if (useXend) { - Asserts.assertEQ(aborts, 0L, - "Expected to get no aborts on busy lock"); - } else { - Asserts.assertGT(aborts, 0L, - "Expected to get at least one abort on busy lock"); - } - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMXendForLockBusy().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java b/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java deleted file mode 100644 index 07514e4fc37..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that NoRTMLockEliding option could be applied to - * specified method and that such method will not use rtm. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.method_options.TestNoRTMLockElidingOption - */ - -package compiler.rtm.method_options; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that method tagged with option <i>NoRTMLockElidingOption</i> - * will not use RTM-based lock elision. - * Test invokes compiled method and checks that no deoptimization with - * <i>rtm_state_change</i> reason had happened and that that VM output - * does not contain RTM locking statistics for compiled method. - */ -public class TestNoRTMLockElidingOption { - - public void runTestCases() throws Throwable { - verifyOption(false); - verifyOption(true); - } - - public void verifyOption(boolean useStackLock) throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", - (useStackLock ? "use" : "no")); - String methodOption = String.format("-XX:CompileCommand=option," + - "%s,NoRTMLockEliding", provoker.getMethodWithLockName()); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFileName, - provoker, - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - methodOption, - "-XX:RTMTotalCountIncrRate=1", - "-XX:+UseRTMDeopt", - "-XX:+PrintPreciseRTMLockingStatistics", - AbortProvoker.class.getName(), - AbortType.XABORT.toString(), - Boolean.toString(!useStackLock) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); - - Asserts.assertEQ(firedTraps, 0, - "No deoptimizations with rtm_state_change reason are expected"); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 0, - "VM output should not contain RTM locking statistics entries " - + "for method " + provoker.getMethodWithLockName()); - } - - public static void main(String args[]) throws Throwable { - new TestNoRTMLockElidingOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java b/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java deleted file mode 100644 index 4007121b4aa..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that UseRTMLockEliding option could be applied to - * specified method and that such method will not be deoptimized - * on high abort ratio. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.method_options.TestUseRTMLockElidingOption - */ - -package compiler.rtm.method_options; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.util.List; - -/** - * Test verifies that method tagged with option <i>UseRTMLockElidingOption</i> - * will use RTM-based lock elision, but will be never deoptimized with - * <i>rtm_state_change reason</i>. - * Test invokes compiled method and checks that no deoptimization with - * <i>rtm_state_change</i> reason had happened and that that VM output - * contains RTM locking statistics for compiled method and that total locks - * count equals to method's invocations. - * Since last assert is pretty strict, test uses -XX:RTMRetryCount=0 in order - * to avoid issue with retriable aborts described in - * {@link TestUseRTMAfterLockInflation}. - */ -public class TestUseRTMLockElidingOption { - - public void runTestCases() throws Throwable { - verifyOption(false); - verifyOption(true); - } - - public void verifyOption(boolean useStackLock) throws Throwable { - AbortProvoker provoker = AbortType.XABORT.provoker(); - String logFileName = String.format("rtm_deopt_%s_stack_lock.xml", - (useStackLock ? "use" : "no")); - String methodOption = String.format("-XX:CompileCommand=option," + - "%s,UseRTMLockEliding", provoker.getMethodWithLockName()); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - logFileName, - provoker, - CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks", - useStackLock), - methodOption, - "-XX:RTMTotalCountIncrRate=1", - "-XX:RTMRetryCount=0", - "-XX:+UseRTMDeopt", - "-XX:+PrintPreciseRTMLockingStatistics", - provoker.getClass().getName(), - AbortType.XABORT.toString(), - Boolean.toString(!useStackLock) - ); - - outputAnalyzer.shouldHaveExitValue(0); - - int firedTraps = RTMTestBase.firedRTMStateChangeTraps(logFileName); - - Asserts.assertEQ(firedTraps, 0, - "Method deoptimization with rtm_state_change is unexpected"); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 1, - "VM output should contain exactly one RTM locking " - + "statistics entry for method " - + provoker.getMethodWithLockName()); - - RTMLockingStatistics lock = statistics.get(0); - - Asserts.assertEQ(lock.getTotalLocks(), AbortProvoker.DEFAULT_ITERATIONS, - "Expected to get total locks count equal to total amount of " - + "lock attempts."); - } - - public static void main(String args[]) throws Throwable { - new TestUseRTMLockElidingOption().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java b/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java deleted file mode 100644 index 4223924b9bd..00000000000 --- a/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 8031320 - * @summary Verify that rtm locking statistics contain proper information - * on overall aborts and locks count and count of aborts of - * different types. Test also verify that VM output does not - * contain rtm locking statistics when it should not. - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management - * @requires vm.rtm.cpu & vm.rtm.compiler - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/native -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI - * compiler.rtm.print.TestPrintPreciseRTMLockingStatistics - */ - - -package compiler.rtm.print; - -import compiler.testlibrary.rtm.AbortProvoker; -import compiler.testlibrary.rtm.AbortType; -import compiler.testlibrary.rtm.RTMLockingStatistics; -import compiler.testlibrary.rtm.RTMTestBase; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * Test verifies that VM output does not contain RTM locking statistics when it - * should not (when PrintPreciseRTMLockingStatistics is off) and that with - * -XX:+PrintPreciseRTMLockingStatistics locking statistics contains sane - * total locks and aborts count as well as for specific abort types. - */ -public class TestPrintPreciseRTMLockingStatistics { - - public void runTestCases() throws Throwable { - verifyNoStatistics(); - verifyStatistics(); - } - - // verify that VM output does not contain - // rtm locking statistics - private void verifyNoStatistics() throws Throwable { - verifyNoStatistics(AbortType.XABORT); - - verifyNoStatistics(AbortType.XABORT, - "-XX:-PrintPreciseRTMLockingStatistics"); - - verifyNoStatistics(AbortType.XABORT, "-XX:-UseRTMLocking", - "-XX:+PrintPreciseRTMLockingStatistics"); - } - - // verify that rtm locking statistics contain information - // about each type of aborts - private void verifyStatistics() throws Throwable { - verifyAbortsCount(AbortType.XABORT); - verifyAbortsCount(AbortType.MEM_CONFLICT); - verifyAbortsCount(AbortType.BUF_OVERFLOW); - verifyAbortsCount(AbortType.NESTED_ABORT); - } - - private void verifyNoStatistics(AbortType abortProvokerType, - String... vmOpts) throws Throwable { - AbortProvoker provoker = abortProvokerType.provoker(); - List<String> finalVMOpts = new LinkedList<>(); - Collections.addAll(finalVMOpts, vmOpts); - Collections.addAll(finalVMOpts, AbortProvoker.class.getName(), - abortProvokerType.toString()); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest(provoker, - finalVMOpts.toArray(new String[finalVMOpts.size()])); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - outputAnalyzer.getOutput()); - - Asserts.assertEQ(statistics.size(), 0, "VM output should not contain " - + "any RTM locking statistics"); - } - - private void verifyAbortsCount(AbortType abortType) throws Throwable { - AbortProvoker provoker = abortType.provoker(); - - OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( - provoker, - "-XX:+PrintPreciseRTMLockingStatistics", - AbortProvoker.class.getName(), - abortType.toString()); - - outputAnalyzer.shouldHaveExitValue(0); - - List<RTMLockingStatistics> statistics = RTMLockingStatistics.fromString( - provoker.getMethodWithLockName(),outputAnalyzer.getOutput()); - - Asserts.assertGT(statistics.size(), 0, "VM output should contain one " - + "rtm locking statistics entry for method " - + provoker.getMethodWithLockName()); - - RTMLockingStatistics lock = statistics.get(0); - - Asserts.assertGT(lock.getTotalAborts(), 0L, - "RTM locking statistics should contain non zero total aborts " - + "count"); - - Asserts.assertGT(lock.getAborts(abortType), 0L, String.format( - "RTM locking statistics should contain non zero aborts count " - + "for abort reason %s", abortType)); - } - - public static void main(String args[]) throws Throwable { - new TestPrintPreciseRTMLockingStatistics().runTestCases(); - } -} diff --git a/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java b/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java index 5dd938442cc..2bf8afae609 100644 --- a/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java +++ b/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java @@ -36,6 +36,7 @@ * @requires vm.opt.TieredStopAtLevel == null & vm.opt.TieredCompilation == null * @requires vm.simpleArch == "x86" | vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" * @requires vm.debug + * @requires !vm.graal.enabled * @run driver compiler.sharedstubs.SharedStubToInterpTest -XX:-TieredCompilation * */ diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java deleted file mode 100644 index cf74942aadf..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortProvoker.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. - * 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 compiler.testlibrary.rtm; - -import jdk.test.lib.Asserts; -import jdk.test.whitebox.WhiteBox; - -import java.util.Objects; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; - -/** - * Base class for different transactional execution abortion - * provokers aimed to force abort due to specified reason. - */ -public abstract class AbortProvoker implements CompilableTest { - public static final long DEFAULT_ITERATIONS = 10000L; - private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); - @SuppressWarnings("unused") - private static int sharedState = 0; - /** - * Inflates monitor associated with object {@code monitor}. - * Inflation is forced by entering the same monitor from - * two different threads. - * - * @param monitor monitor to be inflated. - * @return inflated monitor. - * @throws Exception if something went wrong. - */ - public static Object inflateMonitor(Object monitor) throws Exception { - CyclicBarrier barrier = new CyclicBarrier(2); - - Runnable inflatingRunnable = () -> { - synchronized (monitor) { - try { - barrier.await(); - } catch (BrokenBarrierException | InterruptedException e) { - throw new RuntimeException( - "Synchronization issue occurred.", e); - } - try { - monitor.wait(); - } catch (InterruptedException e) { - throw new AssertionError("The thread waiting on an" - + " inflated monitor was interrupted, thus test" - + " results may be incorrect.", e); - } - } - }; - - Thread t = new Thread(inflatingRunnable); - t.setDaemon(true); - t.start(); - // Wait until thread t enters the monitor. - barrier.await(); - synchronized (monitor) { - // At this point thread t is already waiting on the monitor. - // Modifying static field just to avoid lock's elimination. - sharedState++; - } - verifyMonitorState(monitor, true /* inflated */); - return monitor; - } - - /** - * Verifies that {@code monitor} is a stack-lock or inflated lock depending - * on {@code shouldBeInflated} value. If {@code monitor} is inflated while - * it is expected that it should be a stack-lock, then this method attempts - * to deflate it by forcing a safepoint and then verifies the state once - * again. - * - * @param monitor monitor to be verified. - * @param shouldBeInflated flag indicating whether or not monitor is - * expected to be inflated. - * @throws RuntimeException if the {@code monitor} in a wrong state. - */ - public static void verifyMonitorState(Object monitor, - boolean shouldBeInflated) { - if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) { - boolean did_deflation = WHITE_BOX.deflateIdleMonitors(); - Asserts.assertEQ(did_deflation, true, - "deflateIdleMonitors() should have worked."); - } - Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated, - "Monitor in a wrong state."); - } - /** - * Verifies that monitor used by the {@code provoker} is a stack-lock or - * inflated lock depending on {@code shouldBeInflated} value. If such - * monitor is inflated while it is expected that it should be a stack-lock, - * then this method attempts to deflate it by forcing a safepoint and then - * verifies the state once again. - * - * @param provoker AbortProvoker whose monitor's state should be verified. - * @param shouldBeInflated flag indicating whether or not monitor is - * expected to be inflated. - * @throws RuntimeException if the {@code monitor} in a wrong state. - */ - public static void verifyMonitorState(AbortProvoker provoker, - boolean shouldBeInflated) { - verifyMonitorState(provoker.monitor, shouldBeInflated); - } - - /** - * Get instance of specified AbortProvoker, inflate associated monitor - * if needed and then invoke forceAbort method in a loop. - * - * Usage: - * AbortProvoker <AbortType name> [<inflate monitor> - * [<iterations> [ <delay>]]] - * - * Default parameters are: - * <ul> - * <li>inflate monitor = <b>true</b></li> - * <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li> - * <li>delay = <b>0</b></li> - * </ul> - */ - public static void main(String args[]) throws Throwable { - Asserts.assertGT(args.length, 0, "At least one argument is required."); - - AbortType abortType = AbortType.lookup(Integer.valueOf(args[0])); - boolean monitorShouldBeInflated = true; - long iterations = AbortProvoker.DEFAULT_ITERATIONS; - - if (args.length > 1) { - monitorShouldBeInflated = Boolean.valueOf(args[1]); - - if (args.length > 2) { - iterations = Long.valueOf(args[2]); - - if (args.length > 3) { - Thread.sleep(Integer.valueOf(args[3])); - } - } - } - - AbortProvoker provoker = abortType.provoker(); - - if (monitorShouldBeInflated) { - provoker.inflateMonitor(); - } - - for (long i = 0; i < iterations; i++) { - AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated); - provoker.forceAbort(); - } - } - - protected final Object monitor; - - protected AbortProvoker() { - this(new Object()); - } - - protected AbortProvoker(Object monitor) { - this.monitor = Objects.requireNonNull(monitor); - } - - /** - * Inflates monitor used by this AbortProvoker instance. - * @throws Exception - */ - public void inflateMonitor() throws Exception { - AbortProvoker.inflateMonitor(monitor); - } - - /** - * Forces transactional execution abortion. - */ - public abstract void forceAbort(); - - /** - * Returns names of all methods that have to be compiled - * in order to successfully force transactional execution - * abortion. - * - * @return array with methods' names that have to be compiled. - */ - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName() }; - } - - /** - * Returns name of the method that will contain monitor whose locking - * will be elided using transactional execution. - * - * @return name of the method that will contain elided lock. - */ - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::forceAbort"; - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortType.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortType.java deleted file mode 100644 index dd439111afa..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/AbortType.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.testlibrary.rtm; - -import jdk.test.lib.Asserts; - -import java.util.HashMap; -import java.util.Map; - -/** - * Type of transactional execution abort. - * For more details on different abort types please see - * shared/vm/runtime/rtmLocking.hpp - */ -public enum AbortType { - XABORT(0), - RETRIABLE(1), - MEM_CONFLICT(2), - BUF_OVERFLOW(3), - DEBUG_BREAKPOINT(4), - NESTED_ABORT(5); - - private final int type; - private static final Map<Integer, AbortType> LOOKUP_MAP = new HashMap<>(); - - static { - for (AbortType abortType : AbortType.values()) { - Asserts.assertFalse(LOOKUP_MAP.containsKey(abortType.type), - "Abort type values should be unique."); - LOOKUP_MAP.put(abortType.type, abortType); - } - } - - private AbortType(int type) { - this.type = type; - } - - /** - * Returns AbortProvoker for aborts represented by this abort type. - * - * @return an AbortProvoker instance - */ - public AbortProvoker provoker() { - return AbortType.createNewProvoker(this); - } - - public static AbortType lookup(int type) { - Asserts.assertLT(type, AbortType.values().length, - "Unknown abort type."); - return LOOKUP_MAP.get(type); - } - - /** - * Returns transaction execution abort provoker for specified abortion type. - * - * @param type a type of abort which will be forced by returned - * AbortProvoker instance. - * @return AbortProvoker instance that will force abort of specified type - * @throws RuntimeException if there is no provoker for specified type - */ - private static AbortProvoker createNewProvoker(AbortType type) { - switch (type) { - case XABORT: - return new XAbortProvoker(); - case MEM_CONFLICT: - return new MemoryConflictProvoker(); - case BUF_OVERFLOW: - return new BufferOverflowProvoker(); - case NESTED_ABORT: - return new NestedAbortProvoker(); - default: - throw new RuntimeException("No provoker exists for type " - + type.name()); - } - } - - @Override - public String toString() { - return Integer.toString(type); - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/BufferOverflowProvoker.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/BufferOverflowProvoker.java deleted file mode 100644 index 6a3ab4e35aa..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/BufferOverflowProvoker.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.testlibrary.rtm; - -/** - * In order to provoke transactional execution abort due to - * internal's buffer overflow BufferOverflowProvoker modifies - * 1MB of BYTES during single transaction. - */ -class BufferOverflowProvoker extends AbortProvoker { - /** - * To force buffer overflow abort we modify memory region with - * size more then L1d cache size. - */ - private static final int MORE_THAN_L1D_SIZE = 1024 * 1024; - private static final byte[] DATA = new byte[MORE_THAN_L1D_SIZE]; - - @Override - public void forceAbort() { - synchronized(monitor) { - for (int i = 0; i < BufferOverflowProvoker.DATA.length; i++) { - BufferOverflowProvoker.DATA[i]++; - } - } - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/BusyLock.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/BusyLock.java deleted file mode 100644 index 79120a64136..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/BusyLock.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.testlibrary.rtm; - -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; - -/** - * Test case for busy lock scenario. - * One thread enters the monitor and sleep for a while. - * Another thread is blocked on the same monitor. - */ -public class BusyLock implements CompilableTest, Runnable { - private static final int DEFAULT_TIMEOUT = 1000; - private final CyclicBarrier barrier; - - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - protected final Object monitor; - protected final int timeout; - - public BusyLock() { - this(BusyLock.DEFAULT_TIMEOUT); - } - - public BusyLock(int timeout) { - this.timeout = timeout; - this.monitor = new Object(); - this.barrier = new CyclicBarrier(2); - } - - @Override - public void run() { - try { - synchronized (monitor) { - barrier.await(); - Thread.sleep(timeout); - } - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException("Synchronization error happened.", e); - } - } - - public void syncAndTest() { - try { - // wait until monitor is locked by a ::run method - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException("Synchronization error happened.", e); - } - test(); - } - - public void test() { - synchronized(monitor) { - BusyLock.field++; - } - } - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::test"; - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { getMethodWithLockName() }; - } - - /** - * Usage: - * BusyLock [ <inflate monitor> [ <timeout> ] ] - * - * Default values are: - * <ul> - * <li>inflate monitor = {@code true}</li> - * <li>timeout = {@code BusyLock.DEFAULT_TIMEOUT}</li> - * </ul> - */ - public static void main(String args[]) throws Exception { - int timeoutValue = BusyLock.DEFAULT_TIMEOUT; - boolean inflateMonitor = true; - - if (args.length > 0 ) { - inflateMonitor = Boolean.valueOf(args[0]); - - if (args.length > 1) { - timeoutValue = Integer.valueOf(args[1]); - } - } - - BusyLock busyLock = new BusyLock(timeoutValue); - - if (inflateMonitor) { - AbortProvoker.inflateMonitor(busyLock.monitor); - } - - Thread t = new Thread(busyLock); - t.start(); - busyLock.syncAndTest(); - t.join(); - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/CompilableTest.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/CompilableTest.java deleted file mode 100644 index da701fa30a6..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/CompilableTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.testlibrary.rtm; - -/** - * Interface for test scenarios that contain methods - * that should be compiled. - */ -public interface CompilableTest { - /** - * @return array with methods' names that should be compiled. - */ - String[] getMethodsToCompileNames(); - - /** - * @return name of method with RTM-elided lock. - */ - String getMethodWithLockName(); -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/MemoryConflictProvoker.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/MemoryConflictProvoker.java deleted file mode 100644 index 7926c9e23b4..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/MemoryConflictProvoker.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.testlibrary.rtm; - -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; - -/** - * To force transactional execution abort due to memory conflict - * one thread should access memory region from transactional region - * while another thread should modify the same memory region. - * Since this scenario is based on the race condition between threads - * you should not expect some particular amount of aborts. - */ -class MemoryConflictProvoker extends AbortProvoker { - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - private static final int INNER_ITERATIONS = 10000; - private final CyclicBarrier barrier; - /** - * This thread will access and modify memory region - * from outside of the transaction. - */ - private final Runnable conflictingThread; - - public MemoryConflictProvoker() { - this(new Object()); - } - - public MemoryConflictProvoker(Object monitor) { - super(monitor); - barrier = new CyclicBarrier(2); - conflictingThread = () -> { - try { - barrier.await(); - } catch (Exception e) { - throw new RuntimeException(e); - } - for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { - MemoryConflictProvoker.field++; - } - }; - } - - /** - * Accesses and modifies memory region from within the transaction. - */ - public void transactionalRegion() { - for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { - synchronized(monitor) { - MemoryConflictProvoker.field--; - } - } - } - - @Override - public void forceAbort() { - try { - Thread t = new Thread(conflictingThread); - t.start(); - try { - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException(e); - } - transactionalRegion(); - t.join(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public String getMethodWithLockName() { - return this.getClass().getName() + "::transactionalRegion"; - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/NestedAbortProvoker.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/NestedAbortProvoker.java deleted file mode 100644 index 7123f2d562f..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/NestedAbortProvoker.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.testlibrary.rtm; - -import java.util.Arrays; - -/** - * In order to force nested transaction abort NestedAbortProvoker - * invoke BufferOverflowProvoker from transactional region. - */ -class NestedAbortProvoker extends AbortProvoker { - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - private final AbortProvoker nestedAbortProvoker; - - public NestedAbortProvoker() { - this.nestedAbortProvoker = new XAbortProvoker(monitor); - } - - @Override - public void forceAbort() { - synchronized(monitor) { - NestedAbortProvoker.field++; - nestedAbortProvoker.forceAbort(); - NestedAbortProvoker.field--; - } - } - - @Override - public String[] getMethodsToCompileNames() { - String nestedProvokerMethods[] - = nestedAbortProvoker.getMethodsToCompileNames(); - String methods[] = Arrays.copyOf(nestedProvokerMethods, - nestedProvokerMethods.length + 1); - methods[methods.length - 1] = getMethodWithLockName(); - return methods; - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/RTMLockingStatistics.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/RTMLockingStatistics.java deleted file mode 100644 index 351b1a96bd8..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/RTMLockingStatistics.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 compiler.testlibrary.rtm; - -import java.util.EnumMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Wrapper for +UsePreciseRTMLockingStatistics output. - * - * Example of locking statistics: - * - * java/lang/ClassLoader.loadClass@7 - * # rtm locks total (estimated): 6656 - * # rtm lock aborts (total): 10000 - * # rtm lock aborts 0 (abort instruction ): 9999 - * # rtm lock aborts 1 (may succeed on retry): 9999 - * # rtm lock aborts 2 (thread conflict ): 0 - * # rtm lock aborts 3 (buffer overflow ): 1 - * # rtm lock aborts 4 (debug or trap hit ): 0 - * # rtm lock aborts 5 (maximum nested depth): 0 - */ -public class RTMLockingStatistics { - /** - * Pattern for aborts per abort type entries. - */ - private static final Pattern ABORT_PATTERN; - - /** - * Pattern for whole statistics. - */ - private static final Pattern RTM_LOCKING_STATISTICS_PATTERN; - - static { - String abortRe - = "# rtm lock aborts\\s+(?<type>[0-9]+)\\s+\\([a-z\\s]+\\):\\s(?<count>[0-9]+)"; - - ABORT_PATTERN = Pattern.compile(abortRe); - RTM_LOCKING_STATISTICS_PATTERN = Pattern.compile( - "(?<className>[^.\n]+)\\." + - "(?<methodName>[^@\n]+)@(?<bci>[0-9]+)\n" + - "# rtm locks total \\(estimated\\):\\s*" + - "(?<totalLocks>[0-9]+)\n" + - "# rtm lock aborts\\s+\\(total\\):\\s*(?<totalAborts>[0-9]+)\n" + - "(?<abortStats>(" + abortRe + "\n)+)"); - } - - private final long totalLocks; - private final long totalAborts; - private final String className; - private final String methodName; - private final int bci; - private final Map<AbortType, Long> aborts = new EnumMap<>(AbortType.class); - - /** - * Constructs RTMLockingStatistics from matcher captured statistics entry. - * @param matcher Matcher captured statistics entry. - */ - private RTMLockingStatistics(Matcher matcher) { - className = matcher.group("className"); - methodName = matcher.group("methodName"); - bci = Integer.valueOf(matcher.group("bci")); - totalLocks = Long.valueOf(matcher.group("totalLocks")); - totalAborts = Long.valueOf(matcher.group("totalAborts")); - - Matcher abortMatcher = ABORT_PATTERN.matcher(matcher. - group("abortStats")); - - while (abortMatcher.find()) { - int type = Integer.valueOf(abortMatcher.group("type")); - long count = Long.valueOf(abortMatcher.group("count")); - setAborts(AbortType.lookup(type), count); - } - } - - - /** - * Parses string and return all founded RTM locking statistics entries. - * - * @param str the string to be parsed. - * @return list with all founded RTM locking statistics entries or - * empty list if nothing was found. - */ - public static List<RTMLockingStatistics> fromString(String str) { - List<RTMLockingStatistics> statistics = new LinkedList<>(); - Matcher matcher = RTM_LOCKING_STATISTICS_PATTERN.matcher(str); - - while (matcher.find()) { - RTMLockingStatistics lock = new RTMLockingStatistics(matcher); - statistics.add(lock); - } - - return statistics; - } - - /** - * Parses string and return all founded RTM locking statistics entries - * for locks in method {@code methodName}. - * - * @param methodName a name of the method for locks from which statistics - * should be gathered. - * @param str the string to be parsed. - * @return list with all founded RTM locking statistics entries or - * empty list if nothing was found. - */ - public static List<RTMLockingStatistics> fromString(String methodName, - String str) { - String formattedMethodName = formatMethodName(methodName); - - List<RTMLockingStatistics> statisticsForMethod = new LinkedList<>(); - for (RTMLockingStatistics statistics : fromString(str)) { - if (statistics.getLockName().startsWith(formattedMethodName)) { - statisticsForMethod.add(statistics); - } - } - return statisticsForMethod; - } - - /** - * Formats method's name so it will have the same format as - * in rtm locking statistics. - * - * <pre> - * Example: - * com/example/Klass::method => com/example/Klass.method - * com/example/Klass.method => com/example/Klass.method - * com.example.Klass::method => com/example/Klass.method - * com.example.Klass.method => com/example/Klass.method - * </pre> - * - * @param methodName method's name that should be formatted. - * @return formatted method's name. - */ - private static String formatMethodName(String methodName) { - String m[]; - if (methodName.contains("::")) { - m = methodName.split("::"); - } else { - int splitAt = methodName.lastIndexOf('.'); - m = new String[2]; - m[0] = methodName.substring(0, splitAt); - m[1] = methodName.substring(splitAt + 1); - } - return String.format("%s.%s", m[0].replaceAll("\\.", "/"), m[1]); - } - - /** - * Returns name of lock for which this statistics was collected. - * Lock name has following format: - * <class name>.<method name>@<bci> - * - * @return name of lock. - */ - public String getLockName() { - return String.format("%s.%s@%d", className, methodName, bci); - } - - /** - * Returns aborts count for specified abort type. - * - * @param type an abort type. - * @return count of aborts. - */ - public long getAborts(AbortType type) { - return aborts.getOrDefault(type, 0L); - } - - /** - * Sets aborts count for specified abort type. - * - * @param type an abort type. - * @param count count of aborts. - */ - public void setAborts(AbortType type, long count) { - aborts.put(type, count); - } - - public long getTotalLocks() { - return totalLocks; - } - - public long getTotalAborts() { - return totalAborts; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(getLockName()).append('\n'); - builder.append(String.format("# rtm locks total (estimated): %d\n", - getTotalLocks())); - builder.append(String.format("# rtm lock aborts: %d\n", - getTotalLocks())); - - for (AbortType type : AbortType.values()) { - builder.append(String.format("# rtm lock aborts %s %d\n", - type.toString(), getAborts(type))); - } - return builder.toString(); - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/RTMTestBase.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/RTMTestBase.java deleted file mode 100644 index b6535e65428..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/RTMTestBase.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. - * 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 compiler.testlibrary.rtm; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.Utils; -import jdk.test.lib.cli.CommandLineOptionTest; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Auxiliary methods used for RTM testing. - */ -public class RTMTestBase { - private static final String RTM_STATE_CHANGE_REASON = "rtm_state_change"; - /** - * We don't parse compilation log as XML-document and use regular - * expressions instead, because in some cases it could be - * malformed. - */ - private static final String FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE - = "<uncommon_trap thread='[0-9]+' reason='%s'"; - private static final String INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE - = "<uncommon_trap bci='[0-9]+' reason='%s'"; - - /** - * Executes RTM test in a new JVM started with {@code options} cli options. - * - * @param test test case to execute. - * @param options additional options for VM - * @throws Exception when something went wrong. - */ - public static OutputAnalyzer executeRTMTest(CompilableTest test, - String... options) throws Exception { - ProcessBuilder processBuilder - = ProcessTools.createLimitedTestJavaProcessBuilder( - RTMTestBase.prepareTestOptions(test, options)); - OutputAnalyzer outputAnalyzer - = new OutputAnalyzer(processBuilder.start()); - System.out.println(outputAnalyzer.getOutput()); - return outputAnalyzer; - } - - /** - * Executes test case and save compilation log to {@code logFileName}. - * - * @param logFileName a name of compilation log file - * @param test a test case to execute case to execute - * @param options additional options to VM - * @return OutputAnalyzer for started test case - * @throws Exception when something went wrong - */ - public static OutputAnalyzer executeRTMTest(String logFileName, - CompilableTest test, String... options) throws Exception { - ProcessBuilder processBuilder - = ProcessTools.createLimitedTestJavaProcessBuilder( - RTMTestBase.prepareTestOptions(logFileName, test, options)); - OutputAnalyzer outputAnalyzer - = new OutputAnalyzer(processBuilder.start()); - - System.out.println(outputAnalyzer.getOutput()); - - return outputAnalyzer; - } - - /** - * Finds count of uncommon traps with reason {@code reason} installed - * during compilation. - * - * @param compilationLogFile a path to file with LogCompilation output. - * @param reason reason of installed uncommon traps. - * @return count of installed uncommon traps with reason {@code reason}. - * @throws IOException - */ - public static int installedUncommonTraps(String compilationLogFile, - String reason)throws IOException { - String pattern = String.format( - RTMTestBase.INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE, - reason); - return RTMTestBase.findTraps(compilationLogFile, pattern); - } - - /** - * Finds count of uncommon traps with reason <i>rtm_state_change</i> - * installed during compilation. - * - * @param compilationLogFile a path to file with LogCompilation output. - * @return count of installed uncommon traps with reason - * <i>rtm_state_change</i>. - * @throws IOException - */ - public static int installedRTMStateChangeTraps(String compilationLogFile) - throws IOException { - return RTMTestBase.installedUncommonTraps(compilationLogFile, - RTMTestBase.RTM_STATE_CHANGE_REASON); - } - - /** - * Finds count of fired uncommon traps with reason {@code reason}. - * - * @param compilationLogFile a path to file with LogCompilation output. - * @param reason a reason of fired uncommon traps. - * @return count of fired uncommon traps with reason {@code reason}. - * @throws IOException - */ - public static int firedUncommonTraps(String compilationLogFile, - String reason) throws IOException { - String pattern = String.format( - RTMTestBase.FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE, - reason); - return RTMTestBase.findTraps(compilationLogFile, pattern); - } - - /** - * Finds count of fired uncommon traps with reason <i>rtm_state_change</i>. - * - * @param compilationLogFile a path to file with LogCompilation output. - * @return count of fired uncommon traps with reason - * <i>rtm_state_change</i>. - * @throws IOException - */ - public static int firedRTMStateChangeTraps(String compilationLogFile) - throws IOException { - return RTMTestBase.firedUncommonTraps(compilationLogFile, - RTMTestBase.RTM_STATE_CHANGE_REASON); - } - - /** - * Finds count of uncommon traps that matches regular - * expression in {@code re}. - * - * @param compilationLogFile a path to file with LogCompilation output. - * @param re regular expression to match uncommon traps. - * @throws IOException - */ - private static int findTraps(String compilationLogFile, String re) - throws IOException { - String compilationLog = RTMTestBase.fileAsString(compilationLogFile); - Pattern pattern = Pattern.compile(re); - Matcher matcher = pattern.matcher(compilationLog); - int traps = 0; - while (matcher.find()) { - traps++; - } - return traps; - } - - /** - * Returns file's content as a string. - * - * @param path a path to file to operate on. - * @return string with content of file. - * @throws IOException - */ - private static String fileAsString(String path) throws IOException { - byte[] fileAsBytes = Files.readAllBytes(Paths.get(path)); - return new String(fileAsBytes); - } - - /** - * Prepares VM options for test execution. - * This method get test java options, filter out all RTM-related options, - * adds CompileCommand=compileonly,method_name options for each method - * from {@code methodToCompile} and finally appends all {@code vmOpts}. - * - * @param test test case whose methods that should be compiled. - * If {@code null} then no additional <i>compileonly</i> - * commands will be added to VM options. - * @param vmOpts additional options to pass to VM. - * @return Array with VM options. - */ - private static String[] prepareTestOptions(CompilableTest test, - String... vmOpts) { - return RTMTestBase.prepareFilteredTestOptions(test, null, vmOpts); - } - - /** - * Prepares VM options for test execution. - * This method get test java options, filter out all RTM-related options - * and all options that matches regexps in {@code additionalFilters}, - * adds CompileCommand=compileonly,method_name options for each method - * from {@code methodToCompile} and finally appends all {@code vmOpts}. - * - * @param test test case whose methods that should be compiled. - * If {@code null} then no additional <i>compileonly</i> - * commands will be added to VM options. - * @param additionalFilters array with regular expression that will be - * used to filter out test java options. - * If {@code null} then no additional filters - * will be used. - * @param vmOpts additional options to pass to VM. - * @return array with VM options. - */ - private static String[] prepareFilteredTestOptions(CompilableTest test, - String[] additionalFilters, String... vmOpts) { - List<String> finalVMOpts = new LinkedList<>(); - String[] filters; - - if (additionalFilters != null) { - filters = Arrays.copyOf(additionalFilters, - additionalFilters.length + 1); - } else { - filters = new String[1]; - } - - filters[filters.length - 1] = "RTM"; - String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters); - Collections.addAll(finalVMOpts, filteredVMOpts); - Collections.addAll(finalVMOpts, "-Xcomp", "-server", - "-XX:-TieredCompilation", "-XX:+UseRTMLocking", - CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI", - "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"); - - if (test != null) { - for (String method : test.getMethodsToCompileNames()) { - finalVMOpts.add("-XX:CompileCommand=compileonly," + method); - } - } - Collections.addAll(finalVMOpts, vmOpts); - return finalVMOpts.toArray(new String[finalVMOpts.size()]); - } - - /** - * Adds additional options for VM required for successful execution of test. - * - * @param logFileName a name of compilation log file - * @param test a test case to execute - * @param options additional options to VM - * @return an array with VM options - */ - private static String[] prepareTestOptions(String logFileName, - CompilableTest test, String... options) { - String[] preparedOptions = RTMTestBase.prepareFilteredTestOptions( - test, - new String[] { - "LogCompilation", - "LogFile" - }); - List<String> updatedOptions = new LinkedList<>(); - Collections.addAll(updatedOptions, preparedOptions); - Collections.addAll(updatedOptions, - "-XX:+LogCompilation", - "-XX:LogFile=" + logFileName); - Collections.addAll(updatedOptions, options); - - return updatedOptions.toArray(new String[updatedOptions.size()]); - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/XAbortProvoker.java b/test/hotspot/jtreg/compiler/testlibrary/rtm/XAbortProvoker.java deleted file mode 100644 index 23b7b779288..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/XAbortProvoker.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 compiler.testlibrary.rtm; - -/** - * Current RTM locking implementation force transaction abort - * before native method call by explicit xabort(0) call. - */ -public class XAbortProvoker extends AbortProvoker { - - static { - try { - System.loadLibrary("XAbortProvoker"); - } catch (UnsatisfiedLinkError e) { - System.out.println("Could not load native library: " + e); - } - } - - public native int doAbort(); - - // Following field have to be static in order to avoid escape analysis. - @SuppressWarnings("UnsuedDeclaration") - private static int field = 0; - - public XAbortProvoker() { - this(new Object()); - } - - public XAbortProvoker(Object monitor) { - super(monitor); - } - - @Override - public void forceAbort() { - synchronized(monitor) { - XAbortProvoker.field = doAbort(); - } - } - - @Override - public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - XAbortProvoker.class.getName() + "::doAbort" - }; - } -} diff --git a/test/hotspot/jtreg/compiler/testlibrary/rtm/libXAbortProvoker.c b/test/hotspot/jtreg/compiler/testlibrary/rtm/libXAbortProvoker.c deleted file mode 100644 index b87882771d4..00000000000 --- a/test/hotspot/jtreg/compiler/testlibrary/rtm/libXAbortProvoker.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 "jni.h" - -/** - * Simply calling a JNI method from the JVM will abort any active transaction, - * so doAbort() does nothing special and only returns after being called. - * The transaction abortion happens right before the JNI method is called. - */ -JNIEXPORT int JNICALL -Java_compiler_testlibrary_rtm_XAbortProvoker_doAbort(JNIEnv *env, jobject o) { - return 0; -} diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java new file mode 100644 index 00000000000..549d9aa5d49 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024, Arm Limited. All rights reserved. + * 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 compiler.vectorapi; + +import compiler.lib.ir_framework.*; + +import jdk.incubator.vector.DoubleVector; +import jdk.incubator.vector.FloatVector; +import jdk.incubator.vector.VectorOperators; +import jdk.incubator.vector.VectorSpecies; + +import java.util.Random; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; + +/** + * @test + * @bug 8320725 + * @library /test/lib / + * @summary Verify non-strictly ordered AddReductionVF/VD and MulReductionVF/VD + * nodes are generated in VectorAPI + * @modules jdk.incubator.vector + * @run driver compiler.vectorapi.TestVectorAddMulReduction + */ + +public class TestVectorAddMulReduction { + + private static final int SIZE = 1024; + private static final Random RD = Utils.getRandomInstance(); + + private static float[] fa; + private static float fres; + private static double[] da; + private static double dres; + + static { + fa = new float[SIZE]; + da = new double[SIZE]; + fres = 1; + dres = 1; + for (int i = 0; i < SIZE; i++) { + fa[i] = RD.nextFloat(); + da[i] = RD.nextDouble(); + } + } + + // Test add reduction operation for floats + @ForceInline + public static void testFloatAddKernel(VectorSpecies SPECIES, float[] f) { + for (int i = 0; i < SPECIES.loopBound(f.length); i += SPECIES.length()) { + var av = FloatVector.fromArray(SPECIES, f, i); + fres += av.reduceLanes(VectorOperators.ADD); + } + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VF, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=8"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testFloatAdd_64() { + testFloatAddKernel(FloatVector.SPECIES_64, fa); + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VF, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=16"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testFloatAdd_128() { + testFloatAddKernel(FloatVector.SPECIES_128, fa); + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VF, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=32"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testFloatAdd_256() { + testFloatAddKernel(FloatVector.SPECIES_256, fa); + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VF, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=64"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testFloatAdd_512() { + testFloatAddKernel(FloatVector.SPECIES_512, fa); + } + + // Test add reduction operation for doubles + @ForceInline + public static void testDoubleAddKernel(VectorSpecies SPECIES, double[] d) { + for (int i = 0; i < SPECIES.loopBound(d.length); i += SPECIES.length()) { + var av = DoubleVector.fromArray(SPECIES, d, i); + dres += av.reduceLanes(VectorOperators.ADD); + } + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VD, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=16"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testDoubleAdd_128() { + testDoubleAddKernel(DoubleVector.SPECIES_128, da); + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VD, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=32"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testDoubleAdd_256() { + testDoubleAddKernel(DoubleVector.SPECIES_256, da); + } + + @Test + @IR(counts = {IRNode.ADD_REDUCTION_VD, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=64"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testDoubleAdd_512() { + testDoubleAddKernel(DoubleVector.SPECIES_512, da); + } + + // Test mul reduction operation for floats + // On aarch64, there are no direct vector mul reduction instructions for float/double mul reduction + // and scalar instructions are emitted for 64-bit/128-bit vectors. Thus MulReductionVF/VD nodes are generated + // only for vector length of 8B/16B on vectorAPI. + @ForceInline + public static void testFloatMulKernel(VectorSpecies SPECIES, float[] f) { + for (int i = 0; i < SPECIES.loopBound(f.length); i += SPECIES.length()) { + var av = FloatVector.fromArray(SPECIES, f, i); + fres += av.reduceLanes(VectorOperators.MUL); + } + } + + @Test + @IR(counts = {IRNode.MUL_REDUCTION_VF, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=8"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testFloatMul_64() { + testFloatMulKernel(FloatVector.SPECIES_64, fa); + } + + @Test + @IR(counts = {IRNode.MUL_REDUCTION_VF, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=16"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testFloatMul_128() { + testFloatMulKernel(FloatVector.SPECIES_128, fa); + } + + // Test mul reduction operation for doubles + @ForceInline + public static void testDoubleMulKernel(VectorSpecies SPECIES, double[] d) { + for (int i = 0; i < SPECIES.loopBound(d.length); i += SPECIES.length()) { + var av = DoubleVector.fromArray(SPECIES, d, i); + dres += av.reduceLanes(VectorOperators.MUL); + } + } + + @Test + @IR(counts = {IRNode.MUL_REDUCTION_VD, ">=1", "no_strict_order", ">=1"}, + failOn = {"requires_strict_order"}, + applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + applyIf = {"MaxVectorSize", ">=16"}, + phase = CompilePhase.PRINT_IDEAL) + public static void testDoubleMul_128() { + testDoubleMulKernel(DoubleVector.SPECIES_128, da); + } + + public static void main(String[] args) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + } +} diff --git a/test/hotspot/jtreg/serviceability/dcmd/thread/PrintMountedVirtualThread.java b/test/hotspot/jtreg/serviceability/dcmd/thread/PrintMountedVirtualThread.java new file mode 100644 index 00000000000..bffe4c266a4 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/dcmd/thread/PrintMountedVirtualThread.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.JMXExecutor; +import jdk.test.lib.process.OutputAnalyzer; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; + +/* + * @test + * @summary Test of diagnostic command Thread.print with virtual threads + * @requires vm.continuations + * @library /test/lib + * @run junit PrintMountedVirtualThread + */ +public class PrintMountedVirtualThread { + + public void run(CommandExecutor executor) throws InterruptedException { + var shouldFinish = new AtomicBoolean(false); + var started = new CountDownLatch(1); + final Runnable runnable = new DummyRunnable(shouldFinish, started); + try { + Thread vthread = Thread.ofVirtual().name("Dummy Vthread").start(runnable); + started.await(); + /* Execute */ + OutputAnalyzer output = executor.execute("Thread.print"); + output.shouldMatch(".*at " + Pattern.quote(DummyRunnable.class.getName()) + "\\.run.*"); + output.shouldMatch(".*at " + Pattern.quote(DummyRunnable.class.getName()) + "\\.compute.*"); + output.shouldMatch("Mounted virtual thread " + "\"Dummy Vthread\"" + " #" + vthread.threadId()); + + } finally { + shouldFinish.set(true); + } + } + + @Test + public void jmx() throws InterruptedException { + run(new JMXExecutor()); + } + + static class DummyRunnable implements Runnable { + + private final AtomicBoolean shouldFinish; + private final CountDownLatch started; + + public DummyRunnable(AtomicBoolean shouldFinish, CountDownLatch started) { + this.shouldFinish = shouldFinish; + this.started = started; + } + + public void run() { + compute(); + } + + void compute() { + started.countDown(); + while (!shouldFinish.get()) { + Thread.onSpinWait(); + } + } + } + + +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/FollowReferences/FieldIndices/libFieldIndicesTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/FollowReferences/FieldIndices/libFieldIndicesTest.cpp index b8d83eb5085..6bcbab3f941 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/FollowReferences/FieldIndices/libFieldIndicesTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/FollowReferences/FieldIndices/libFieldIndicesTest.cpp @@ -273,7 +273,9 @@ void Klass::explore_interfaces(JNIEnv* env) { if (super_klass != nullptr) { // Add all interfaces implemented by super_klass first. interface_count = super_klass->interface_count; - memcpy(interfaces, super_klass->interfaces, sizeof(Klass*) * super_klass->interface_count); + if (super_klass->interfaces != nullptr) { + memcpy(interfaces, super_klass->interfaces, sizeof(Klass*) * super_klass->interface_count); + } } // Interfaces implemented by the klass. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001.java index 60ae805703b..5af71d569f1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,10 @@ public class getvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java index 4fc9630df3c..04ddee42061 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ArrayReference.GetValues.getvalues001a - * @run main/othervm + * @run driver * nsk.jdwp.ArrayReference.GetValues.getvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002.java index 47f4097dae6..d5d44faef48 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,7 +116,10 @@ public class getvalues002 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java index 92b567dccf2..5e1e30ae541 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/GetValues/getvalues002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ArrayReference.GetValues.getvalues002a - * @run main/othervm + * @run driver * nsk.jdwp.ArrayReference.GetValues.getvalues002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001.java index 36324982533..45acc929bfa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,10 @@ public class length001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java index 164d8c8ecab..2f96d7c3a07 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/Length/length001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ArrayReference.Length.length001a - * @run main/othervm + * @run driver * nsk.jdwp.ArrayReference.Length.length001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java index 117d66fe24c..12c06d8735d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,7 +92,10 @@ public class setvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java index 380ba4549ef..bf252a44d43 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ArrayReference.SetValues.setvalues001a - * @run main/othervm + * @run driver * nsk.jdwp.ArrayReference.SetValues.setvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001.java index c56ccde4c2f..b29a39fb4c5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,10 @@ public class newinstance001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java index 7376e32c3cc..66b15f21665 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayType/NewInstance/newinstance001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ArrayType.NewInstance.newinstance001a - * @run main/othervm + * @run driver * nsk.jdwp.ArrayType.NewInstance.newinstance001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001.java index ba21914994d..1c02b225e0b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,10 @@ public class visibclasses001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java index b298e05d721..379091615fe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassLoaderReference/VisibleClasses/visibclasses001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ClassLoaderReference.VisibleClasses.visibclasses001a - * @run main/othervm + * @run driver * nsk.jdwp.ClassLoaderReference.VisibleClasses.visibclasses001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001.java index b894d10c1b0..a23144b50e6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,10 @@ public class reflectype001 { static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java index f476b8df0c8..ea86ce80bcb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassObjectReference/ReflectedType/reflectype001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ClassObjectReference.ReflectedType.reflectype001a - * @run main/othervm + * @run driver * nsk.jdwp.ClassObjectReference.ReflectedType.reflectype001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java index d9f5e31b653..c5ab5ed56c8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,7 +97,10 @@ public class invokemeth001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java index 9b97c95b32f..c393e091c56 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ClassType.InvokeMethod.invokemeth001a - * @run main/othervm + * @run driver * nsk.jdwp.ClassType.InvokeMethod.invokemeth001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java index ff23a6420e6..a2323daaf74 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,8 +96,11 @@ public class newinst001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java index 6132dbc6a4d..2d9abe94b73 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ClassType.NewInstance.newinst001a - * @run main/othervm + * @run driver * nsk.jdwp.ClassType.NewInstance.newinst001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java index 7931560a853..e40906c299a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,10 @@ public class setvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java index 24b11421e08..015e3377537 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/SetValues/setvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ClassType.SetValues.setvalues001a - * @run main/othervm + * @run driver * nsk.jdwp.ClassType.SetValues.setvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001.java index 1e46507079e..4aed67d1f7e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,10 @@ public class superclass001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java index 02082032398..6cd1cd94042 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/Superclass/superclass001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ClassType.Superclass.superclass001a - * @run main/othervm + * @run driver * nsk.jdwp.ClassType.Superclass.superclass001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001.java index 60b926256ad..6518ff5bb06 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,8 +90,11 @@ public class breakpoint001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java index f4583fc1015..72c5a23c94f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/BREAKPOINT/breakpoint001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.BREAKPOINT.breakpoint001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.BREAKPOINT.breakpoint001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001.java index 4bb0add7c65..3edb73a609c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,8 +80,11 @@ public class clsprepare001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java index 8690a9d6125..563db722424 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_PREPARE/clsprepare001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.CLASS_PREPARE.clsprepare001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.CLASS_PREPARE.clsprepare001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001.java index ba6905a68bd..ccfec8efeb9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,8 +80,11 @@ public class clsunload001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java index 2d323c71931..354b71a085e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/CLASS_UNLOAD/clsunload001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.CLASS_UNLOAD.clsunload001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.CLASS_UNLOAD.clsunload001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001.java index 0d6c11c40c8..789402dd37a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,8 +75,11 @@ public class composite001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java index 5cf8976cb88..ad91d73534c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/Composite/composite001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.Composite.composite001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.Composite.composite001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001.java index 2092256ef6c..0fca4cb44f9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,8 +97,11 @@ public class exception001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java index 9524d171c4b..7307c026cf5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/EXCEPTION/exception001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.EXCEPTION.exception001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.EXCEPTION.exception001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001.java index c81d901115c..1c6b5f4a931 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,8 +99,11 @@ public class fldaccess001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java index d0c835009d6..ff74b0849ee 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_ACCESS/fldaccess001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.FIELD_ACCESS.fldaccess001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.FIELD_ACCESS.fldaccess001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001.java index 7bcf14c87c3..840b48428e5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,8 +100,11 @@ public class fldmodification001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java index 5055936173d..3901a6eaf8c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/FIELD_MODIFICATION/fldmodification001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.FIELD_MODIFICATION.fldmodification001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.FIELD_MODIFICATION.fldmodification001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001.java index 6d75896e2df..b8834e94bcf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,8 +92,11 @@ public class methentry001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java index e41084de628..106002fdf9d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_ENTRY/methentry001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.METHOD_ENTRY.methentry001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.METHOD_ENTRY.methentry001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001.java index a113161ca32..6da08d6b858 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,8 +92,11 @@ public class methexit001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java index bd765e2ea88..e6a74885a13 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/METHOD_EXIT/methexit001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.METHOD_EXIT.methexit001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.METHOD_EXIT.methexit001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001.java index 25003f018a0..fef8a095908 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,8 +93,11 @@ public class singlestep001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java index 7d7afefd446..661189bcf31 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.SINGLE_STEP.singlestep001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.SINGLE_STEP.singlestep001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002.java index 50e55925d0d..66c9e65df56 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,8 +95,11 @@ public class singlestep002 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java index ac11ead1f09..4fe15d10884 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.SINGLE_STEP.singlestep002a - * @run main/othervm + * @run driver * nsk.jdwp.Event.SINGLE_STEP.singlestep002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003.java index ae98242c0ee..47ef6474536 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,8 +95,11 @@ public class singlestep003 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java index 00cf70a223d..d3c38bcbeb8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/SINGLE_STEP/singlestep003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.SINGLE_STEP.singlestep003a - * @run main/othervm + * @run driver * nsk.jdwp.Event.SINGLE_STEP.singlestep003 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001.java index f5aae7067db..753e5b49480 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,11 @@ public class thrdeath001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java index 85dd77be7e9..8cd28cb2381 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_DEATH/thrdeath001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.THREAD_DEATH.thrdeath001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.THREAD_DEATH.thrdeath001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001.java index f525d7d550f..7936fcbf5cb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,11 @@ public class thrstart001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java index a4350324849..7345debf525 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/THREAD_START/thrstart001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.THREAD_START.thrstart001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.THREAD_START.thrstart001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001.java index 771e121d8ce..8a8526bbeb2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,11 @@ public class vmdeath001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java index e1f3b1053b4..f40ecc66655 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.VM_DEATH.vmdeath001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.VM_DEATH.vmdeath001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002.java index 20f96d064d1..6bfb79d2575 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,8 +81,11 @@ public class vmdeath002 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java index f0dbd749a32..cee21042bf5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_DEATH/vmdeath002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.VM_DEATH.vmdeath002a - * @run main/othervm + * @run driver * nsk.jdwp.Event.VM_DEATH.vmdeath002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001.java index 58d77cd8901..eac5ee3efb6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,11 @@ public class vmstart001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java index 139db45bef5..b0d6abd6928 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Event/VM_START/vmstart001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Event.VM_START.vmstart001a - * @run main/othervm + * @run driver * nsk.jdwp.Event.VM_START.vmstart001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001.java index 4973cac34a7..dccddcf8066 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,11 @@ public class clear001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java index acc4090eb10..cc544397bf2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Clear/clear001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.EventRequest.Clear.clear001a - * @run main/othervm + * @run driver * nsk.jdwp.EventRequest.Clear.clear001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001.java index b4cbd4f2072..166334be16a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,11 @@ public class clrallbreakp001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java index 49c6d12afa5..bd251fe9c91 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp001a - * @run main/othervm + * @run driver * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002.java index c106daa64ff..1a881b075f1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,8 +82,11 @@ public class clrallbreakp002 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java index 981b8fccb5e..53fa51809db 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp002a - * @run main/othervm + * @run driver * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003.java index 34a69758774..ce7c1f6609f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,11 @@ public class clrallbreakp003 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java index 15acb91350c..61c2355c1cb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/ClearAllBreakpoints/clrallbreakp003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp003a - * @run main/othervm + * @run driver * nsk.jdwp.EventRequest.ClearAllBreakpoints.clrallbreakp003 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001.java index 522c6096cdf..55b5d12ee13 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,8 +90,11 @@ public class set001 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java index d04dc2f9328..d982e35850d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.EventRequest.Set.set001a - * @run main/othervm + * @run driver * nsk.jdwp.EventRequest.Set.set001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002.java index ae25ddc2fe2..86256e706fc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,8 +77,11 @@ public class set002 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java index efd3b666924..38df090783b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/EventRequest/Set/set002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.EventRequest.Set.set002a - * @run main/othervm + * @run driver * nsk.jdwp.EventRequest.Set.set002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001.java index 29a06be58fc..7a597286034 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,10 @@ public class bytecodes001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java index b522bbedaa4..46efecf437e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/Bytecodes/bytecodes001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Method.Bytecodes.bytecodes001a - * @run main/othervm + * @run driver * nsk.jdwp.Method.Bytecodes.bytecodes001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001.java index c9e558363a2..b01e814af1e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,10 @@ public class isobsolete001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java index c3b3b3c049d..270f5744bac 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Method.IsObsolete.isobsolete001a - * @run main/othervm + * @run driver * nsk.jdwp.Method.IsObsolete.isobsolete001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002.java index c3266489f92..c06e62be316 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,10 @@ public class isobsolete002 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java index ce9fc223dae..e5b41793291 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/IsObsolete/isobsolete002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,7 @@ * nsk.jdwp.Method.IsObsolete.isobsolete002b * @run driver nsk.share.ExtraClassesBuilder * newclass - * @run main/othervm + * @run driver * nsk.jdwp.Method.IsObsolete.isobsolete002 * . * -arch=${os.family}-${os.simpleArch} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001.java index ebb30638938..cf1bd6eb79a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,10 @@ public class linetable001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java index d5dad5cc979..7a53a1b3816 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/LineTable/linetable001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.Method.LineTable.linetable001a - * @run main/othervm + * @run driver * nsk.jdwp.Method.LineTable.linetable001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001.java index 9953dc9c94f..d6a2dcee264 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,7 +119,10 @@ public class vartable001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java index f5633b360f3..f08b09e5079 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTable/vartable001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @comment debuggee should be compiled w/ debug info * @clean nsk.jdwp.Method.VariableTable.vartable001a * @compile -g:lines,source,vars ../vartable001a.java - * @run main/othervm + * @run driver * nsk.jdwp.Method.VariableTable.vartable001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001.java index a2e18c4f759..39890990b8d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,7 +136,10 @@ public class vartblwithgen001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java index 7741b022618..0227cae87ea 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/Method/VariableTableWithGeneric/vartblwithgen001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @comment debuggee should be compiled w/ debug info * @clean nsk.jdwp.Method.VariableTableWithGeneric.vartblwithgen001a * @compile -g:lines,source,vars ../vartblwithgen001a.java - * @run main/othervm + * @run driver * nsk.jdwp.Method.VariableTableWithGeneric.vartblwithgen001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001.java index 419d944398a..6f11394db53 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,10 @@ public class disablecol001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java index 9e50200593e..fdcc258523e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/DisableCollection/disablecol001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.DisableCollection.disablecol001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.DisableCollection.disablecol001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001.java index 2ab8c28e1c4..9172b4413d7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,10 @@ public class enablecol001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java index d2dd41472e9..71a849b0c2a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/EnableCollection/enablecol001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.EnableCollection.enablecol001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.EnableCollection.enablecol001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java index 08668e91afa..9702cb7f9e6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,7 +99,10 @@ public class getvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java index 7ecb552e6c9..8bfbca6d448 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.GetValues.getvalues001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.GetValues.getvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java index 761a5bf19a4..ffc2cc151a9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,7 +99,10 @@ public class invokemeth001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java index 71bfafa7718..3ad6bbf79db 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.InvokeMethod.invokemeth001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.InvokeMethod.invokemeth001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001.java index 284765bd25a..a8d61451f9a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,10 @@ public class iscollected001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java index fda668d8b32..f6facbb7609 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/IsCollected/iscollected001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.IsCollected.iscollected001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.IsCollected.iscollected001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001.java index 8834b30e21b..e50dc29b151 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,10 @@ public class monitorinfo001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java index cf58779b87d..40be209f16f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/MonitorInfo/monitorinfo001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.MonitorInfo.monitorinfo001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.MonitorInfo.monitorinfo001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001.java index cc5530cf82a..4066c905768 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,10 @@ public class referencetype001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java index 0e7e8b9bb6b..e5b1413f147 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferenceType/referencetype001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.ReferenceType.referencetype001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.ReferenceType.referencetype001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java index c9ee73fa67c..f578d3be7d4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects001/referringObjects001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,8 +95,11 @@ protected String getDebugeeClassName() { return nsk.jdwp.ObjectReference.ReferringObjects.referringObjects001.referringObjects001a.class.getName(); } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java index 4ad6b6ae328..4591bf093ea 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/ReferringObjects/referringObjects002/referringObjects002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,8 +83,11 @@ protected String getDebugeeClassName() { return nsk.jdwp.ObjectReference.ReferringObjects.referringObjects002.referringObjects002a.class.getName(); } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java index 3d20db7fa7e..d9a7622ea04 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,10 @@ public class setvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java index e3c08d68b02..e35ea563262 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/SetValues/setvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ObjectReference.SetValues.setvalues001a - * @run main/othervm + * @run driver * nsk.jdwp.ObjectReference.SetValues.setvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001.java index 23b1c3de7ee..0d7961924f9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,10 @@ public class classloader001 { static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java index be36b5eccee..6b818c0a408 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassLoader/classloader001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.ClassLoader.classloader001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.ClassLoader.classloader001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001.java index b86d17d752f..5d74b011111 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,10 @@ public class classobj001 { static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java index 12baa51bca2..ffa15c1a66d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/ClassObject/classobj001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.ClassObject.classobj001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.ClassObject.classobj001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001.java index b6f559a5ae0..a4cfd9d9eba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,10 @@ public class fields001 { static final int FIELD_MODIFIER_FLAGS = JDWP.ModifierFlag.PUBLIC; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java index a337e6b7fb5..7d6b41cc750 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Fields/fields001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.Fields.fields001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Fields.fields001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001.java index 24ac7321b9f..5feafc3c2b3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,8 +101,11 @@ public class fldwithgeneric001 { static final int FLDS_NUM = fields.length; - public static void main(String argv[]) { - System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java index c410dabad08..7e9679e10eb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/FieldsWithGeneric/fldwithgeneric001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.FieldsWithGeneric.fldwithgeneric001t - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.FieldsWithGeneric.fldwithgeneric001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java index cafe1ba1d1a..72c0c679bb8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,7 +99,10 @@ public class getvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java index 6a0ceb754d8..e4c850e28a4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.GetValues.getvalues001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.GetValues.getvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java index 2312f571822..5a83ed4435b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances001/instances001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,8 +89,11 @@ protected String getDebugeeClassName() { return nsk.jdwp.ReferenceType.Instances.instances001.instances001a.class.getName(); } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java index cd90392f3d9..378104a1b74 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Instances/instances002/instances002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Instances.instances002.instances002 * -arch=${os.family}-${os.simpleArch} * -verbose @@ -82,8 +82,11 @@ protected String getDebugeeClassName() { return nsk.jdwp.ReferenceType.Instances.instances002.instances002a.class.getName(); } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001.java index e7e06473d7b..d30d63b272b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,10 @@ public class interfaces001 { static final long interfaceIDs[] = new long[DECLARED_INTERFACES]; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java index b67ad06b1c3..bfa503d42b3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Interfaces/interfaces001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.Interfaces.interfaces001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Interfaces.interfaces001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001.java index 22e656e1f41..247ed13f668 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,10 @@ public class methods001 { static final int METHOD_MODIFIER_FLAGS = JDWP.ModifierFlag.PUBLIC; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java index f24bcd39b84..28a7ad43a60 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Methods/methods001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.Methods.methods001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Methods.methods001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001.java index e2e633222b3..d1536035625 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,8 +110,11 @@ public class methwithgeneric001 { static final int CLS_NUM = classes.length; - public static void main(String argv[]) { - System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java index 648349f887e..475b7eedb05 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/MethodsWithGeneric/methwithgeneric001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.MethodsWithGeneric.methwithgeneric001t - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.MethodsWithGeneric.methwithgeneric001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001.java index 92e4f6f6b7c..7695861df3a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,10 @@ public class modifiers001 { | JDWP.ModifierFlag.FINAL; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java index fa26934f149..907993049a4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Modifiers/modifiers001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.Modifiers.modifiers001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Modifiers.modifiers001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001.java index 33e4727bfe8..6b4e82dd6b6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,7 +92,10 @@ public class nestedtypes001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java index 4436bcccbb6..5da686e4a43 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/NestedTypes/nestedtypes001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.NestedTypes.nestedtypes001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.NestedTypes.nestedtypes001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001.java index 641079ba7fa..ddba04e292a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,10 @@ public class signature001 { static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";"; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java index 27628d13e61..49ac330b518 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Signature/signature001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.Signature.signature001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Signature.signature001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001.java index c6bbcd437f8..8f819a050b9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,8 +81,11 @@ public class sigwithgeneric001 { static final int CLS_NUM = classes.length; - public static void main(String argv[]) { - System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java index 9dc7275de7d..9928a55505e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SignatureWithGeneric/sigwithgeneric001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.SignatureWithGeneric.sigwithgeneric001t - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.SignatureWithGeneric.sigwithgeneric001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001.java index af9d7a26021..0735246d239 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,10 @@ public class srcdebugext001 { private Transport transport; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java index c614604e55d..f3fbe8830c4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceDebugExtension/srcdebugext001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.SourceDebugExtension.srcdebugext001t - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.SourceDebugExtension.srcdebugext001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001.java index fb9d8948ef5..6ca69c009b2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,10 @@ public class srcfile001 { static final String TESTED_CLASS_SRCFILENAME = "srcfile001a.java"; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java index 09608b3757d..ff56e5c99cc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/SourceFile/srcfile001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.SourceFile.srcfile001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.SourceFile.srcfile001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001.java index f0e357b4840..2aa64d3ed4b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,10 @@ public class status001 { | JDWP.ClassStatus.INITIALIZED; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java index aefbb989bf9..5efd81a3896 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/Status/status001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ReferenceType.Status.status001a - * @run main/othervm + * @run driver * nsk.jdwp.ReferenceType.Status.status001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java index 656ba90a250..b9f7a1f0ef3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,10 @@ public class getvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java index 09ee0ba021a..5d862a12ec3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ * @comment debuggee should be compiled w/ debug info * @clean nsk.jdwp.StackFrame.GetValues.getvalues001a * @compile -g:lines,source,vars ../getvalues001a.java - * @run main/othervm + * @run driver * nsk.jdwp.StackFrame.GetValues.getvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001.java index a896d567eb5..b4ad931f044 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,10 @@ public class popframes001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java index 2fd126b9fbb..902cdda31dc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.StackFrame.PopFrames.popframes001a - * @run main/othervm + * @run driver * nsk.jdwp.StackFrame.PopFrames.popframes001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001.java index 58b9c26fae3..7e7d44ff968 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,7 +109,10 @@ public class setvalues001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java index 96302cd9592..fec909b4092 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/SetValues/setvalues001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,7 @@ * @comment debuggee should be compiled w/ debug info * @clean nsk.jdwp.StackFrame.SetValues.setvalues001a * @compile -g:lines,source,vars ../setvalues001a.java - * @run main/othervm + * @run driver * nsk.jdwp.StackFrame.SetValues.setvalues001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001.java index 90ab9f6e06b..d8302f07c7d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,10 @@ public class thisobject001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java index 9216e598b04..7d00be7f307 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/ThisObject/thisobject001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.StackFrame.ThisObject.thisobject001a - * @run main/othervm + * @run driver * nsk.jdwp.StackFrame.ThisObject.thisobject001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001.java index 6a218281473..b07413fae93 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class value001 { static final int JDWP_COMMAND_ID = JDWP.Command.StringReference.Value; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java index ff107802db0..7380eed448d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StringReference/Value/value001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.StringReference.Value.value001a - * @run main/othervm + * @run driver * nsk.jdwp.StringReference.Value.value001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001.java index 5bcf5132863..24e5d1a48d6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class children001 { static final int JDWP_COMMAND_ID = JDWP.Command.ThreadGroupReference.Children; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java index 679af7f78c7..b77233495fd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Children/children001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadGroupReference.Children.children001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadGroupReference.Children.children001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001.java index abb7ed4a59e..c33780bfba0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class name001 { static final int JDWP_COMMAND_ID = JDWP.Command.ThreadGroupReference.Name; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java index 14218e86942..00304ac2b1d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Name/name001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadGroupReference.Name.name001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadGroupReference.Name.name001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001.java index bdcdbc1dd2d..8ebb47b1aea 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class parent001 { static final int JDWP_COMMAND_ID = JDWP.Command.ThreadGroupReference.Parent; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java index 4a2ff8684ac..48aeb6e47d2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadGroupReference/Parent/parent001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadGroupReference.Parent.parent001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadGroupReference.Parent.parent001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001.java index 3b8219e63b7..9d74ebcc081 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,7 +92,10 @@ public class curcontmonitor001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java index 298363ade01..126310353c2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/CurrentContendedMonitor/curcontmonitor001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.CurrentContendedMonitor.curcontmonitor001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.CurrentContendedMonitor.curcontmonitor001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java index 8453e54e2c1..e7dce1525a0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ * * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001 * -arch=${os.family}-${os.simpleArch} * -verbose @@ -123,8 +123,11 @@ protected String getDebugeeClassName() { return "nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn001.forceEarlyReturn001a"; } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java index e66da807669..2cb8de8cfa7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn002/forceEarlyReturn002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,8 +95,11 @@ protected String getDebugeeClassName() { return "nsk.jdwp.ThreadReference.ForceEarlyReturn.forceEarlyReturn002.forceEarlyReturn002a"; } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001.java index 0a6770fe338..5bab037024d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,10 @@ public class framecnt001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java index 16adec92f82..77063a5ce2f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/FrameCount/framecnt001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.FrameCount.framecnt001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.FrameCount.framecnt001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001.java index 42ab3aa776e..0a5028c4a65 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,10 @@ public class frames001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java index d742fb39d0e..b8dad9a09d7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Frames/frames001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Frames.frames001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Frames.frames001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001.java index 722543cf8e1..f0c2914dffc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,10 @@ public class interrupt001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java index 236ff3140d5..b6284ec0a50 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Interrupt/interrupt001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Interrupt.interrupt001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Interrupt.interrupt001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001.java index 5793eb8dc67..4633c6f1185 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,10 @@ public class name001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java index afc50298c1c..ab49aa26e14 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Name/name001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Name.name001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Name.name001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001.java index 75f1dc408e6..c9ba5bcc955 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,7 +98,10 @@ public class ownmonitors001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java index 84c7f627e6d..a929ce527f5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitors/ownmonitors001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.OwnedMonitors.ownmonitors001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.OwnedMonitors.ownmonitors001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java index f178c88ae14..3b250989a43 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo001/ownedMonitorsStackDepthInfo001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,8 +87,11 @@ protected String getDebugeeClassName() { return nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo001.ownedMonitorsStackDepthInfo001a.class.getName(); } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java index cbc5fb63a23..140b249de9c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/OwnedMonitorsStackDepthInfo/ownedMonitorsStackDepthInfo002/ownedMonitorsStackDepthInfo002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.OwnedMonitorsStackDepthInfo.ownedMonitorsStackDepthInfo002.ownedMonitorsStackDepthInfo002 * -arch=${os.family}-${os.simpleArch} * -verbose @@ -77,8 +77,11 @@ protected String getDebugeeClassName() { return AbstractJDWPDebuggee.class.getName(); } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001.java index 94697452200..97e270b32ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,10 @@ public class resume001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java index e5eb1c510f1..12af9f76939 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Resume/resume001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Resume.resume001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Resume.resume001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001.java index b7c708570f5..f41e3e919a5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,10 @@ public class status001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java index 14ff0247143..5ae025526ac 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Status/status001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Status.status001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Status.status001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001.java index f89d64ae747..416b3254e0e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,10 @@ public class stop001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java index 9229392142b..a9bcab6ef3e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Stop/stop001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Stop.stop001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Stop.stop001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001.java index 9f6ed3db961..0418fe080d6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,10 @@ public class suspend001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java index d1477e47749..1c4bcf62e52 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/Suspend/suspend001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.Suspend.suspend001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.Suspend.suspend001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001.java index cbfe330774e..cbdff74e9cc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,10 @@ public class suspendcnt001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java index 39e5469173a..188b5c01ec1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/SuspendCount/suspendcnt001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.SuspendCount.suspendcnt001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.SuspendCount.suspendcnt001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001.java index c58491cb3d4..eb66314ebda 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class threadgroup001 { static final int JDWP_COMMAND_ID = JDWP.Command.ThreadReference.ThreadGroup; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java index f9b503a82fe..0aa449e9239 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ThreadReference/ThreadGroup/threadgroup001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.ThreadReference.ThreadGroup.threadgroup001a - * @run main/othervm + * @run driver * nsk.jdwp.ThreadReference.ThreadGroup.threadgroup001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001.java index 687a56e69fb..292b2d8eb53 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,10 @@ public class allclasses001 { static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001/TestDescription.java index 4f11e1d91bd..85a45c798e6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClasses/allclasses001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.AllClasses.allclasses001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.AllClasses.allclasses001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001.java index c5806ce7b54..aee8b353368 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,8 +87,11 @@ public class allclswithgeneric001 { private Log log; - public static void main(String argv[]) { - System.exit(run(argv,System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001/TestDescription.java index 980bdb98c89..8c251a0ca4b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllClassesWithGeneric/allclswithgeneric001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.AllClassesWithGeneric.allclswithgeneric001t - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.AllClassesWithGeneric.allclswithgeneric001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001.java index e3e291fcdcd..5fa23569fc4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,10 @@ public class allthreads001 { static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java index 782045881ac..6822e5e7b32 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/AllThreads/allthreads001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.AllThreads.allthreads001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.AllThreads.allthreads001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001.java index 5e05f6406f6..e5b11b3be96 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class capabilities001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Capabilities; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java index bba5b1c3015..30ed332c53e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Capabilities/capabilities001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.Capabilities.capabilities001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.Capabilities.capabilities001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001.java index 00ffc505034..1fe5df86db8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class capabilitiesnew001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.CapabilitiesNew; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java index 4d4c69cde63..aa0479c819b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CapabilitiesNew/capabilitiesnew001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.CapabilitiesNew.capabilitiesnew001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.CapabilitiesNew.capabilitiesnew001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001.java index da06f738f93..1882ce81415 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class classpaths001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.ClassPaths; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java index 4f7d685117c..41e53912f20 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassPaths/classpaths001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.ClassPaths.classpaths001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.ClassPaths.classpaths001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001.java index 03fc0c49dca..c319372fc90 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,10 @@ public class classbysig001 { // static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME + ";"; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java index 14f40d16e78..2127c0d3d87 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ClassesBySignature/classbysig001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.ClassesBySignature.classbysig001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.ClassesBySignature.classbysig001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001.java index 5e0a4b8427e..aaa964b4fa3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class createstr001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.CreateString; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java index 54789071b51..27bab252c02 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/CreateString/createstr001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.CreateString.createstr001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.CreateString.createstr001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001.java index e115fa9e648..89b0f608ff7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class dispose001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Dispose; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java index 44b64f614f3..2e3e7d2afcd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Dispose/dispose001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.Dispose.dispose001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.Dispose.dispose001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001.java index 901b69de37a..9c2a0e53478 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,10 @@ public class disposeobj001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java index 3782fc59b3f..5fc151bf339 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/DisposeObjects/disposeobj001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.DisposeObjects.disposeobj001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.DisposeObjects.disposeobj001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001.java index b9313fc838f..f7fd27b03d5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class exit001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Exit; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java index c1fb69e2228..772184d294e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Exit/exit001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.Exit.exit001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.Exit.exit001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001.java index c0b28b905cc..890b1be77bc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,10 @@ public class holdevents001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java index c562dc2e2a6..4f096ee2f49 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.HoldEvents.holdevents001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.HoldEvents.holdevents001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002.java index 2995beb7979..c6e0cc4b014 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/HoldEvents/holdevents002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,8 +87,11 @@ public class holdevents002 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001.java index 49dbbcd1705..863160e6a1f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class idsizes001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.IDSizes; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java index 0dcb07c803b..bf0d6db0f88 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/IDSizes/idsizes001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.IDSizes.idsizes001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.IDSizes.idsizes001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java index e25d2cc3189..dc21d1bc9d3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/InstanceCounts/instanceCounts001/instanceCounts001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,8 +91,11 @@ protected String getDebugeeClassName() { return "nsk.jdwp.VirtualMachine.InstanceCounts.instanceCounts001.instanceCounts001a"; } - public static void main(String[] argv) { - System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String[] argv, PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java index 37cc65ff94e..bc620c8b59c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,10 @@ public class redefinecls001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java index 5ea557b5164..7707821bc79 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/RedefineClasses/redefinecls001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ * nsk.jdwp.VirtualMachine.RedefineClasses.redefinecls001b * @run driver nsk.share.ExtraClassesBuilder * newclass - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.RedefineClasses.redefinecls001 * . * -arch=${os.family}-${os.simpleArch} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001.java index 95bafeb1aff..ddca99b03d3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,10 @@ public class releaseevents001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java index 589d061373d..8cbb7a6e15f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002.java index 64b6ce1547b..ff278aabcf3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,8 +87,11 @@ public class releaseevents002 { /** * Start test from command line. */ - public static void main(String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + public static void main (String argv[]) { + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java index cb6760f9787..1c94d9d7587 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/ReleaseEvents/releaseevents002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents002a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.ReleaseEvents.releaseevents002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001.java index ed427439edc..cb602d17ba0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class resume001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Resume; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java index 14fcd815f28..90b6db41be0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Resume/resume001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.Resume.resume001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.Resume.resume001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001.java index 51e8a03487b..b90423e6219 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,10 @@ public class setdefstrat001 { * Start test from command line. */ public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java index 94828c43d80..43f0a403798 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/SetDefaultStratum/setdefstrat001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.SetDefaultStratum.setdefstrat001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.SetDefaultStratum.setdefstrat001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001.java index e04cb45580c..daaf39cc5fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class threadgroups001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.TopLevelThreadGroups; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java index ecd37d43e84..ac51bc95011 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/TopLevelThreadGroups/threadgroups001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.TopLevelThreadGroups.threadgroups001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.TopLevelThreadGroups.threadgroups001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001.java index b89aa3e0ec0..66575fee4f8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class version001 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Version; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java index c26171f0dec..cd1d7123a34 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.Version.version001a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.Version.version001 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002.java index 5907a8159ff..8060922340c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * 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,7 +42,10 @@ public class version002 { static final int JDWP_COMMAND_ID = JDWP.Command.VirtualMachine.Version; public static void main (String argv[]) { - System.exit(run(argv,System.out) + JCK_STATUS_BASE); + int result = run(argv, System.out); + if (result != 0) { + throw new RuntimeException("Test failed"); + } } public static int run(String argv[], PrintStream out) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java index cfc6ed266c1..d09e4f5176d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/VirtualMachine/Version/version002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase /test/hotspot/jtreg/vmTestbase * /test/lib * @build nsk.jdwp.VirtualMachine.Version.version002a - * @run main/othervm + * @run driver * nsk.jdwp.VirtualMachine.Version.version002 * -arch=${os.family}-${os.simpleArch} * -verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java index b2af4412947..de99ad3686e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,3 +48,10 @@ * @run main/othervm/native -agentlib:setfldw001 nsk.jvmti.SetFieldAccessWatch.setfldw001 */ +/* + * @test id=logging + * + * @library /vmTestbase + * /test/lib + * @run main/othervm/native -agentlib:setfldw001 -XX:TraceJVMTI=ec+,+ioe,+s -Xlog:jvmti=trace:file=vm.%p.log nsk.jvmti.SetFieldAccessWatch.setfldw001 + */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/setfldw001.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/setfldw001.cpp index 57286ce78a0..67d92df6dd2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/setfldw001.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/setfldw001.cpp @@ -26,6 +26,7 @@ #include <ctype.h> #include "jvmti.h" #include "agent_common.hpp" +#include "jvmti_common.hpp" #include "JVMTITools.hpp" extern "C" { @@ -114,6 +115,14 @@ void JNICALL FieldAccess(jvmtiEnv *jvmti_env, JNIEnv *env, } fld_ind = (int)(fld_name[len - 1] - '0'); /* last digit is index in the array */ fields[fld_ind].thrown_fid = field; + + if (field == nullptr) { + fatal(env, "null field ID in FieldModification event."); + } + + LOG("Event: (Field %d) field ID expected: 0x%p, got: 0x%p\n", + fld_ind, fields[fld_ind].fid, field); + jvmti_env->Deallocate((unsigned char*) fld_name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/TestDescription.java index 1decdae357d..d0cbdc288b4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,3 +48,10 @@ * @run main/othervm/native -agentlib:setfmodw001 nsk.jvmti.SetFieldModificationWatch.setfmodw001 */ +/* + * @test id=logging + * + * @library /vmTestbase + * /test/lib + * @run main/othervm/native -agentlib:setfmodw001 -XX:TraceJVMTI=ec+,+ioe,+s -Xlog:jvmti=trace:file=vm.%p.log nsk.jvmti.SetFieldModificationWatch.setfmodw001 + */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/setfmodw001.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/setfmodw001.cpp index 28851bc6838..4e41aa285e3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/setfmodw001.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SetFieldModificationWatch/setfmodw001/setfmodw001.cpp @@ -26,6 +26,7 @@ #include <ctype.h> #include "jvmti.h" #include "agent_common.hpp" +#include "jvmti_common.hpp" #include "JVMTITools.hpp" extern "C" { @@ -108,6 +109,13 @@ void JNICALL FieldModification(jvmtiEnv *jvmti_env, JNIEnv *env, } fld_ind = (int)(fld_name[len - 1] - '0'); /* last digit is index in the array */ fields[fld_ind].thrown_fid = field; + + if (field == nullptr) { + fatal(env, "null field ID in FieldModification event."); + } + LOG("Event: (Field %d) field ID expected: 0x%p, got: 0x%p\n", + fld_ind, fields[fld_ind].fid, field); + jvmti_env->Deallocate((unsigned char*) fld_name); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java index 58732bd0aa4..e3071e5cef0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java @@ -320,11 +320,11 @@ public String[] makeCommandLineArgs(String classToExecute, String transportAddre } } -/* - String classPath = System.getProperty("java.class.path"); - args.add("-classpath") + + String classPath = System.getProperty("test.class.path"); + args.add("-classpath"); args.add(classPath); - */ + String server; if (argumentHandler.isAttachingConnector()) { diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index e2201e9f95c..da674d6a047 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -621,7 +621,9 @@ sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java 8039280 gene sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic-all javax/net/ssl/SSLSession/CertMsgCheck.java 8326705 generic-all -sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8316183 linux-ppc64le +sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8316183,8333317 generic-all + +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#teliasonerarootcav1 8333640 generic-all ############################################################################ diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 25ef8250e4d..bfa99c72b66 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -11,7 +11,7 @@ # # A test flagged with cgroups uses cgroups. # -# Notes on "client" keywords : headful sound printer multimon +# Notes on "client" keywords : headful sound printer multimon # =========================================================== # # These keywords are there to help with test selection so that @@ -31,7 +31,7 @@ # Tests may not fail if there is none, instead just silently return. # But they also may legitimately throw an Exception depending on the test. # Also printer tests are not necessarily headful, but some are, and some are automated. -# +# # "sound". Similarly, not all sound tests require audio devices, but many do. # A test flagged with key "sound" needs audio devices on the system. # Also they are not necessarily "headful", since they don't require a display etc. @@ -99,6 +99,7 @@ requires.properties= \ vm.jvmci \ vm.jvmci.enabled \ vm.jvmti \ + vm.cpu.features \ docker.support \ release.implementor \ jdk.containerized \ diff --git a/test/jdk/com/sun/tools/attach/Agent.java b/test/jdk/com/sun/tools/attach/Agent.java index 9090ea73519..510ff787fa7 100644 --- a/test/jdk/com/sun/tools/attach/Agent.java +++ b/test/jdk/com/sun/tools/attach/Agent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * the given port. */ import java.net.Socket; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.io.IOException; @@ -38,7 +39,7 @@ public static void agentmain(String args) throws IOException { int port = Integer.parseInt(args); System.out.println("Agent connecting back to Tool...."); Socket s = new Socket(); - s.connect( new InetSocketAddress(port) ); + s.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), port)); System.out.println("Agent connected to Tool."); s.close(); } diff --git a/test/jdk/com/sun/tools/attach/BasicTests.java b/test/jdk/com/sun/tools/attach/BasicTests.java index 4dc7065630f..9ae45436810 100644 --- a/test/jdk/com/sun/tools/attach/BasicTests.java +++ b/test/jdk/com/sun/tools/attach/BasicTests.java @@ -23,6 +23,8 @@ import java.io.File; import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.List; @@ -213,7 +215,8 @@ public static void main(String args[]) throws Exception { System.out.println(" - Test: End-to-end connection with agent"); - ServerSocket ss = new ServerSocket(0); + ServerSocket ss = new ServerSocket(); + ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); int port = ss.getLocalPort(); System.out.println(" - Loading Agent.jar into target VM ..."); @@ -231,7 +234,8 @@ public static void main(String args[]) throws Exception { System.out.println(" - Test: End-to-end connection with RedefineAgent"); - ServerSocket ss2 = new ServerSocket(0); + ServerSocket ss2 = new ServerSocket(); + ss2.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); int port2 = ss2.getLocalPort(); System.out.println(" - Loading RedefineAgent.jar into target VM ..."); diff --git a/test/jdk/com/sun/tools/attach/RedefineAgent.java b/test/jdk/com/sun/tools/attach/RedefineAgent.java index af01df42762..cc0e7d269df 100644 --- a/test/jdk/com/sun/tools/attach/RedefineAgent.java +++ b/test/jdk/com/sun/tools/attach/RedefineAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ * 6446941 java.lang.instrument: multiple agent attach fails (first agent chooses capabilities) */ import java.net.Socket; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.io.IOException; import java.util.Arrays; @@ -104,7 +105,7 @@ public static void agentmain(String args, Instrumentation inst) throws Exception int port = Integer.parseInt(args); System.out.println("RedefineAgent connecting back to Tool...."); Socket s = new Socket(); - s.connect( new InetSocketAddress(port) ); + s.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), port)); System.out.println("RedefineAgent connected to Tool."); testRedefine(inst); diff --git a/test/jdk/java/awt/print/PrinterJob/PrintNullString.java b/test/jdk/java/awt/print/PrinterJob/PrintNullString.java index e4323b232a7..397dd2902d1 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintNullString.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintNullString.java @@ -148,7 +148,7 @@ private void paint(Graphics2D g2d) { // API 3: null & empty drawString(Iterator, int, int); try { g2d.drawString(nullIterator, 20, 120); - g2d.drawString("FAILURE: No NPE for null iterator, float", 20, 120); + g2d.drawString("FAILURE: No NPE for null iterator, int", 20, 120); } catch (NullPointerException e) { g2d.drawString("caught expected NPE for null iterator, int", 20, 120); } @@ -169,7 +169,7 @@ private void paint(Graphics2D g2d) { } try { - g2d.drawString(emptyIterator, 20, 180); + g2d.drawString(emptyIterator, 20.0f, 180.0f); g2d.drawString("FAILURE: No IAE for empty iterator, float", 20, 180); } catch (IllegalArgumentException e) { g2d.drawString("caught expected IAE for empty iterator, float", 20, 180); diff --git a/test/jdk/java/io/Console/RestoreEchoTest.java b/test/jdk/java/io/Console/RestoreEchoTest.java new file mode 100644 index 00000000000..78d36faa537 --- /dev/null +++ b/test/jdk/java/io/Console/RestoreEchoTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.Console; +import java.nio.file.Files; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; +import static org.junit.jupiter.api.Assertions.*; + + +/** + * @test + * @bug 8332161 + * @summary Tests JdkConsoleImpl restores the echo state after readPassword() call + * @library /test/lib + * @run junit RestoreEchoTest + */ +public class RestoreEchoTest { + + @Test + @EnabledOnOs({OS.LINUX, OS.MAC}) + public void testRestoreEcho() throws Throwable { + // check "expect" command availability + var expect = Paths.get("/usr/bin/expect"); + if (!Files.exists(expect) || !Files.isExecutable(expect)) { + Assumptions.abort("'" + expect + "' not found"); + } + + expectRunner("-echo"); + expectRunner("echo"); + } + + private static void expectRunner(String initialEcho) throws Throwable { + // invoking "expect" command + var testSrc = System.getProperty("test.src", "."); + var testClasses = System.getProperty("test.classes", "."); + var jdkDir = System.getProperty("test.jdk"); + OutputAnalyzer output = ProcessTools.executeProcess( + "expect", + "-n", + testSrc + "/restoreEcho.exp", + initialEcho, + jdkDir + "/bin/java", + "-Djdk.console=java.base", + "-classpath", testClasses, + "RestoreEchoTest"); + output.reportDiagnosticSummary(); + assertEquals(0, output.getExitValue()); + } + + public static void main(String... args) throws Throwable { + if (!"java.base".equals(System.getProperty("jdk.console"))) { + throw new RuntimeException("Test failed. jdk.console is not java.base"); + } + + Console con = System.console(); + if (con == null) { + throw new RuntimeException("Test failed. System.console() returned null"); + } + + // testing readLine() + String input = con.readLine("prompt: "); + con.printf("input is %s%n", input); + + // testing readPassword() + input = String.valueOf(con.readPassword("password prompt: ")); + con.printf("password is %s%n", input); + } +} diff --git a/test/jdk/java/io/Console/restoreEcho.exp b/test/jdk/java/io/Console/restoreEcho.exp new file mode 100644 index 00000000000..5a194b07a7d --- /dev/null +++ b/test/jdk/java/io/Console/restoreEcho.exp @@ -0,0 +1,58 @@ +# +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +set initialEcho [lindex $argv 0] +set java [lrange $argv 1 end] +set rlprompt "prompt: " +set rpprompt "password prompt: " +set rlinput "InPuT" +set rpinput "PaSsWoRd" +set rlexpected "input is $rlinput" +set rpexpected "password is $rpinput" +set stty_init $initialEcho +set timeout 10 + +proc test {prompt input echoStat expected} { + expect "$prompt" + send -- "$input\n" + if {$echoStat == "echo"} { + expect "$input" + } + expect "$expected" + + if {$expect_out(0,string) != $expected} { + send_error "Expected: $expected\n" + send_error "Received: $expect_out(0,string)" + exit 1 + } +} + +spawn sh -c "[list {*}$java] && stty -a" + +# readLine() - input is displayed depending on initialEcho value +test "$rlprompt" "$rlinput" "$initialEcho" "$rlexpected" +# readPassword() - input is not displayed +test "$rpprompt" "$rpinput" "-echo" "$rpexpected" +# See if the initialEcho is restored with `stty -a` +expect -- " $initialEcho " +expect eof diff --git a/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java b/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java index 48cbd1b0ffe..196a27b52ba 100644 --- a/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java +++ b/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ */ import java.io.*; +import java.util.concurrent.CountDownLatch; class Good implements Serializable { private static final long serialVersionUID = 6319710844400051132L; @@ -51,19 +52,20 @@ class Bad implements Serializable { class SuccessfulLookup extends Thread { Class<?> cl; long suid; - Object barrier; + final CountDownLatch lookupLatch; boolean ok; - SuccessfulLookup(Class<?> cl, long suid, Object barrier) { + SuccessfulLookup(Class<?> cl, long suid, CountDownLatch lookupLatch) { this.cl = cl; this.suid = suid; - this.barrier = barrier; + this.lookupLatch = lookupLatch; } public void run() { - synchronized (barrier) { - try { barrier.wait(); } catch (InterruptedException ex) {} - } + lookupLatch.countDown(); // let others know we are ready + try { + lookupLatch.await(); // await for others + } catch (InterruptedException ex) {} for (int i = 0; i < 100; i++) { if (ObjectStreamClass.lookup(cl).getSerialVersionUID() != suid) { return; @@ -75,18 +77,19 @@ public void run() { class FailingLookup extends Thread { Class<?> cl; - final Object barrier; + final CountDownLatch lookupLatch; boolean ok; - FailingLookup(Class<?> cl, Object barrier) { + FailingLookup(Class<?> cl, CountDownLatch lookupLatch) { this.cl = cl; - this.barrier = barrier; + this.lookupLatch = lookupLatch; } public void run() { - synchronized (barrier) { - try { barrier.wait(); } catch (InterruptedException ex) {} - } + lookupLatch.countDown(); // let others know we are ready + try { + lookupLatch.await(); // await for others + } catch (InterruptedException ex) {} for (int i = 0; i < 100; i++) { try { ObjectStreamClass.lookup(cl); @@ -102,39 +105,36 @@ public class ConcurrentClassDescLookup { public static void main(String[] args) throws Exception { ClassLoader loader = ConcurrentClassDescLookup.class.getClassLoader(); Class<?> cl = Class.forName("Good", false, loader); - Object barrier = new Object(); - SuccessfulLookup[] slookups = new SuccessfulLookup[50]; + int numSuccessfulLookups = 50; + CountDownLatch sLookupLatch = new CountDownLatch(numSuccessfulLookups); + SuccessfulLookup[] slookups = new SuccessfulLookup[numSuccessfulLookups]; for (int i = 0; i < slookups.length; i++) { - slookups[i] = - new SuccessfulLookup(cl, 6319710844400051132L, barrier); + slookups[i] = new SuccessfulLookup(cl, 6319710844400051132L, sLookupLatch); slookups[i].start(); } - Thread.sleep(1000); - synchronized (barrier) { - barrier.notifyAll(); - } + System.out.println("awaiting completion of " + slookups.length + " SuccessfulLookup"); for (int i = 0; i < slookups.length; i++) { slookups[i].join(); if (!slookups[i].ok) { throw new Error(); } } - + System.out.println("all " + slookups.length + " SuccessfulLookup completed"); cl = Class.forName("Bad", false, loader); - FailingLookup[] flookups = new FailingLookup[50]; + int numFailingLookups = 50; + CountDownLatch fLookupLatch = new CountDownLatch(numFailingLookups); + FailingLookup[] flookups = new FailingLookup[numFailingLookups]; for (int i = 0; i < flookups.length; i++) { - flookups[i] = new FailingLookup(cl, barrier); + flookups[i] = new FailingLookup(cl, fLookupLatch); flookups[i].start(); } - Thread.sleep(1000); - synchronized (barrier) { - barrier.notifyAll(); - } - for (int i = 0; i < slookups.length; i++) { + System.out.println("awaiting completion of " + flookups.length + " FailingLookup"); + for (int i = 0; i < flookups.length; i++) { flookups[i].join(); if (!flookups[i].ok) { throw new Error(); } } + System.out.println("all " + flookups.length + " FailingLookup completed"); } } diff --git a/test/jdk/java/lang/ProcessHandle/OnExitTest.java b/test/jdk/java/lang/ProcessHandle/OnExitTest.java index b75775b51a2..79c696efdfc 100644 --- a/test/jdk/java/lang/ProcessHandle/OnExitTest.java +++ b/test/jdk/java/lang/ProcessHandle/OnExitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import jdk.test.lib.Platform; import jdk.test.lib.Utils; import org.testng.annotations.Test; @@ -40,6 +41,7 @@ /* * @test + * @bug 8333742 * @requires vm.flagless * @library /test/lib * @modules jdk.management @@ -65,8 +67,10 @@ public static void main(String[] args) { @Test public static void test1() { try { - int[] exitValues = {0, 1, 10}; + int[] exitValues = {0, 1, 10, 259}; for (int value : exitValues) { + // Linux & Mac don't support exit codes longer than 8 bits, skip + if (value == 259 && !Platform.isWindows()) continue; Process p = JavaChild.spawn("exit", Integer.toString(value)); CompletableFuture<Process> future = p.onExit(); future.thenAccept( (ph) -> { @@ -81,7 +85,9 @@ public static void test1() { Assert.assertEquals(h, p); Assert.assertEquals(p.exitValue(), value); Assert.assertFalse(p.isAlive(), "Process should not be alive"); - p.waitFor(); + Assert.assertEquals(p.waitFor(), value); + Assert.assertTrue(p.waitFor(1, TimeUnit.MILLISECONDS), + "waitFor should return true"); } } catch (IOException | InterruptedException | ExecutionException ex) { Assert.fail(ex.getMessage(), ex); diff --git a/test/jdk/java/lang/String/IndexOf.java b/test/jdk/java/lang/String/IndexOf.java new file mode 100644 index 00000000000..baab83e19c4 --- /dev/null +++ b/test/jdk/java/lang/String/IndexOf.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2024, Intel Corporation. All rights reserved. + * 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 8320448 + * @summary test String indexOf() intrinsic + * @run driver IndexOf + */ + +/* + * @test + * @bug 8320448 + * @summary test String indexOf() intrinsic + * @requires vm.cpu.features ~= ".*avx2.*" + * @requires vm.compiler2.enabled + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts IndexOf + */ + + public class IndexOf { + final int scope = 32*2+16+8; + final char a, aa, b, c, d; + enum Encoding {LL, UU, UL; } + final Encoding ae; + int failures; + + IndexOf(Encoding _ae) { + failures = 0; + ae = _ae; + switch (ae) { + case LL: + a = 'a'; + aa = a; + b = 'b'; + c = 'c'; + d = 'd'; + break; + case UU: + a = '\u0061'; + aa = a; + b = '\u0062'; + c = '\u1063'; + d = '\u0064'; + break; + default: //case UL: + a = 'a'; + aa = '\u1061'; + b = 'b'; + c = 'c'; + d = 'd'; + break; + } + } + + // needle =~ /ab*d/ + // badNeedle =~ /ab*db*d/ + interface Append {void append(int pos, char cc);} + String newNeedle(int size, int badPosition) { + if (size<2) {throw new RuntimeException("Fix testcase "+size);} + + StringBuilder needle = new StringBuilder(size); + Append n = (int pos, char cc) -> { + if (pos == badPosition) + needle.append(c); + else + needle.append(cc); + }; + + n.append(0, a); + for (int i=1; i<size-1; i++) { + n.append(i, b); + } + n.append(size-1, d); + + return needle.toString(); + } + + // haystack =~ /a*{needle}d*/ + String newHaystack(int size, String needle, int nPosition) { + if (nPosition+needle.length()>size) {throw new RuntimeException("Fix testcase "+nPosition+" "+needle.length()+" "+size);} + StringBuilder haystack = new StringBuilder(size); + int i = 0; + for (; i<nPosition; i++) { + haystack.append(aa); + } + haystack.append(needle); + i += needle.length(); + for (; i<size; i++) { + haystack.append(d); + } + return haystack.toString(); + } + + // haystack =~ /a*{needle}+b*/ + String newHaystackRepeat(int size, String needle, int nPosition) { + if (nPosition+needle.length()>size) {throw new RuntimeException("Fix testcase "+nPosition+" "+needle.length()+" "+size);} + StringBuilder haystack = new StringBuilder(size); + int i = 0; + for (; i<nPosition; i++) { + haystack.append(aa); + } + for (; i< nPosition+needle.length(); i += needle.length()) { + haystack.append(needle); + } + for (; i<size; i++) { + haystack.append(d); + } + return haystack.toString(); + } + + public static void main(String[] args) { + int failures = 0; + for (Encoding ae : Encoding.values()) { + failures += (new IndexOf(ae)) + .test0() + .test1() + .test2() + .test3() + .test4() + .failures; + } + if (failures != 0) { + throw new RuntimeException("IndexOf test failed."); + } + } + + // Need to disable checks in String.java if intrinsic is to be tested + IndexOf test0() { // Test 'trivial cases' + // if (0==needle_len) return haystack_off; + if (3 != "Hello".indexOf("", 3)) { + System.out.println("FAILED: if (0==needle_len) return haystack_off"); + failures++; + } + //if (0==haystack_len) return -1; + if (-1 != "".indexOf("Hello", 3)) { + System.out.println("FAILED: if (0==haystack_len) return -1"); + failures++; + } + //if (needle_len>haystack_len) return -1; + if (-1 != "Hello".indexOf("HelloWorld", 3)) { + System.out.println("FAILED: if (needle_len>haystack_len) return -1"); + failures++; + } + return this; + } + + IndexOf test1() { // Test expected to find one needle + for (int nSize = 2; nSize<scope; nSize++) { + String needle = newNeedle(nSize, -1); + for (int hSize = nSize; hSize<scope; hSize++) { + for (int i = 0; i<hSize-nSize; i++) { + String haystack = newHaystack(hSize, needle, i); + for (int j = 0; j<=i; j++) { + int found = haystack.indexOf(needle, j); + if (i != found) { + System.out.println("("+ae.name()+")(T1) Trying needle["+nSize+"] in haystack["+hSize+"] at offset["+i+"]"); + System.out.println(" FAILED: Found " + needle + "@" + found + " in " + haystack + " from ["+j+"]"); + failures++; + } + } + } + } + } + return this; + } + + IndexOf test2() { // Test needle with one mismatched character + for (int nSize = 2; nSize<scope; nSize++) { + for (int hSize = nSize; hSize<scope; hSize++) { + String needle = newNeedle(nSize, -1); + for (int badPosition = 0; badPosition < nSize; badPosition+=1) { + String badNeedle = newNeedle(nSize, badPosition); + for (int i = 0; i<hSize-nSize; i++) { + String haystack = newHaystack(hSize, needle, i); + int found = haystack.indexOf(badNeedle, 1); + if (-1 != found) { + System.out.println("("+ae.name()+")(T2) Trying bad needle["+nSize+"]["+badPosition+"] in haystack["+hSize+"] at offset["+i+"]"); + System.out.println(" FAILED: False " + found + " " + haystack + "["+needle+"]["+badNeedle+"]"); + failures++; + } + } + } + } + } + return this; + } + + IndexOf test3() { // Test expected to find first of the repeated needles + for (int nSize = 2; nSize<scope; nSize++) { + String needle = newNeedle(nSize, -1); + for (int hSize = nSize; hSize<scope; hSize++) { + for (int i = 0; i<hSize-nSize; i++) { + String haystack = newHaystackRepeat(hSize, needle, i); + for (int j = 0; j<=i; j++) { + int found = haystack.indexOf(needle, j); + if (i != found) { + System.out.println("("+ae.name()+")(T3) Trying repeaded needle["+nSize+"] in haystack["+hSize+"] at offset["+i+"]"); + System.out.println(" FAILED: " + found + " " + haystack + "["+needle+"]"); + failures++; + } + } + } + } + } + return this; + } + + IndexOf test4() { // Test needle at unreachable offset + for (int nSize = 2; nSize<scope; nSize++) { + String needle = newNeedle(nSize, -1); + for (int hSize = nSize; hSize<scope; hSize++) { + for (int i = 0; i<hSize-nSize; i++) { + String haystack = newHaystack(hSize, needle, i); + // prefix lookup + for (int j = nSize-1; j<i+nSize; j++) { + int found = haystack.indexOf(needle, 0, j); + if (-1 != found) { + System.out.println("("+ae.name()+")(T4) Trying needle["+nSize+"] at offset ["+i+"] in haystack["+hSize+"] upto ["+j+"]"); + System.out.println(" FAILED: False " + found + " " + haystack + "["+needle+"]"); + failures++; + } + } + + // sufix lookup + for (int j = i+1; j<hSize; j++) { + int found = haystack.indexOf(needle, j); + if (-1 != found) { + System.out.println("("+ae.name()+")(T4) Trying needle["+nSize+"] at offset ["+i+"] in haystack["+hSize+"] from ["+j+"]"); + System.out.println(" FAILED: False " + found + " " + haystack + "["+needle+"]"); + failures++; + } + } + } + } + } + return this; + } +} \ No newline at end of file diff --git a/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java b/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java new file mode 100644 index 00000000000..ccaee0f77ea --- /dev/null +++ b/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java @@ -0,0 +1,1381 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * 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 8320448 + * @summary Test indexOf and lastIndexOf + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileCommand=dontinline,ECoreIndexOf.indexOfKernel ECoreIndexOf + * @run main/othervm -Xbatch -XX:CompileCommand=dontinline,ECoreIndexOf.indexOfKernel ECoreIndexOf + * @key randomness + */ + +/* @test + * @bug 8320448 + * @summary Test indexOf and lastIndexOf + * @requires vm.cpu.features ~= ".*avx2.*" + * @requires vm.compiler2.enabled + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts -XX:UseAVX=2 -Xbatch -XX:-TieredCompilation -XX:CompileCommand=dontinline,ECoreIndexOf.indexOfKernel ECoreIndexOf + * @key randomness + */ + +import java.nio.charset.StandardCharsets; +import java.util.Random; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.nio.charset.Charset; +import java.lang.Math; + +// @ECoreIndexOf(singleThreaded=true) +public class ECoreIndexOf { + + static Random generator; + private static boolean failure = false; + static char[] haystack = new char[128]; + static char[] haystack_16 = new char[128]; + + static boolean verbose = false; + static boolean success = true; + + static Map<Charset, String> titles = new HashMap<Charset, String>(); + static Random rng = new Random(1999); + + public static void main(String[] args) throws Exception { + int foo = 0; + String testName = "ECoreIndexOf"; + + generator = new Random(); + long seed = generator.nextLong(); + generator.setSeed(seed); + System.out.println("Seed set to "+ seed); + + /////////////////////////// WARM-UP ////////////////////////// + + for (int i = 0; i < 20000; i++) { + char c = 65; + char c16 = 0x1ed; + StringBuffer sb = new StringBuffer("a"); + StringBuffer sb16 = new StringBuffer("\u01fe"); + + foo += indexOfKernel("\u01fe", "a"); + foo += indexOfKernel("\u01fe", "a", 0); + foo += indexOfKernel("\u01fe", "\u01ff"); + foo += indexOfKernel("\u01fe", "\u01ff", 0); + foo += indexOfKernel("a", "a"); + foo += indexOfKernel("a", "a", 0); + foo += indexOfKernel("a", "\u01ff"); + foo += indexOfKernel("a", "\u01ff", 0); + + foo += indexOfKernel("\u01fe", c); + foo += indexOfKernel("\u01fe", c, 0); + foo += indexOfKernel("\u01fe", c16); + foo += indexOfKernel("\u01fe", c16, 0); + foo += indexOfKernel("a", c); + foo += indexOfKernel("a", c, 0); + foo += indexOfKernel("a", c16); + foo += indexOfKernel("a", c16, 0); + + foo += indexOfKernel(sb16, c); + foo += indexOfKernel(sb16, c, 0); + foo += indexOfKernel(sb16, c16); + foo += indexOfKernel(sb16, c16, 0); + foo += indexOfKernel(sb, c); + foo += indexOfKernel(sb, c, 0); + foo += indexOfKernel(sb, c16); + foo += indexOfKernel(sb, c16, 0); + } + + /////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////// + + String[] decorators = {"", " (same char)"}; + Charset[] charSets = {StandardCharsets.ISO_8859_1, StandardCharsets.UTF_16}; + boolean[] truefalse = {true, false}; + + titles.put(StandardCharsets.ISO_8859_1, "L"); + titles.put(StandardCharsets.UTF_16, "U"); + + for (int xxy = 0; xxy < 2; xxy++) { // Run at least twice to ensure stub called + + for (int i = 0; i < 128; i++) { + haystack[i] = (char) i; + } + + haystack_16[0] = '\u0000'; // (char) (23 + 256); + for (int i = 1; i < 128; i++) { + haystack_16[i] = (char) (i); + } + + simpleTest(); + compareIndexOfLastIndexOf(); + compareStringStringBuffer(); + StringIndexof(); + StringIndexofChar(); + StringIndexofHuge(); + + for (String decorator : decorators) { + for (Charset csHaystack : charSets) { + for (Charset csNeedle : charSets) { + System.out.println("Testing " + titles.get(csHaystack) + titles.get(csNeedle) + decorator); + for (boolean useOffset : truefalse) { + for (boolean useBuffer : truefalse) { + exhaustive(useOffset, useBuffer, csHaystack, csNeedle); + } + } + } + } + + for (int i = 0; i < 128; i++) { + haystack[i] = (char) 'a'; + } + + for (int i = 0; i < 128; i++) { + haystack_16[i] = (char) ('a' + 256); + } + } + } + + System.out.println(testName + " complete."); + + if (failure) + throw new RuntimeException("One or more failures."); + } + + private static void report(String testName, int failCount) { + System.err.println(testName + ": " + + (failCount == 0 ? "Passed" : "Failed(" + failCount + ")")); + if (failCount > 0) + failure = true; + } + + private static String generateTestString(int min, int max) { + StringBuffer aNewString = new StringBuffer(120); + int aNewLength = getRandomIndex(min, max); + for (int y = 0; y < aNewLength; y++) { + int achar = generator.nextInt(30) + 30; + char test = (char) (achar); + aNewString.append(test); + } + return aNewString.toString(); + } + + private static String makeRndString(boolean isUtf16, int length) { + StringBuilder sb = new StringBuilder(length); + if (length > 0) { + sb.append(isUtf16 ? '\u2026' : 'b'); // ... + + for (int i = 1; i < length - 1; i++) { + sb.append((char) ('b' + rng.nextInt(26))); + } + + sb.append(rng.nextInt(3) >= 1 ? 'a' : 'b');// 66.6% of time 'a' is in string + } + return sb.toString(); + } + + private static int indexOfKernel(String haystack, String needle) { + return haystack.indexOf(needle); + } + + private static int indexOfKernel(String haystack, String needle, int offset) { + return haystack.indexOf(needle, offset); + } + + private static int indexOfKernel(StringBuffer haystack, String needle) { + return haystack.indexOf(needle); + } + + private static int indexOfKernel(StringBuffer haystack, char cneedle) { + String needle = String.valueOf(cneedle); + return haystack.indexOf(needle); + } + + private static int indexOfKernel(StringBuffer haystack, String needle, int offset) { + return haystack.indexOf(needle, offset); + } + + private static int indexOfKernel(StringBuffer haystack, char cneedle, int offset) { + String needle = String.valueOf(cneedle); + return haystack.indexOf(needle, offset); + } + + private static int indexOfKernel(String haystack, char needle) { + return haystack.indexOf(needle); + } + + private static int indexOfKernel(String haystack, char needle, int offset) { + return haystack.indexOf(needle, offset); + } + + private static void printStringBytes(byte[] bytes) { + System.err.println(" bytes.len=" + bytes.length); + for (byte b : bytes) { + System.err.print(String.format("0x%02x ", b)); + } + System.err.println(""); + } + + private static int getRandomIndex(int constraint1, int constraint2) { + int range = constraint2 - constraint1; + int x = generator.nextInt(range); + return constraint1 + x; + } + + private static int naiveFind(String haystack, String needle) { + return naiveFind(haystack, needle, 0); + } + + private static int naiveFind(String haystack, char needle) { + return naiveFind(haystack, needle, 0); + } + + private static int naiveFind(String haystack, String needle, int offset) { + int x = offset; + int len = haystack.length() - offset; + if (needle.length() == 0) + return offset; + if (needle.length() > len) + return -1; + int hsndx = 0; + int nndx = 0; + for (int xx = 0; xx < offset; xx++) { + hsndx += Character.charCount(haystack.codePointAt(hsndx)); + } + + for (x = offset; x < haystack.length() - needle.length() + 1; x++) { + if (haystack.codePointAt(hsndx) == needle.codePointAt(0)) { + nndx = Character.charCount(needle.codePointAt(0)); + int hsndx_tmp = hsndx + Character.charCount(haystack.codePointAt(hsndx)); + + while (nndx < needle.length()) { + if (haystack.codePointAt(hsndx_tmp) != needle.codePointAt(nndx)) { + break; + } + hsndx_tmp += Character.charCount(haystack.codePointAt(hsndx_tmp)); + nndx += Character.charCount(needle.codePointAt(nndx)); + } + if (nndx == needle.length()) { + return x; + } + } + hsndx += Character.charCount(haystack.codePointAt(hsndx)); + } + return -1; + } + + private static int naiveFind(String haystack, char cneedle, int offset) { + int x = offset; + int len = haystack.length() - offset; + String needle = String.valueOf(cneedle); + if (len == 0) + return -1; + int hsndx = 0; + for (int xx = 0; xx < offset; xx++) { + hsndx += Character.charCount(haystack.codePointAt(hsndx)); + } + + for (x = offset; x < haystack.length(); x++) { + if (haystack.codePointAt(hsndx) == needle.codePointAt(0)) { + return x; + } + hsndx += Character.charCount(haystack.codePointAt(hsndx)); + } + + return -1; + } + + private static void exhaustive(boolean useOffset, boolean useStringBuffer, Charset hs_charset, + Charset needleCharset) { + int result = 0; + int midresult = 0; + int endresult = 0; + int l_offset = 0; + int failCount = 0; + + String thisTest = titles.get(hs_charset) + titles.get(needleCharset) + (useOffset ? " w/offset" : "") + (useStringBuffer ? " StringBuffer" : ""); + + for (int needleSize = 0; needleSize < 128; needleSize++) { + for (int haystackSize = 0; haystackSize < 128; haystackSize++) { + for (l_offset = 0; l_offset <= haystackSize; l_offset++) { + String needle = new String(Arrays.copyOfRange( + (needleCharset == StandardCharsets.UTF_16) ? haystack_16 : haystack, l_offset, l_offset + needleSize)); + int hsSize = (haystackSize - l_offset) >= 0 ? haystackSize - l_offset : 0; + int midStart = Math.max((hsSize / 2) - (needleSize / 2), 0); + int endStart = (hsSize > needleSize) ? hsSize - needleSize : 0; + String midNeedle = new String( + Arrays.copyOfRange((needleCharset == StandardCharsets.UTF_16) ? haystack_16 : haystack, + midStart + l_offset, midStart + needleSize + l_offset)); + String endNeedle = new String( + Arrays.copyOfRange((needleCharset == StandardCharsets.UTF_16) ? haystack_16 : haystack, + endStart + l_offset, endStart + needleSize + l_offset)); + String shs = new String( + Arrays.copyOfRange((hs_charset == StandardCharsets.UTF_16) ? haystack_16 : haystack, 0, haystackSize)); + + // Truncate needles to correct lengths + + if (l_offset + needleSize > haystack.length + 1) { + needle = needle.substring(0, needleSize); + midNeedle = midNeedle.substring(0, needleSize); + endNeedle = endNeedle.substring(0, needleSize); + } + + if (!success && needleSize > 1) { + needle = needle.substring(0, needle.length() - 1) + (char) ((int) (needle.charAt(needle.length() - 2) + 1)); + midNeedle = midNeedle.substring(0, midNeedle.length() - 1) + + (char) ((int) (midNeedle.charAt(midNeedle.length() - 2) + 1)); + endNeedle = endNeedle.substring(0, endNeedle.length() - 1) + + (char) ((int) (endNeedle.charAt(endNeedle.length() - 2) + 1)); + } + + StringBuffer hs = new StringBuffer(shs.length()); + hs.append(shs); + if (!shs.equals(hs.toString())) + throw new RuntimeException("Initial equality failure"); + + if (useStringBuffer) { + result = indexOfKernel(hs, needle, l_offset); + midresult = indexOfKernel(hs, midNeedle, l_offset); + endresult = indexOfKernel(hs, endNeedle, l_offset); + } else { + result = indexOfKernel(shs, needle, l_offset); + midresult = indexOfKernel(shs, midNeedle, l_offset); + endresult = indexOfKernel(shs, endNeedle, l_offset); + } + int nResult = naiveFind(hs.toString(), needle, l_offset); + int midnResult = naiveFind(hs.toString(), midNeedle, l_offset); + int endnResult = naiveFind(hs.toString(), endNeedle, l_offset); + if (result != nResult) { + failCount++; + System.err.println("useOffset=" + useOffset + ", useStringBuffer=" + useStringBuffer); + System.err.print("Haystack="); + printStringBytes(shs.getBytes(hs_charset)); + System.err.print("Needle="); + printStringBytes(needle.getBytes(needleCharset)); + System.err.println("l_offset=" + l_offset); + System.err.println("haystackLen=" + haystackSize + " needleLen=" + needleSize + + " result=" + result + " nResult=" + nResult); + System.err.println(""); + } + // badResults = success ? ((midnResult == -1) || (midresult == -1)) : + // ((midnResult != -1) || (midresult != -1)); + if ((midresult != midnResult)) { + failCount++; + System.err.println("useOffset=" + useOffset + ", useStringBuffer=" + useStringBuffer); + System.err.print("Haystack="); + printStringBytes(shs.getBytes(hs_charset)); + System.err.print("Needle="); + printStringBytes(midNeedle.getBytes(needleCharset)); + System.err.println("l_offset=" + l_offset); + System.err.println("haystackLen=" + haystackSize + " needleLen=" + needleSize + + " midresult=" + midresult + " midnResult=" + midnResult); + System.err.println(""); + } + // badResults = success ? ((endnResult == -1) || (endresult == -1)) : + // ((endnResult != -1) || (endresult != -1)); + if ((endresult != endnResult)) { + failCount++; + System.err.println("useOffset=" + useOffset + ", useStringBuffer=" + useStringBuffer); + System.err.print("Haystack="); + printStringBytes(shs.getBytes(hs_charset)); + System.err.print("Needle="); + printStringBytes(endNeedle.getBytes(needleCharset)); + System.err.println("l_offset=" + l_offset); + System.err.println("haystackLen=" + haystackSize + " needleLen=" + needleSize + + " endresult=" + endresult + " endnResult=" + endnResult); + System.err.println(""); + } + + if (!useOffset) + l_offset = haystackSize + 100; + } + } + } + + report("Exhaustive " + thisTest, failCount); + } + + private static void PrintError(int kernel, int naive, int num, String prefix, String hs, char needle) { + PrintError(kernel, naive, num, prefix, hs, String.valueOf(needle)); + } + + private static void PrintError(int kernel, int naive, int num, String prefix, String hs, String needle) { + if (!verbose) + return; + System.err.println(prefix + ": (" + num + "): kernel=" + kernel + ", naive=" + naive); + System.err.print("Haystack="); + printStringBytes(hs.getBytes()); + System.err.print("Needle="); + printStringBytes(needle.getBytes()); + System.err.println(""); + } + + private static void simpleTest() { + int failCount = 0; + String sourceString; + StringBuffer sourceBuffer; + String targetString; + String emptyString = ""; + String allAs = new String("aaaaaaaaaaaaaaaaaaaaaaaaa"); + StringBuffer allAsBuffer = new StringBuffer(allAs); + + for (int i = 0; i < 10000; i++) { + do { + sourceString = generateTestString(99, 100); + sourceBuffer = new StringBuffer(sourceString); + targetString = generateTestString(10, 11); + } while (indexOfKernel(sourceString, targetString) != -1); + + int index1 = generator.nextInt(90) + 5; + sourceBuffer = sourceBuffer.replace(index1, index1, targetString); + + if ((indexOfKernel(sourceBuffer, targetString) != index1) || + (index1 != naiveFind(sourceBuffer.toString(), targetString, 0))) { + System.err.println("sourceBuffer.indexOf(targetString) fragment '" + targetString + "' (" + + targetString.length() + ") String = " + + sourceBuffer.toString() + " len Buffer = " + sourceBuffer.toString().length()); + System.err.println(" naive = " + naiveFind(sourceBuffer.toString(), targetString, 0) + ", IndexOf = " + + indexOfKernel(sourceBuffer, targetString)); + failCount++; + } + if ((indexOfKernel(sourceBuffer, targetString, 5) != index1) || + (index1 != naiveFind(sourceBuffer.toString(), targetString, 0))) { + System.err.println("sourceBuffer.indexOf(targetString, 5) fragment '" + targetString + "' (" + + targetString.length() + ") String = " + + sourceBuffer.toString() + " len Buffer = " + sourceBuffer.toString().length()); + System.err.println(" naive = " + naiveFind(sourceBuffer.toString(), targetString, 0) + ", IndexOf = " + + indexOfKernel(sourceBuffer, targetString, 5)); + failCount++; + } + if ((indexOfKernel(sourceBuffer, targetString, 99) == index1) || + (index1 != naiveFind(sourceBuffer.toString(), targetString, 0))) { + System.err.println("sourceBuffer.indexOf(targetString, 99) fragment '" + targetString + "' (" + + targetString.length() + ") String = " + + sourceBuffer.toString() + " len Buffer = " + sourceBuffer.toString().length()); + System.err.println(" naive = " + naiveFind(sourceBuffer.toString(), targetString, 0) + ", IndexOf = " + + indexOfKernel(sourceBuffer, targetString, 99)); + failCount++; + } + if ((indexOfKernel(sourceBuffer, emptyString, 99) != 99) || + (99 != naiveFind(sourceBuffer.toString(), emptyString, 99))) { + System.err.println("sourceBuffer.indexOf(emptyString, 99) fragment '" + emptyString + "' (" + + emptyString.length() + ") String = " + + sourceBuffer.toString() + " len Buffer = " + sourceBuffer.toString().length()); + System.err.println(" naive = " + naiveFind(sourceBuffer.toString(), emptyString, 99) + ", IndexOf = " + + indexOfKernel(sourceBuffer, emptyString, 99)); + failCount++; + } + if ((indexOfKernel(allAsBuffer.substring(1, 3), allAsBuffer.substring(5, 12)) != -1) || + (-1 != naiveFind(allAsBuffer.substring(1, 3).toString(), allAsBuffer.substring(5, 12), 0))) { + System.err.println("allAsBuffer.substring(1, 3).indexOf(allAsBuffer.substring(5, 12)) fragment '" + + allAsBuffer.substring(5, 12) + "' (" + + allAsBuffer.substring(5, 12).length() + ") String = " + + allAsBuffer.substring(1, 3) + " len Buffer = " + allAsBuffer.substring(1, 3).length()); + System.err.println( + " naive = " + naiveFind(allAsBuffer.substring(1, 3).toString(), allAsBuffer.substring(5, 12), 0) + + ", IndexOf = " + indexOfKernel(allAsBuffer.substring(1, 3), allAsBuffer.substring(5, 12))); + failCount++; + } + } + + report("Basic Test ", failCount); + } + + // Note: it is possible although highly improbable that failCount will + // be > 0 even if everthing is working ok + private static void compareIndexOfLastIndexOf() { + int failCount = 0; + String sourceString; + StringBuffer sourceBuffer; + String targetString; + + for (int i = 0; i < 10000; i++) { + do { + sourceString = generateTestString(99, 100); + sourceBuffer = new StringBuffer(sourceString); + targetString = generateTestString(10, 11); + } while (indexOfKernel(sourceString, targetString) != -1); + + int index1 = generator.nextInt(100); + sourceBuffer = sourceBuffer.replace(index1, index1, targetString); + + // extremely remote possibility of > 1 match + int matches = 0; + int index2 = -1; + while ((index2 = indexOfKernel(sourceBuffer, targetString, index2 + 1)) != -1) + matches++; + if (matches > 1) + continue; + + if (indexOfKernel(sourceBuffer, targetString) != sourceBuffer.lastIndexOf(targetString)) + failCount++; + sourceString = sourceBuffer.toString(); + if (indexOfKernel(sourceString, targetString) != sourceString.lastIndexOf(targetString)) + failCount++; + } + + report("IndexOf vs LastIndexOf ", failCount); + } + + private static void compareStringStringBuffer() { + int failCount = 0; + boolean make_new = true; + + String fragment = null; + StringBuffer testBuffer = null; + String testString = null; + int testIndex = 0; + + failCount = indexOfKernel("", ""); + + for (int x = 0; x < 1000000; x++) { + if (make_new) { + testString = generateTestString(1, 100); + int len = testString.length(); + + testBuffer = new StringBuffer(len); + testBuffer.append(testString); + if (!testString.equals(testBuffer.toString())) + throw new RuntimeException("Initial equality failure"); + + int x1 = 0; + int x2 = 1000; + while (x2 > testString.length()) { + x1 = generator.nextInt(len); + x2 = generator.nextInt(100); + x2 = x1 + x2; + } + fragment = testString.substring(x1, x2); + } + + int sAnswer = indexOfKernel(testString, fragment); + int sbAnswer = indexOfKernel(testBuffer, fragment); + + if (sAnswer != sbAnswer) { + System.err.println("(1) IndexOf fragment '" + fragment + "' (" + fragment.length() + ") len String = " + + testString.length() + " len Buffer = " + testBuffer.length()); + System.err.println(" sAnswer = " + sAnswer + ", sbAnswer = " + sbAnswer); + System.err.println(" testString = '" + testString + "'"); + System.err.println(" testBuffer = '" + testBuffer + "'"); + failCount++; + + sAnswer = indexOfKernel(testString, fragment); + sbAnswer = indexOfKernel(testBuffer, fragment); + } else { + if (sAnswer > testString.length()) { + System.err.println( + "IndexOf returned value out of range; return: " + sAnswer + " length max: " + testBuffer.length()); + } + } + + if ((fragment == "0#:02/62;+-\"\"0$25-5$#)1263") && (testBuffer.length() == 94)) { + String xx = "abc"; + String yy = "abcdefg"; + int sA = indexOfKernel(xx, yy); + } + + if (make_new) + testIndex = getRandomIndex(-100, 100); + + sAnswer = indexOfKernel(testString, fragment, testIndex); + sbAnswer = indexOfKernel(testBuffer, fragment, testIndex); + + if (sAnswer != sbAnswer) { + System.err.println("(2) IndexOf fragment '" + fragment + "' (" + fragment.length() + ") index = " + testIndex + + " len String = " + testString.length() + " len Buffer = " + testBuffer.length()); + System.err.println(" sAnswer = " + sAnswer + ", sbAnswer = " + sbAnswer); + System.err.println(" testString = '" + testString + "'"); + System.err.println(" testBuffer = '" + testBuffer + "'"); + failCount++; + make_new = true; + + sAnswer = indexOfKernel(testString, fragment, testIndex); + sbAnswer = indexOfKernel(testBuffer, fragment, testIndex); + } else { + if ((sAnswer > testString.length()) || ((sAnswer != -1) && (sAnswer < testIndex) && (fragment.length() != 0))) { + System.err.println("IndexOf returned value out of range; return: " + sAnswer + " length max: " + + testString.length() + " index: " + testIndex); + System.err.println("(3) IndexOf fragment '" + fragment + "' (" + fragment.length() + ") index = " + testIndex + + " len String = " + testString.length() + " len Buffer = " + testBuffer.length()); + } + } + + sAnswer = testString.lastIndexOf(fragment); + sbAnswer = testBuffer.lastIndexOf(fragment); + + if (sAnswer != sbAnswer) { + System.err.println("(1) lastIndexOf fragment '" + fragment + "' len String = " + testString.length() + + " len Buffer = " + testBuffer.length()); + System.err.println(" sAnswer = " + sAnswer + ", sbAnswer = " + sbAnswer); + failCount++; + + sAnswer = testString.lastIndexOf(fragment); + sbAnswer = testBuffer.lastIndexOf(fragment); + } + + if (make_new) + testIndex = getRandomIndex(-100, 100); + + sAnswer = testString.lastIndexOf(fragment, testIndex); + sbAnswer = testBuffer.lastIndexOf(fragment, testIndex); + + if (sAnswer != sbAnswer) { + System.err.println("(2) lastIndexOf fragment '" + fragment + "' index = " + testIndex + " len String = " + + testString.length() + " len Buffer = " + testBuffer.length()); + failCount++; + } + } + + report("String vs StringBuffer ", failCount); + } + + ////////////////////////////////////////////////////////////////////// + // Test routines used in benchmarks + // + // From StringIndexofHuge + private static void StringIndexofHuge() { + int stubResult = 0; + int failCount = 0; + + for (int xx = 0; xx < 2; xx++) { + int num = 1; + + String dataString = "ngdflsoscargfdgf"; + String dataString16 = "ngdfilso\u01facargfd\u01eef"; + String dataStringHuge = (("A".repeat(32) + "B".repeat(32)).repeat(16) + "X").repeat(2) + "bB"; + String dataStringHuge16 = "\u01de" + (("A".repeat(32) + "B".repeat(32)).repeat(16) + "\u01fe").repeat(2) + + "\u01eeB"; + String earlyMatchString = dataStringHuge.substring(0, 34); + String earlyMatchString16 = dataStringHuge16.substring(0, 34); + String midMatchString = dataStringHuge.substring(dataStringHuge.length() / 2 - 16, + dataStringHuge.length() / 2 + 32); + String midMatchString16 = dataStringHuge16.substring(dataStringHuge16.length() / 2 - 16, + dataStringHuge16.length() / 2 + 32); + String lateMatchString = dataStringHuge.substring(dataStringHuge.length() - 31); + String lateMatchString16 = dataStringHuge16.substring(dataStringHuge16.length() - 31); + + String searchString = "oscar"; + String searchString16 = "o\u01facar"; + String searchStringSmall = "dgf"; + String searchStringSmall16 = "d\u01eef"; + + String searchStringHuge = "capaapapapasdkajdlkajskldjaslkajdlkajskldjaslkjdlkasjdsalk"; + String searchStringHuge16 = "capaapapapasdkajdlka\u01feskldjaslkajdlkajskldjaslkjdlkasjdsalk"; + + String searchNoMatch = "XYXyxYxy".repeat(22); + String searchNoMatch16 = "\u01ab\u01ba\u01cb\u01bc\u01de\u01ed\u01fa\u01af".repeat(22); + + stubResult = indexOfKernel(dataStringHuge16, earlyMatchString); + int nResult = naiveFind(dataStringHuge16, earlyMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, earlyMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, earlyMatchString); + nResult = naiveFind(dataStringHuge, earlyMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, earlyMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, midMatchString); + nResult = naiveFind(dataStringHuge, midMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, midMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, lateMatchString); + nResult = naiveFind(dataStringHuge, lateMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, lateMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, searchNoMatch); + nResult = naiveFind(dataStringHuge, searchNoMatch); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, searchNoMatch); + failCount++; + } + num++; + stubResult = indexOfKernel(searchString, searchString); + nResult = naiveFind(searchString, searchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", searchString, searchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString, searchString); + nResult = naiveFind(dataString, searchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataString, searchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString, searchStringSmall); + nResult = naiveFind(dataString, searchStringSmall); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataString, searchStringSmall); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, "B".repeat(30) + "X" + "A".repeat(30), 74); + nResult = naiveFind(dataStringHuge, "B".repeat(30) + "X" + "A".repeat(30), 74); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, + "B".repeat(30) + "X" + "A".repeat(30)); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, "A".repeat(32) + "F" + "B".repeat(32), 64); + nResult = naiveFind(dataStringHuge, "A".repeat(32) + "F" + "B".repeat(32), 64); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, + "A".repeat(32) + "F" + "B".repeat(32)); + failCount++; + } + num++; + stubResult = indexOfKernel(midMatchString, dataStringHuge, 3); + nResult = naiveFind(midMatchString, dataStringHuge, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", midMatchString, dataStringHuge); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge, "A".repeat(32) + "B".repeat(30) + "bB"); + nResult = naiveFind(dataStringHuge, "A".repeat(32) + "B".repeat(30) + "bB"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge, + "A".repeat(32) + "B".repeat(30) + "bB"); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, earlyMatchString); + nResult = naiveFind(dataStringHuge16, earlyMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, earlyMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, midMatchString); + nResult = naiveFind(dataStringHuge16, midMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, midMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, lateMatchString); + nResult = naiveFind(dataStringHuge16, lateMatchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, lateMatchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, searchNoMatch); + nResult = naiveFind(dataStringHuge16, searchNoMatch); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, searchNoMatch); + failCount++; + } + num++; + stubResult = indexOfKernel(searchString16, searchString); + nResult = naiveFind(searchString16, searchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", searchString16, searchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString16, searchString); + nResult = naiveFind(dataString16, searchString); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataString16, searchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString16, searchStringSmall); + nResult = naiveFind(dataString16, searchStringSmall); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataString16, searchStringSmall); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, "B".repeat(30) + "X" + "A".repeat(30), 74); + nResult = naiveFind(dataStringHuge16, "B".repeat(30) + "X" + "A".repeat(30), 74); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, + "B".repeat(30) + "X" + "A".repeat(30)); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, "A".repeat(32) + "F" + "B".repeat(32), 64); + nResult = naiveFind(dataStringHuge16, "A".repeat(32) + "F" + "B".repeat(32), 64); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, + "A".repeat(32) + "F" + "B".repeat(32)); + failCount++; + } + num++; + stubResult = indexOfKernel(midMatchString16, dataStringHuge, 3); + nResult = naiveFind(midMatchString16, dataStringHuge, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", midMatchString16, dataStringHuge); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, "A".repeat(32) + "B".repeat(30) + "bB"); + nResult = naiveFind(dataStringHuge16, "A".repeat(32) + "B".repeat(30) + "bB"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, + "A".repeat(32) + "B".repeat(30) + "bB"); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, earlyMatchString16); + nResult = naiveFind(dataStringHuge16, earlyMatchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, earlyMatchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, midMatchString16); + nResult = naiveFind(dataStringHuge16, midMatchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, midMatchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, lateMatchString16); + nResult = naiveFind(dataStringHuge16, lateMatchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, lateMatchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, searchNoMatch16); + nResult = naiveFind(dataStringHuge16, searchNoMatch16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, searchNoMatch16); + failCount++; + } + num++; + stubResult = indexOfKernel(searchString16, searchString16); + nResult = naiveFind(searchString16, searchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", searchString16, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString16, searchString16); + nResult = naiveFind(dataString16, searchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataString16, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString16, searchStringSmall16); + nResult = naiveFind(dataString16, searchStringSmall16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataString16, searchStringSmall16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, "B".repeat(30) + "X" + "A".repeat(30), 74); + nResult = naiveFind(dataStringHuge16, "B".repeat(30) + "X" + "A".repeat(30), 74); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, + "B".repeat(30) + "X" + "A".repeat(30)); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, "A".repeat(32) + "\u01ef" + "B".repeat(32), 64); + nResult = naiveFind(dataStringHuge16, "A".repeat(32) + "\u01ef" + "B".repeat(32), 64); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, + "A".repeat(32) + "\u01ef" + "B".repeat(32)); + failCount++; + } + num++; + stubResult = indexOfKernel(midMatchString16, dataStringHuge16, 3); + nResult = naiveFind(midMatchString16, dataStringHuge16, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", midMatchString16, dataStringHuge16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringHuge16, "A".repeat(32) + "B".repeat(30) + "\u01eeB"); + nResult = naiveFind(dataStringHuge16, "A".repeat(32) + "B".repeat(30) + "\u01eeB"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofHuge", dataStringHuge16, + "A".repeat(32) + "B".repeat(30) + "\u01eeB"); + failCount++; + } + num++; + } + + report("StringIndexofHuge ", failCount); + } + + ///////////////////////////////////////////////////////////////////// + // + // From StringIndexof + private static void StringIndexof() { + int stubResult = 0; + int failCount = 0; + + for (int xx = 0; xx < 2; xx++) { + int num = 1; + + String dataString = "ngdfilsoscargfdgf"; + String searchString = "oscar"; + String dataStringBig = "2937489745890797905764956790452976742965790437698498409583479067ngdcapaapapapasdkajdlkajskldjaslkjdlkasjdsalkjas"; + String searchStringBig = "capaapapapasdkajdlkajskldjaslkjdlkasjdsalk"; + String data = "0000100101010010110101010010101110101001110110101010010101010010000010111010101010101010100010010101110111010101101010100010010100001010111111100001010101001010100001010101001010101010111010010101010101010101010101010"; + String sub = "10101010"; + String shortSub1 = "1"; + String data2 = "00001001010100a10110101010010101110101001110110101010010101010010000010111010101010101010a100010010101110111010101101010100010010a100a0010101111111000010101010010101000010101010010101010101110a10010101010101010101010101010"; + String shortSub2 = "a"; + char searchChar = 's'; + + String string16Short = "scar\u01fe1"; + String string16Medium = "capaapapapasdkajdlkajskldjaslkjdlkasjdsalksca1r\u01fescar"; + String string16Long = "2937489745890797905764956790452976742965790437698498409583479067ngdcapaapapapasdkajdlkajskldjaslkjdlkasjdsalkja1sscar\u01fescar"; + char searchChar16 = 0x1fe; + String searchString16 = "\u01fe"; + + stubResult = indexOfKernel(dataStringBig, searchChar); + int nResult = naiveFind(dataStringBig, searchChar); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", dataStringBig, searchChar); + failCount++; + } + num++; + stubResult = indexOfKernel(searchStringBig, searchChar); + nResult = naiveFind(searchStringBig, searchChar); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", searchStringBig, searchChar); + failCount++; + } + num++; + stubResult = indexOfKernel(searchString, searchChar); + nResult = naiveFind(searchString, searchChar); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", searchString, searchChar); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, searchChar16); + nResult = naiveFind(string16Long, searchChar16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, searchChar16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Medium, searchChar16); + nResult = naiveFind(string16Medium, searchChar16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Medium, searchChar16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Short, searchChar16); + nResult = naiveFind(string16Short, searchChar16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Short, searchChar16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringBig, searchChar, 3); + nResult = naiveFind(dataStringBig, searchChar, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", dataStringBig, searchChar); + failCount++; + } + num++; + stubResult = indexOfKernel(searchStringBig, searchChar, 3); + nResult = naiveFind(searchStringBig, searchChar, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", searchStringBig, searchChar); + failCount++; + } + num++; + stubResult = indexOfKernel(searchString, searchChar, 1); + nResult = naiveFind(searchString, searchChar, 1); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", searchString, searchChar); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, searchChar16, 3); + nResult = naiveFind(string16Long, searchChar16, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, searchChar16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Medium, searchChar16, 3); + nResult = naiveFind(string16Medium, searchChar16, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Medium, searchChar16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Short, searchChar16, 2); + nResult = naiveFind(string16Short, searchChar16, 2); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Short, searchChar16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, shortSub1); + nResult = naiveFind(string16Long, shortSub1); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, shortSub1); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Medium, shortSub1); + nResult = naiveFind(string16Medium, shortSub1); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Medium, shortSub1); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, shortSub2); + nResult = naiveFind(string16Long, shortSub2); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, shortSub2); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, shortSub1, 3); + nResult = naiveFind(string16Long, shortSub1, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, shortSub1); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Medium, shortSub1, 3); + nResult = naiveFind(string16Medium, shortSub1, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Medium, shortSub1); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Short, shortSub2, 1); + nResult = naiveFind(string16Short, shortSub2, 1); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Short, shortSub2); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, searchString16, 3); + nResult = naiveFind(string16Long, searchString16, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Medium, searchString16, 3); + nResult = naiveFind(string16Medium, searchString16, 3); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Medium, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Short, searchString16, 2); + nResult = naiveFind(string16Short, searchString16, 2); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Short, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Long, searchString16); + nResult = naiveFind(string16Long, searchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Long, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Medium, searchString16); + nResult = naiveFind(string16Medium, searchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Medium, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(string16Short, searchString16); + nResult = naiveFind(string16Short, searchString16); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", string16Short, searchString16); + failCount++; + } + num++; + stubResult = indexOfKernel(dataString, searchString, 2); + nResult = naiveFind(dataString, searchString, 2); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", dataString, searchString); + failCount++; + } + num++; + stubResult = indexOfKernel(dataStringBig, searchStringBig, 2); + nResult = naiveFind(dataStringBig, searchStringBig, 2); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexof", dataStringBig, searchStringBig); + } + { + int index = 0; + int dummy = 0; + while ((index = indexOfKernel(data, sub, index)) > -1) { + nResult = naiveFind(data, sub, index); + if (index != nResult) { + PrintError(stubResult, nResult, num, "StringIndexof", data, sub); + failCount++; + } + index++; + dummy += index; + } + num++; + } + { + int dummy = 0; + int index = 0; + while ((index = indexOfKernel(data, shortSub1, index)) > -1) { + nResult = naiveFind(data, shortSub1, index); + if (index != nResult) { + PrintError(stubResult, nResult, num, "StringIndexof", data, shortSub1); + failCount++; + } + index++; + dummy += index; + } + num++; + } + { + int dummy = 0; + int index = 0; + while ((index = indexOfKernel(data2, shortSub2, index)) > -1) { + nResult = naiveFind(data2, shortSub2, index); + if (index != nResult) { + PrintError(stubResult, nResult, num, "StringIndexof", data2, shortSub2); + failCount++; + } + index++; + dummy += index; + } + num++; + } + { + String tmp = "simple-hash:SHA-1/UTF-8"; + if (!tmp.contains("SHA-1")) { + PrintError(stubResult, nResult, num, "StringIndexof", "simple-hash:SHA-1/UTF-8", "SHA-1"); + failCount++; + } + num++; + } + } + + report("StringIndexof ", failCount); + } + + ///////////////////////////////////////////////////////////////////// + // + // From StringIndexofChar + private static void StringIndexofChar() { + int stubResult = 0; + int failCount = 0; + + for (int xx = 0; xx < 2; xx++) { + stubResult = 0; + int nResult = 0; + int num = 1; + + String[] latn1_short = new String[100]; + String[] latn1_sse4 = new String[100]; + String[] latn1_avx2 = new String[100]; + String[] latn1_mixedLength = new String[100]; + String[] utf16_short = new String[100]; + String[] utf16_sse4 = new String[100]; + String[] utf16_avx2 = new String[100]; + String[] utf16_mixedLength = new String[100]; + + for (int i = 0; i < 100; i++) { + latn1_short[i] = makeRndString(false, 15); + latn1_sse4[i] = makeRndString(false, 16); + latn1_avx2[i] = makeRndString(false, 32); + utf16_short[i] = makeRndString(true, 7); + utf16_sse4[i] = makeRndString(true, 8); + utf16_avx2[i] = makeRndString(true, 16); + latn1_mixedLength[i] = makeRndString(false, rng.nextInt(65)); + utf16_mixedLength[i] = makeRndString(true, rng.nextInt(65)); + } + for (String what : latn1_mixedLength) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : utf16_mixedLength) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : latn1_mixedLength) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : utf16_mixedLength) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : latn1_short) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : latn1_sse4) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : latn1_avx2) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : utf16_short) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : utf16_sse4) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : utf16_avx2) { + stubResult = indexOfKernel(what, 'a'); + nResult = naiveFind(what, 'a'); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, 'a'); + failCount++; + } + } + num++; + for (String what : latn1_short) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : latn1_sse4) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : latn1_avx2) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : utf16_short) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : utf16_sse4) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + for (String what : utf16_avx2) { + stubResult = indexOfKernel(what, "a"); + nResult = naiveFind(what, "a"); + if (nResult != stubResult) { + PrintError(stubResult, nResult, num, "StringIndexofChar", what, "a"); + failCount++; + } + } + num++; + } + + report("StringIndexofChar ", failCount); + } + +} diff --git a/test/jdk/java/lang/instrument/NativeMethodPrefixApp.java b/test/jdk/java/lang/instrument/NativeMethodPrefixApp.java index 5060e67ca87..65cc54793cb 100644 --- a/test/jdk/java/lang/instrument/NativeMethodPrefixApp.java +++ b/test/jdk/java/lang/instrument/NativeMethodPrefixApp.java @@ -25,6 +25,7 @@ import java.io.File; import java.nio.file.Path; import java.lang.management.*; +import java.util.zip.CRC32; import bootreporter.*; import jdk.test.lib.helpers.ClassFileInstaller; @@ -96,6 +97,10 @@ private static void launchApp(final Path agentJar) throws Exception { final OutputAnalyzer oa = ProcessTools.executeTestJava( "--enable-preview", // due to usage of ClassFile API PreviewFeature in the agent "-javaagent:" + agentJar.toString(), + // We disable CheckIntrinsic because the NativeMethodPrefixAgent modifies + // the native method names, which then causes a failure in the VM check + // for the presence of an intrinsic on a @IntrinsicCandidate native method. + "-XX:+UnlockDiagnosticVMOptions", "-XX:-CheckIntrinsics", NativeMethodPrefixApp.class.getName()); oa.shouldHaveExitValue(0); // make available stdout/stderr in the logs, even in case of successful completion @@ -109,6 +114,10 @@ private void run() throws Exception { java.lang.reflect.Array.getLength(new short[5]); RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); System.err.println(mxbean.getVmVendor()); + // Simply load a class containing an @IntrinsicCandidate on a native method + // to exercise the VM code which verifies the presence of the intrinsic + // implementation for that method. + System.err.println(new CRC32()); NativeMethodPrefixAgent.checkErrors(); diff --git a/test/jdk/java/net/httpclient/BodySubscribersTest.java b/test/jdk/java/net/httpclient/BodySubscribersTest.java index 508cc95abb0..5ee7ed4ef62 100644 --- a/test/jdk/java/net/httpclient/BodySubscribersTest.java +++ b/test/jdk/java/net/httpclient/BodySubscribersTest.java @@ -24,7 +24,7 @@ /* * @test * @summary Basic test for the standard BodySubscribers default behavior - * @bug 8225583 + * @bug 8225583 8334028 * @run testng BodySubscribersTest */ diff --git a/test/jdk/java/net/httpclient/ForbiddenHeadTest.java b/test/jdk/java/net/httpclient/ForbiddenHeadTest.java index 4b651eb4813..1498aa118b3 100644 --- a/test/jdk/java/net/httpclient/ForbiddenHeadTest.java +++ b/test/jdk/java/net/httpclient/ForbiddenHeadTest.java @@ -381,7 +381,7 @@ public void setup() throws Exception { public void teardown() throws Exception { authClient = noAuthClient = null; Thread.sleep(100); - AssertionError fail = TRACKER.check(500); + AssertionError fail = TRACKER.check(1500); try { proxy.stop(); authproxy.stop(); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java index ac251f9ba7d..114110344a4 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,16 +85,17 @@ private static class SSLLoopbackSubscriber implements FlowTube { ExecutorService exec, CountDownLatch allBytesReceived) throws IOException { SSLServerSocketFactory fac = ctx.getServerSocketFactory(); + InetAddress loopback = InetAddress.getLoopbackAddress(); SSLServerSocket serv = (SSLServerSocket) fac.createServerSocket(); serv.setReuseAddress(false); - serv.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + serv.bind(new InetSocketAddress(loopback, 0)); SSLParameters params = serv.getSSLParameters(); params.setApplicationProtocols(new String[]{"proto2"}); serv.setSSLParameters(params); int serverPort = serv.getLocalPort(); - clientSock = new Socket("localhost", serverPort); + clientSock = new Socket(loopback, serverPort); serverSock = (SSLSocket) serv.accept(); this.buffer = new LinkedBlockingQueue<>(); this.allBytesReceived = allBytesReceived; @@ -107,6 +108,7 @@ private static class SSLLoopbackSubscriber implements FlowTube { } public void start() { + System.out.println("Starting: server listening at: " + serverSock.getLocalSocketAddress()); thread1.start(); thread2.start(); thread3.start(); @@ -144,6 +146,7 @@ private void clientReader() { publisher.submit(List.of(bb)); } } catch (Throwable e) { + System.out.println("clientReader got exception: " + e); e.printStackTrace(); Utils.close(clientSock); } @@ -176,6 +179,7 @@ private void clientWriter() { clientSubscription.request(1); } } catch (Throwable e) { + System.out.println("clientWriter got exception: " + e); e.printStackTrace(); } } @@ -212,6 +216,7 @@ private void serverLoopback() { is.close(); os.close(); serverSock.close(); + System.out.println("serverLoopback exiting normally"); return; } os.write(bb, 0, n); @@ -219,7 +224,10 @@ private void serverLoopback() { loopCount.addAndGet(n); } } catch (Throwable e) { + System.out.println("serverLoopback got exception: " + e); e.printStackTrace(); + } finally { + System.out.println("serverLoopback exiting at count: " + loopCount.get()); } } diff --git a/test/jdk/java/nio/channels/etc/MemorySegments.java b/test/jdk/java/nio/channels/etc/MemorySegments.java new file mode 100644 index 00000000000..77da11759c7 --- /dev/null +++ b/test/jdk/java/nio/channels/etc/MemorySegments.java @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * 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 8333849 + * @summary Test ByteChannel implementations of read and write with ByteBuffers that are + * backed by MemorySegments allocated from an Arena + * @run junit MemorySegments + */ + +import java.io.IOException; +import java.lang.foreign.Arena; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.FileChannel; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Random; +import java.util.function.Supplier; +import java.util.stream.Stream; +import static java.nio.file.StandardOpenOption.*; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; + +class MemorySegments { + private static final int SIZE = 100; // buffer size used by tests + + /** + * Return a stream of suppliers for each Arena type. A supplier is used to avoid JUnit + * closing the Arena and failing (as some Arenas are not closable). + */ + static Stream<Supplier<Arena>> arenaSuppliers() { + return Stream.of(Arena::global, Arena::ofAuto, Arena::ofConfined, Arena::ofShared); + } + + /** + * SocketChannel read/write(ByteBuffer). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testSocketChannelReadWrite(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { + ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + + try (SocketChannel sc1 = SocketChannel.open(ssc.getLocalAddress()); + SocketChannel sc2 = ssc.accept()) { + + // write + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int nwritten = sc1.write(src); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + + // read + ByteBuffer dst = arena.allocate(SIZE + 100).asByteBuffer(); + int nread = sc2.read(dst); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } + + } finally { + tryClose(arena); + } + } + + /** + * SocketChannel write(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testSocketChannelGatheringWrite(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { + ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + + try (SocketChannel sc1 = SocketChannel.open(ssc.getLocalAddress()); + SocketChannel sc2 = ssc.accept()) { + + // gathering write + ByteBuffer src = arena.allocate(SIZE * 2).asByteBuffer(); + fillRandom(src); + ByteBuffer src1 = src.slice(0, SIZE); + ByteBuffer src2 = src.slice(SIZE, SIZE); + var srcs = new ByteBuffer[] { src1, src2 }; + int nwritten = (int) sc1.write(srcs); + assertTrue(nwritten > 0); + assertEquals(Math.min(nwritten, SIZE), src1.position()); + assertEquals(nwritten, src1.position() + src2.position()); + + // read + ByteBuffer dst = arena.allocate(SIZE * 2 + 50).asByteBuffer(); + int nread = sc2.read(dst); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } + + } finally { + tryClose(arena); + } + } + + /** + * SocketChannel read(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testSocketChannelScatteringRead(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (ServerSocketChannel ssc = ServerSocketChannel.open()) { + ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + + try (SocketChannel sc1 = SocketChannel.open(ssc.getLocalAddress()); + SocketChannel sc2 = ssc.accept()) { + + // write + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int nwritten = sc1.write(src); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + + // scattering read + ByteBuffer dst = arena.allocate(SIZE + 50).asByteBuffer(); + ByteBuffer dst1 = dst.slice(0, 50); + ByteBuffer dst2 = dst.slice(50, dst.capacity() - 50); + var dsts = new ByteBuffer[]{ dst1, dst2 }; + int nread = (int) sc2.read(dsts); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertTrue(dst1.position() > 0); + assertEquals(nread, dst1.position() + dst2.position()); + + // check contents + src.flip(); + assertEquals(src, dst.slice(0, nread)); + } + + } finally { + tryClose(arena); + } + } + + /** + * DatagramChannel send/receive(ByteBuffer). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testDatagramChannelSendReceive(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (DatagramChannel dc = DatagramChannel.open()) { + dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + SocketAddress target = dc.getLocalAddress(); + + // send + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int n = dc.send(src, target); + assertEquals(SIZE, n); + assertFalse(src.hasRemaining()); + + // receive + ByteBuffer dst = arena.allocate(SIZE + 100).asByteBuffer(); + SocketAddress remote = dc.receive(dst); + assertEquals(remote, target); + assertEquals(SIZE, dst.position()); + + // check contents + src.clear(); + dst.flip(); + assertEquals(src, dst); + } finally { + tryClose(arena); + } + } + + /** + * DatagramChannel read/write(ByteBuffer). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testDatagramChannelReadWrite(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (DatagramChannel dc = DatagramChannel.open()) { + dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + SocketAddress target = dc.getLocalAddress(); + dc.connect(target); + + // write + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int n = dc.write(src); + assertEquals(SIZE, n); + assertFalse(src.hasRemaining()); + + // read + ByteBuffer dst = arena.allocate(SIZE + 100).asByteBuffer(); + n = dc.read(dst); + assertEquals(SIZE, n); + assertEquals(SIZE, dst.position()); + + // check contents + src.clear(); + dst.flip(); + assertEquals(src, dst); + } finally { + tryClose(arena); + } + } + + /** + * DatagramChannel write(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testDatagramChannelGatheringWrite(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (DatagramChannel dc = DatagramChannel.open()) { + dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + SocketAddress target = dc.getLocalAddress(); + dc.connect(target); + + // gathering write + ByteBuffer src1 = arena.allocate(SIZE).asByteBuffer(); + ByteBuffer src2 = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src1); + fillRandom(src2); + var srcs = new ByteBuffer[] { src1, src2 }; + int nwritten = (int) dc.write(srcs); + assertEquals(SIZE*2, nwritten); + assertFalse(src1.hasRemaining()); + assertFalse(src2.hasRemaining()); + + // read + ByteBuffer dst = arena.allocate(SIZE*2 + 50).asByteBuffer(); + int nread = dc.read(dst); + assertEquals(SIZE*2, nread); + assertEquals(SIZE*2, dst.position()); + + // check contents + src1.flip(); + src2.flip(); + assertEquals(src1, dst.slice(0, SIZE)); + assertEquals(src2, dst.slice(SIZE, SIZE)); + } finally { + tryClose(arena); + } + } + + /** + * DatagramChannel read(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testDatagramChannelScatteringRead(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + try (DatagramChannel dc = DatagramChannel.open()) { + dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + SocketAddress target = dc.getLocalAddress(); + dc.connect(target); + + // write + ByteBuffer src = arena.allocate(SIZE*2).asByteBuffer(); + fillRandom(src); + int nwritten = dc.write(src); + assertEquals(SIZE*2, nwritten); + assertEquals(nwritten, src.position()); + + // scattering read + ByteBuffer dst1 = arena.allocate(SIZE).asByteBuffer(); + ByteBuffer dst2 = arena.allocate(SIZE + 50).asByteBuffer(); + var dsts = new ByteBuffer[] { dst1, dst2 }; + int nread = (int) dc.read(dsts); + assertEquals(SIZE*2, nread); + assertEquals(nread, dst1.position() + dst2.position()); + + // check contents + dst1.flip(); + assertEquals(src.slice(0, SIZE), dst1); + dst2.flip(); + assertEquals(src.slice(SIZE, SIZE), dst2); + } finally { + tryClose(arena); + } + } + + /** + * FileChannel read/write(ByteBuffer). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testFileChannelReadWrite(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + Path file = Files.createTempFile(Path.of("."), "test", "dat"); + try (FileChannel fc = FileChannel.open(file, READ, WRITE)) { + + // write + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int nwritten = fc.write(src); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + assertEquals(nwritten, (int) fc.position()); + assertEquals(nwritten, (int) fc.size()); + + // read + ByteBuffer dst = arena.allocate(SIZE + 100).asByteBuffer(); + fc.position(0); + int nread = fc.read(dst); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + assertEquals(nread, (int) fc.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + + // reset + fc.truncate(0L); + src.clear(); + dst.clear(); + + // write with position + nwritten = fc.write(src, 10L); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + assertEquals(0, (int) fc.position()); + assertEquals(nwritten + 10, (int) fc.size()); + + // read with position + nread = fc.read(dst, 10L); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + assertEquals(0, (int)fc.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } finally { + tryClose(arena); + } + } + + /** + * FileChannel write(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testFileChannelGatheringWrite(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + Path file = Files.createTempFile(Path.of(""), "test", "dat"); + try (FileChannel fc = FileChannel.open(file, READ, WRITE)) { + + // gathering write + ByteBuffer src = arena.allocate(SIZE * 2).asByteBuffer(); + fillRandom(src); + ByteBuffer src1 = src.slice(0, SIZE); + ByteBuffer src2 = src.slice(SIZE, SIZE); + var srcs = new ByteBuffer[] { src1, src2 }; + int nwritten = (int) fc.write(srcs); + assertTrue(nwritten > 0); + assertEquals(Math.min(nwritten, SIZE), src1.position()); + assertEquals(nwritten, src1.position() + src2.position()); + assertEquals(nwritten, (int) fc.position()); + assertEquals(nwritten, (int) fc.size()); + + // read + ByteBuffer dst = arena.allocate(SIZE*2 + 50).asByteBuffer(); + fc.position(0); + int nread = fc.read(dst); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + assertEquals(nread, (int) fc.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } finally { + tryClose(arena); + } + } + + /** + * FileChannel read(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testFileChannelScatteringRead(Supplier<Arena> arenaSupplier) throws IOException { + Arena arena = arenaSupplier.get(); + Path file = Files.createTempFile(Path.of(""), "test", "dat"); + try (FileChannel fc = FileChannel.open(file, READ, WRITE)) { + + // write + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int nwritten = fc.write(src); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + assertEquals(nwritten, (int) fc.position()); + assertEquals(nwritten, (int) fc.size()); + + // scattering read + ByteBuffer dst = arena.allocate(SIZE + 50).asByteBuffer(); + ByteBuffer dst1 = dst.slice(0, 50); + ByteBuffer dst2 = dst.slice(50, dst.capacity() - 50); + var dsts = new ByteBuffer[] { dst1, dst2 }; + fc.position(0); + int nread = (int) fc.read(dsts); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertTrue(dst1.position() > 0); + assertEquals(nread, dst1.position() + dst2.position()); + assertEquals(nread, (int) fc.position()); + + // check contents + dst.limit(nread); + assertEquals(src.slice(0, nread), dst); + } finally { + tryClose(arena); + } + } + + /** + * Fill the buffer with random bytes. + */ + private void fillRandom(ByteBuffer bb) { + Random r = new Random(); + int pos = bb.position(); + while (bb.hasRemaining()) { + bb.put((byte) r.nextInt(256)); + } + bb.position(pos); + } + + /** + * Attempt to close the given Arena. + */ + private boolean tryClose(Arena arena) { + try { + arena.close(); + return true; + } catch (UnsupportedOperationException e) { + return false; + } + } + +} diff --git a/test/jdk/java/rmi/reliability/benchmark/bench/Makefile b/test/jdk/java/rmi/reliability/benchmark/bench/Makefile index f0600d4df30..805d6216373 100644 --- a/test/jdk/java/rmi/reliability/benchmark/bench/Makefile +++ b/test/jdk/java/rmi/reliability/benchmark/bench/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,4 +47,3 @@ all: .classes clean: rm -f *.class .classes - diff --git a/test/jdk/java/rmi/reliability/benchmark/bench/rmi/Makefile b/test/jdk/java/rmi/reliability/benchmark/bench/rmi/Makefile index bb44d94f154..c142b3a2d05 100644 --- a/test/jdk/java/rmi/reliability/benchmark/bench/rmi/Makefile +++ b/test/jdk/java/rmi/reliability/benchmark/bench/rmi/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -72,4 +72,3 @@ altroot.clean: clean: altroot.clean rm -f *.class .classes - diff --git a/test/jdk/javax/crypto/SecretKeyFactory/evilprov/Makefile b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/Makefile index 918c31f0947..800e1817b42 100644 --- a/test/jdk/javax/crypto/SecretKeyFactory/evilprov/Makefile +++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ JAVABIN=$(JAVA_BASE)/bin JAVAC=$(JAVABIN)/javac JAVA=$(JAVABIN)/java -JAR=$(JAVABIN)/jar +JAR=$(JAVABIN)/jar JARSIGNER=$(JAVABIN)/jarsigner # Compile-time flags and paths diff --git a/test/jdk/javax/swing/JMenu/TestUngrab.java b/test/jdk/javax/swing/JMenu/TestUngrab.java index 64326009c6c..ca738dabcb0 100644 --- a/test/jdk/javax/swing/JMenu/TestUngrab.java +++ b/test/jdk/javax/swing/JMenu/TestUngrab.java @@ -27,7 +27,6 @@ * @test * @bug 8267374 * @key headful - * @requires (os.family == "mac") * @summary Verifies menu closes when main window is resized * @run main TestUngrab */ diff --git a/test/jdk/javax/swing/JPopupMenu/MouseDragPopupTest.java b/test/jdk/javax/swing/JPopupMenu/MouseDragPopupTest.java new file mode 100644 index 00000000000..e34b53d0360 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/MouseDragPopupTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +/* + * @test + * @bug 8315655 + * @summary Verifies Right click and dragging over a component with a popup menu will not open the popup + * @key headful + * @run main MouseDragPopupTest + */ +public class MouseDragPopupTest { + static JFrame frame; + static JPanel panel; + static Robot robot; + static volatile boolean failed; + static volatile Point srcPoint; + static volatile Dimension d; + + public static void main(String[] args) throws Exception { + try { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(100); + + SwingUtilities.invokeAndWait(() -> { + createAndShowGUI(); + }); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + srcPoint = frame.getLocationOnScreen(); + d = frame.getSize(); + }); + srcPoint.translate(2 * d.width / 3, 3 * d.height / 4); + + final Point dstPoint = new Point(srcPoint); + dstPoint.translate(4 * d.width / 15, 0); + + robot.mouseMove(srcPoint.x, srcPoint.y); + + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + + while (!srcPoint.equals(dstPoint)) { + srcPoint.translate(sign(dstPoint.x - srcPoint.x), 0); + robot.mouseMove(srcPoint.x, srcPoint.y); + } + + if (failed) { + throw new RuntimeException("Popup was shown, Test Failed."); + } + } finally { + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + static void createAndShowGUI() { + frame = new JFrame("MouseDragPopupTest"); + panel = new JPanel(); + JPanel innerPanel = new JPanel(); + JPopupMenu menu = new JPopupMenu(); + + menu.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + failed = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} + + @Override + public void popupMenuCanceled(PopupMenuEvent e) {} + }); + + menu.add("This should not appear"); + innerPanel.setComponentPopupMenu(menu); + + panel.add(new JLabel("Right click and drag from here")); + panel.add(innerPanel); + panel.add(new JLabel("to here")); + + frame.add(panel); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 3faabcd6f8d..1a4dbd22897 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,6 +139,30 @@ static PackageHandlers createMsiPackageHandlers() { String.format("TARGETDIR=\"%s\"", unpackDir.toAbsolutePath().normalize()))))); runMsiexecWithRetries(Executor.of("cmd", "/c", unpackBat.toString())); + + // + // WiX3 uses "." as the value of "DefaultDir" field for "ProgramFiles64Folder" folder in msi's Directory table + // WiX4 uses "PFiles64" as the value of "DefaultDir" field for "ProgramFiles64Folder" folder in msi's Directory table + // msiexec creates "Program Files/./<App Installation Directory>" from WiX3 msi which translates to "Program Files/<App Installation Directory>" + // msiexec creates "Program Files/PFiles64/<App Installation Directory>" from WiX4 msi + // So for WiX4 msi we need to transform "Program Files/PFiles64/<App Installation Directory>" into "Program Files/<App Installation Directory>" + // + // WiX4 does the same thing for %LocalAppData%. + // + for (var extraPathComponent : List.of("PFiles64", "LocalApp")) { + if (Files.isDirectory(unpackDir.resolve(extraPathComponent))) { + Path installationSubDirectory = getInstallationSubDirectory(cmd); + Path from = Path.of(extraPathComponent).resolve(installationSubDirectory); + Path to = installationSubDirectory; + TKit.trace(String.format("Convert [%s] into [%s] in [%s] directory", from, to, + unpackDir)); + ThrowingRunnable.toRunnable(() -> { + Files.createDirectories(unpackDir.resolve(to).getParent()); + Files.move(unpackDir.resolve(from), unpackDir.resolve(to)); + TKit.deleteDirectoryRecursive(unpackDir.resolve(extraPathComponent)); + }).run(); + } + } return destinationDir; }; return msi; diff --git a/test/jdk/tools/jpackage/windows/WinL10nTest.java b/test/jdk/tools/jpackage/windows/WinL10nTest.java index deb6b1a8705..a868fd5f051 100644 --- a/test/jdk/tools/jpackage/windows/WinL10nTest.java +++ b/test/jdk/tools/jpackage/windows/WinL10nTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.test.Executor; @@ -55,11 +56,11 @@ public class WinL10nTest { public WinL10nTest(WixFileInitializer wxlFileInitializers[], - String expectedCulture, String expectedErrorMessage, + String[] expectedCultures, String expectedErrorMessage, String userLanguage, String userCountry, boolean enableWixUIExtension) { this.wxlFileInitializers = wxlFileInitializers; - this.expectedCulture = expectedCulture; + this.expectedCultures = expectedCultures; this.expectedErrorMessage = expectedErrorMessage; this.userLanguage = userLanguage; this.userCountry = userCountry; @@ -69,56 +70,65 @@ public WinL10nTest(WixFileInitializer wxlFileInitializers[], @Parameters public static List<Object[]> data() { return List.of(new Object[][]{ - {null, "en-us", null, null, null, false}, - {null, "en-us", null, "en", "US", false}, - {null, "en-us", null, "en", "US", true}, - {null, "de-de", null, "de", "DE", false}, - {null, "de-de", null, "de", "DE", true}, - {null, "ja-jp", null, "ja", "JP", false}, - {null, "ja-jp", null, "ja", "JP", true}, - {null, "zh-cn", null, "zh", "CN", false}, - {null, "zh-cn", null, "zh", "CN", true}, + {null, new String[] {"en-us"}, null, null, null, false}, + {null, new String[] {"en-us"}, null, "en", "US", false}, + {null, new String[] {"en-us"}, null, "en", "US", true}, + {null, new String[] {"de-de"}, null, "de", "DE", false}, + {null, new String[] {"de-de"}, null, "de", "DE", true}, + {null, new String[] {"ja-jp"}, null, "ja", "JP", false}, + {null, new String[] {"ja-jp"}, null, "ja", "JP", true}, + {null, new String[] {"zh-cn"}, null, "zh", "CN", false}, + {null, new String[] {"zh-cn"}, null, "zh", "CN", true}, {new WixFileInitializer[] { WixFileInitializer.create("a.wxl", "en-us") - }, "en-us", null, null, null, false}, + }, new String[] {"en-us"}, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("a.wxl", "fr") - }, "fr;en-us", null, null, null, false}, + }, new String[] {"fr", "en-us"}, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("a.wxl", "fr"), WixFileInitializer.create("b.wxl", "fr") - }, "fr;en-us", null, null, null, false}, + }, new String[] {"fr", "en-us"}, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("a.wxl", "it"), WixFileInitializer.create("b.wxl", "fr") - }, "it;fr;en-us", null, null, null, false}, + }, new String[] {"it", "fr", "en-us"}, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("c.wxl", "it"), WixFileInitializer.create("b.wxl", "fr") - }, "fr;it;en-us", null, null, null, false}, + }, new String[] {"fr", "it", "en-us"}, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("a.wxl", "fr"), WixFileInitializer.create("b.wxl", "it"), WixFileInitializer.create("c.wxl", "fr"), WixFileInitializer.create("d.wxl", "it") - }, "fr;it;en-us", null, null, null, false}, + }, new String[] {"fr", "it", "en-us"}, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("c.wxl", "it"), WixFileInitializer.createMalformed("b.wxl") }, null, null, null, null, false}, {new WixFileInitializer[] { WixFileInitializer.create("MsiInstallerStrings_de.wxl", "de") - }, "en-us", null, null, null, false} + }, new String[] {"en-us"}, null, null, null, false} }); } - private static Stream<String> getLightCommandLine( - Executor.Result result) { - return result.getOutput().stream().filter(s -> { + private static Stream<String> getBuildCommandLine(Executor.Result result) { + return result.getOutput().stream().filter(createToolCommandLinePredicate("light").or( + createToolCommandLinePredicate("wix"))); + } + + private static boolean isWix3(Executor.Result result) { + return result.getOutput().stream().anyMatch(createToolCommandLinePredicate("light")); + } + + private final static Predicate<String> createToolCommandLinePredicate(String wixToolName) { + var toolFileName = wixToolName + ".exe"; + return (s) -> { s = s.trim(); - return s.startsWith("light.exe") || ((s.contains("\\light.exe ") - && s.contains(" -out "))); - }); + return s.startsWith(toolFileName) || ((s.contains(String.format("\\%s ", toolFileName)) && s. + contains(" -out "))); + }; } private static List<TKit.TextStreamVerifier> createDefaultL10nFilesLocVerifiers(Path tempDir) { @@ -148,14 +158,23 @@ public void test() throws IOException { // 2. Instruct test to save jpackage output. cmd.setFakeRuntime().saveConsoleOutput(true); + boolean withJavaOptions = false; + // Set JVM default locale that is used to select primary l10n file. if (userLanguage != null) { + withJavaOptions = true; cmd.addArguments("-J-Duser.language=" + userLanguage); } if (userCountry != null) { + withJavaOptions = true; cmd.addArguments("-J-Duser.country=" + userCountry); } + if (withJavaOptions) { + // Use jpackage as a command to allow "-J" options come through + cmd.useToolProvider(false); + } + // Cultures handling is affected by the WiX extensions used. // By default only WixUtilExtension is used, this flag // additionally enables WixUIExtension. @@ -169,9 +188,16 @@ public void test() throws IOException { cmd.addArguments("--temp", tempDir.toString()); }) .addBundleVerifier((cmd, result) -> { - if (expectedCulture != null) { - TKit.assertTextStream("-cultures:" + expectedCulture).apply( - getLightCommandLine(result)); + if (expectedCultures != null) { + String expected; + if (isWix3(result)) { + expected = "-cultures:" + String.join(";", expectedCultures); + } else { + expected = Stream.of(expectedCultures).map(culture -> { + return String.join(" ", "-culture", culture); + }).collect(Collectors.joining(" ")); + } + TKit.assertTextStream(expected).apply(getBuildCommandLine(result)); } if (expectedErrorMessage != null) { @@ -180,24 +206,24 @@ public void test() throws IOException { } if (wxlFileInitializers != null) { + var wixSrcDir = Path.of(cmd.getArgumentValue("--temp")).resolve("config"); + if (allWxlFilesValid) { for (var v : wxlFileInitializers) { if (!v.name.startsWith("MsiInstallerStrings_")) { - v.createCmdOutputVerifier(resourceDir).apply( - getLightCommandLine(result)); + v.createCmdOutputVerifier(wixSrcDir).apply(getBuildCommandLine(result)); } } Path tempDir = getTempDirectory(cmd, tempRoot).toAbsolutePath(); for (var v : createDefaultL10nFilesLocVerifiers(tempDir)) { - v.apply(getLightCommandLine(result)); + v.apply(getBuildCommandLine(result)); } } else { Stream.of(wxlFileInitializers) .filter(Predicate.not(WixFileInitializer::isValid)) .forEach(v -> v.createCmdOutputVerifier( - resourceDir).apply(result.getOutput().stream())); - TKit.assertFalse( - getLightCommandLine(result).findAny().isPresent(), + wixSrcDir).apply(result.getOutput().stream())); + TKit.assertFalse(getBuildCommandLine(result).findAny().isPresent(), "Check light.exe was not invoked"); } } @@ -223,7 +249,7 @@ public void test() throws IOException { } final private WixFileInitializer[] wxlFileInitializers; - final private String expectedCulture; + final private String[] expectedCultures; final private String expectedErrorMessage; final private String userLanguage; final private String userCountry; diff --git a/test/lib-test/jdk/test/whitebox/CPUInfoTest.java b/test/lib-test/jdk/test/whitebox/CPUInfoTest.java index 138327ec44f..859ec772229 100644 --- a/test/lib-test/jdk/test/whitebox/CPUInfoTest.java +++ b/test/lib-test/jdk/test/whitebox/CPUInfoTest.java @@ -65,7 +65,8 @@ public class CPUInfoTest { "avx512_vbmi2", "avx512_vbmi", "rdtscp", "rdpid", "hv", "fsrm", "avx512_bitalg", "gfni", "f16c", "pku", "ospke", "cet_ibt", - "cet_ss", "avx512_ifma", "serialize", "avx_ifma" + "cet_ss", "avx512_ifma", "serialize", "avx_ifma", + "apx_f" ); // @formatter:on // Checkstyle: resume diff --git a/test/micro/org/openjdk/bench/java/lang/StringIndexOfHuge.java b/test/micro/org/openjdk/bench/java/lang/StringIndexOfHuge.java new file mode 100644 index 00000000000..cac86bcc17f --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringIndexOfHuge.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 3) +public class StringIndexOfHuge { + + private String dataString; + private String dataString16; + private String dataStringHuge; + private String dataStringHuge16; + private String earlyMatchString; + private String earlyMatchString16; + private String midMatchString; + private String midMatchString16; + private String lateMatchString; + private String lateMatchString16; + + private String searchString; + private String searchString16; + private String searchStringSmall; + private String searchStringSmall16; + + private String searchStringHuge; + private String searchStringHuge16; + + private String searchNoMatch; + private String searchNoMatch16; + + private String Amdahl_1; + private String Amdahl_2; + private String Amdahl_3; + private String Amdahl_4; + private String Amdahl_5; + private String Amdahl_6; + + @Setup + public void setup() { + dataString = "ngdflsoscargfdgf"; + dataString16 = "ngdfilso\u01facargfd\u01eef"; + dataStringHuge = (("A".repeat(32) + "B".repeat(32)).repeat(16) + "X").repeat(2) + "bB"; + dataStringHuge16 = "\u01de" + (("A".repeat(32) + "B".repeat(32)).repeat(16) + "\u01fe").repeat(2) + "\u01eeB"; + earlyMatchString = dataStringHuge.substring(0, 34); + earlyMatchString16 = dataStringHuge16.substring(0, 34); + midMatchString = dataStringHuge.substring(dataStringHuge.length() / 2 - 16, dataStringHuge.length() / 2 + 17); + midMatchString16 = dataStringHuge16.substring(dataStringHuge16.length() / 2 - 16, dataStringHuge16.length() / 2 + 17); + lateMatchString = dataStringHuge.substring(dataStringHuge.length() - 31); + lateMatchString16 = dataStringHuge16.substring(dataStringHuge16.length() - 31); + + searchString = "oscar"; + searchString16 = "o\u01facar"; + searchStringSmall = "dgf"; + searchStringSmall16 = "d\u01eef"; + + searchStringHuge = "capaapapapasdkajdlkajskldjaslkajdlkajskldjaslkjdlkasjdsalk"; + searchStringHuge16 = "capaapapapasdkajdlka\u01feskldjaslkajdlkajskldjaslkjdlkasjdsalk"; + + searchNoMatch = "XYXyxYxy".repeat(22); + searchNoMatch16 = "\u01ab\u01ba\u01cb\u01bc\u01de\u01ed\u01fa\u01af".repeat(22); + + Amdahl_1 = "B".repeat(30) + "X" + "A".repeat(30); + Amdahl_2 = "A".repeat(32) + "F" + "B".repeat(32); + Amdahl_3 = "A".repeat(32) + "B".repeat(32) + "XbB"; + Amdahl_4 = "B".repeat(30) + "\u01ef" + "A".repeat(30); + Amdahl_5 = "A".repeat(32) + "\u01ef" + "B".repeat(32); + Amdahl_6 = "A".repeat(32) + "B".repeat(32) + "\u01fe\u01eeB"; + } + + + /** IndexOf Micros */ + @Benchmark + public int searchHugeEarlyMatch() { + return dataStringHuge.indexOf(earlyMatchString); + } + + @Benchmark + public int searchHugeMiddleMatch() { + return dataStringHuge.indexOf(midMatchString); + } + + @Benchmark + public int searchHugeLateMatch() { + return dataStringHuge.indexOf(lateMatchString); + } + + @Benchmark + public int searchHugeNoMatch() { + return dataStringHuge.indexOf(searchNoMatch); + } + + @Benchmark + public int searchSmallEarlyMatch() { + return searchString.indexOf(searchString); + } + + @Benchmark + public int searchSmallMidMatch() { + return dataString.indexOf(searchString); + } + + @Benchmark + public int searchSmallLateMatch() { + return dataString.indexOf(searchStringSmall); + } + + @Benchmark + public int searchHugeLargeSubstring() { + return dataStringHuge.indexOf(Amdahl_1, 74); + } + + @Benchmark + public int searchHugeLargeSubstringNoMatch() { + return dataStringHuge.indexOf(Amdahl_2, 64); + } + + @Benchmark + public int searchSubstringLongerThanString() { + return midMatchString.indexOf(dataStringHuge, 3); + } + + @Benchmark + public int searchHugeWorstCase() { + return dataStringHuge.indexOf(Amdahl_3); + } + + @Benchmark + public int search16HugeEarlyMatch() { + return dataStringHuge16.indexOf(earlyMatchString); + } + + @Benchmark + public int search16HugeMiddleMatch() { + return dataStringHuge16.indexOf(midMatchString); + } + + @Benchmark + public int search16HugeLateMatch() { + return dataStringHuge16.indexOf(lateMatchString); + } + + @Benchmark + public int search16HugeNoMatch() { + return dataStringHuge16.indexOf(searchNoMatch); + } + + @Benchmark + public int search16SmallEarlyMatch() { + return searchString16.indexOf(searchString); + } + + @Benchmark + public int search16SmallMidMatch() { + return dataString16.indexOf(searchString); + } + + @Benchmark + public int search16SmallLateMatch() { + return dataString16.indexOf(searchStringSmall); + } + + @Benchmark + public int search16HugeLargeSubstring() { + return dataStringHuge16.indexOf(Amdahl_1, 74); + } + + @Benchmark + public int search16HugeLargeSubstringNoMatch() { + return dataStringHuge16.indexOf(Amdahl_2, 64); + } + + @Benchmark + public int search16SubstringLongerThanString() { + return midMatchString16.indexOf(dataStringHuge, 3); + } + + @Benchmark + public int search16HugeWorstCase() { + return dataStringHuge16.indexOf(Amdahl_3); + } + + @Benchmark + public int search16HugeEarlyMatch16() { + return dataStringHuge16.indexOf(earlyMatchString16); + } + + @Benchmark + public int search16HugeMiddleMatch16() { + return dataStringHuge16.indexOf(midMatchString16); + } + + @Benchmark + public int search16HugeLateMatch16() { + return dataStringHuge16.indexOf(lateMatchString16); + } + + @Benchmark + public int search16HugeNoMatch16() { + return dataStringHuge16.indexOf(searchNoMatch16); + } + + @Benchmark + public int search16SmallEarlyMatch16() { + return searchString16.indexOf(searchString16); + } + + @Benchmark + public int search16SmallMidMatch16() { + return dataString16.indexOf(searchString16); + } + + @Benchmark + public int search16SmallLateMatch16() { + return dataString16.indexOf(searchStringSmall16); + } + + @Benchmark + public int search16HugeLargeSubstring16() { + return dataStringHuge16.indexOf(Amdahl_4, 74); + } + + @Benchmark + public int search16HugeLargeSubstringNoMatch16() { + return dataStringHuge16.indexOf(Amdahl_5, 64); + } + + @Benchmark + public int search16SubstringLongerThanString16() { + return midMatchString16.indexOf(dataStringHuge16, 3); + } + + @Benchmark + public int search16HugeWorstCase16() { + return dataStringHuge16.indexOf(Amdahl_6); + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java b/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java new file mode 100644 index 00000000000..ee0779faecf --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024, Alibaba Group Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.*; + +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.infra.Blackhole; + +/* test allocation speed of object with final field */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +@Warmup(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3) +public class FinalFieldInitialize { + final static int LEN = 100_000; + Object arr[] = null; + @Setup + public void setup(){ + arr = new Object[LEN]; + } + + @Benchmark + public void testAlloc(Blackhole bh) { + for (int i=0; i<LEN; i++) { + arr[i] = new TObj(); + } + bh.consume(arr); + } + + @Benchmark + public void testAllocWithFinal(Blackhole bh) { + for (int i=0; i<LEN; i++) { + arr[i] = new TObjWithFinal(); + } + bh.consume(arr); + } +} + +class TObj { + private int i; + private long l; + private boolean b; + + public TObj() { + i = 10; + l = 100L; + b = true; + } +} + +class TObjWithFinal { + private int i; + private long l; + private final boolean b; + + public TObjWithFinal() { + i = 10; + l = 100L; + b = true; + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/PopCount.java b/test/micro/org/openjdk/bench/vm/compiler/PopCount.java new file mode 100644 index 00000000000..cbf44023c1e --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/PopCount.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 IBM Corporation. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 5) +public class PopCount { + int numTests = 100_000; + + @Benchmark + public long test() { + long l1 = 1, l2 = 2, l3 = 3, l4 = 4, l5 = 5, l6 = 6, l7 = 7, l8 = 9, l9 = 9, l10 = 10; + for (long i = 0; i < numTests; i++) { + l1 ^= Long.bitCount(l1) + i; + l2 ^= Long.bitCount(l2) + i; + l3 ^= Long.bitCount(l3) + i; + l4 ^= Long.bitCount(l4) + i; + l5 ^= Long.bitCount(l5) + i; + l6 ^= Long.bitCount(l6) + i; + l7 ^= Long.bitCount(l7) + i; + l8 ^= Long.bitCount(l8) + i; + l9 ^= Long.bitCount(l9) + i; + l10 ^= Long.bitCount(l10) + i; + } + return l1 + l2 + l3 + l4 + l5 + l6 + l7 + l8 + l9 + l10; + } + +}