From b670ee05441058f03bb369bba07aa389a423e860 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Mon, 11 May 2026 14:02:22 +0000 Subject: [PATCH 1/2] 8384281: [BACKOUT] C2: Deep recursion with cmovP_regNode::bottom_type Reviewed-by: mbaesken, rrich, dbriemann --- src/hotspot/share/adlc/formssel.cpp | 108 ++++++++++++ src/hotspot/share/adlc/formssel.hpp | 9 +- src/hotspot/share/adlc/output_c.cpp | 41 +++-- src/hotspot/share/adlc/output_h.cpp | 108 +++++++++++- src/hotspot/share/opto/machnode.cpp | 21 ++- src/hotspot/share/opto/machnode.hpp | 37 ++-- src/hotspot/share/opto/matcher.hpp | 1 + .../compiler/types/TestCMovePMachType.java | 161 ------------------ 8 files changed, 282 insertions(+), 204 deletions(-) delete mode 100644 test/hotspot/jtreg/compiler/types/TestCMovePMachType.java diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 79779782c2a3..5802217c1c1c 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -453,6 +453,14 @@ Form::DataType InstructForm::is_ideal_store() const { return _matrule->is_ideal_store(); } +// Return 'true' if this instruction matches an ideal vector node +bool InstructForm::is_vector() const { + if( _matrule == nullptr ) return false; + + return _matrule->is_vector(); +} + + // Return the input register that must match the output register // If this is not required, return 0 uint InstructForm::two_address(FormDict &globals) { @@ -759,6 +767,51 @@ int InstructForm::memory_operand(FormDict &globals) const { return NO_MEMORY_OPERAND; } +// This instruction captures the machine-independent bottom_type +// Expected use is for pointer vs oop determination for LoadP +bool InstructForm::captures_bottom_type(FormDict &globals) const { + if (_matrule && _matrule->_rChild && + (!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type + !strcmp(_matrule->_rChild->_opType,"CastDD") || + !strcmp(_matrule->_rChild->_opType,"CastFF") || + !strcmp(_matrule->_rChild->_opType,"CastII") || + !strcmp(_matrule->_rChild->_opType,"CastLL") || + !strcmp(_matrule->_rChild->_opType,"CastVV") || + !strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type + !strcmp(_matrule->_rChild->_opType,"DecodeN") || + !strcmp(_matrule->_rChild->_opType,"EncodeP") || + !strcmp(_matrule->_rChild->_opType,"DecodeNKlass") || + !strcmp(_matrule->_rChild->_opType,"EncodePKlass") || + !strcmp(_matrule->_rChild->_opType,"LoadN") || + !strcmp(_matrule->_rChild->_opType,"LoadNKlass") || + !strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception + !strcmp(_matrule->_rChild->_opType,"CheckCastPP") || + !strcmp(_matrule->_rChild->_opType,"GetAndSetP") || + !strcmp(_matrule->_rChild->_opType,"GetAndSetN") || + !strcmp(_matrule->_rChild->_opType,"RotateLeft") || + !strcmp(_matrule->_rChild->_opType,"RotateRight") || +#if INCLUDE_SHENANDOAHGC + !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") || + !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") || +#endif + !strcmp(_matrule->_rChild->_opType,"StrInflatedCopy") || + !strcmp(_matrule->_rChild->_opType,"VectorCmpMasked")|| + !strcmp(_matrule->_rChild->_opType,"VectorMaskGen")|| + !strcmp(_matrule->_rChild->_opType,"VerifyVectorAlignment")|| + !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") || + !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true; + else if ( is_ideal_load() == Form::idealP ) return true; + else if ( is_ideal_store() != Form::none ) return true; + + if (needs_base_oop_edge(globals)) return true; + + if (is_vector()) return true; + if (is_mach_constant()) return true; + + return false; +} + + // Access instr_cost attribute or return null. const char* InstructForm::cost() { for (Attribute* cur = _attribs; cur != nullptr; cur = (Attribute*)cur->_next) { @@ -1128,6 +1181,9 @@ const char *InstructForm::mach_base_class(FormDict &globals) const { } else if (is_mach_constant()) { return "MachConstantNode"; + } + else if (captures_bottom_type(globals)) { + return "MachTypeNode"; } else { return "MachNode"; } @@ -4281,6 +4337,58 @@ Form::DataType MatchRule::is_ideal_load() const { return ideal_load; } +bool MatchRule::is_vector() const { + static const char *vector_list[] = { + "AddVB","AddVS","AddVI","AddVL","AddVHF","AddVF","AddVD", + "SubVB","SubVS","SubVI","SubVL","SubVHF","SubVF","SubVD", + "MulVB","MulVS","MulVI","MulVL","MulVHF","MulVF","MulVD", + "DivVHF","DivVF","DivVD", + "AbsVB","AbsVS","AbsVI","AbsVL","AbsVF","AbsVD", + "NegVF","NegVD","NegVI","NegVL", + "SqrtVD","SqrtVF","SqrtVHF", + "AndV" ,"XorV" ,"OrV", + "MaxV", "MinV", "MinVHF", "MaxVHF", "UMinV", "UMaxV", + "CompressV", "ExpandV", "CompressM", "CompressBitsV", "ExpandBitsV", + "AddReductionVI", "AddReductionVL", + "AddReductionVHF", "AddReductionVF", "AddReductionVD", + "MulReductionVI", "MulReductionVL", + "MulReductionVHF", "MulReductionVF", "MulReductionVD", + "MaxReductionV", "MinReductionV", + "AndReductionV", "OrReductionV", "XorReductionV", + "MulAddVS2VI", "MacroLogicV", + "LShiftCntV","RShiftCntV", + "LShiftVB","LShiftVS","LShiftVI","LShiftVL", + "RShiftVB","RShiftVS","RShiftVI","RShiftVL", + "URShiftVB","URShiftVS","URShiftVI","URShiftVL", + "Replicate","ReverseV","ReverseBytesV", + "RoundDoubleModeV","RotateLeftV" , "RotateRightV", "LoadVector","StoreVector", + "LoadVectorGather", "StoreVectorScatter", "LoadVectorGatherMasked", "StoreVectorScatterMasked", + "SelectFromTwoVector", "VectorTest", "VectorLoadMask", "VectorStoreMask", "VectorBlend", "VectorInsert", + "VectorRearrange", "VectorLoadShuffle", "VectorLoadConst", + "VectorCastB2X", "VectorCastS2X", "VectorCastI2X", + "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", "VectorCastF2HF", "VectorCastHF2F", + "VectorUCastB2X", "VectorUCastS2X", "VectorUCastI2X", + "VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked", + "FmaVD", "FmaVF", "FmaVHF", "PopCountVI", "PopCountVL", "PopulateIndex", "VectorLongToMask", + "CountLeadingZerosV", "CountTrailingZerosV", "SignumVF", "SignumVD", "SaturatingAddV", "SaturatingSubV", + // Next are vector mask ops. + "MaskAll", "AndVMask", "OrVMask", "XorVMask", "VectorMaskCast", + "RoundVF", "RoundVD", + // Next are not supported currently. + "PackB","PackS","PackI","PackL","PackF","PackD","Pack2L","Pack2D", + "ExtractB","ExtractUB","ExtractC","ExtractS","ExtractI","ExtractL","ExtractF","ExtractD" + }; + int cnt = sizeof(vector_list)/sizeof(char*); + if (_rChild) { + const char *opType = _rChild->_opType; + for (int i=0; iadd_req(inst%d->in(%d)); // unmatched ideal edge\n", inst_num, unmatched_edge); } - // Get bottom type from instruction whose result we are replacing - fprintf(fp, " root->_bottom_type = inst%d->bottom_type();\n", inst_num); + // If new instruction captures bottom type + if( root_form->captures_bottom_type(globals) ) { + // Get bottom type from instruction whose result we are replacing + fprintf(fp, " root->_bottom_type = inst%d->bottom_type();\n", inst_num); + } // Define result register and result operand fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%d));\n", inst_num); fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num); @@ -1584,8 +1587,11 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { fprintf(fp, " ((MachIfNode*)n%d)->_fcnt = _fcnt;\n", cnt); } - // Fill in the bottom_type - fprintf(fp, " n%d->_bottom_type = bottom_type();\n", cnt); + // Fill in the bottom_type where requested + if (node->captures_bottom_type(_globalNames) && + new_inst->captures_bottom_type(_globalNames)) { + fprintf(fp, " ((MachTypeNode*)n%d)->_bottom_type = bottom_type();\n", cnt); + } const char *resultOper = new_inst->reduce_result(); fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator(%s));\n", @@ -3959,15 +3965,13 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden } } - // Fill in the bottom_type - if (inst->_matrule != nullptr && strcmp(inst->_matrule->_opType, "PrefetchAllocation") == 0) { - // Special case, with AllocatePrefetchStyle == 3, this should be Type::MEMORY, but the graph - // seems unsound, needs further investigation - fprintf(fp_cpp, "%s node->_bottom_type = Type::ABIO;\n", indent); - } else { - fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent); + // Fill in the bottom_type where requested + if (inst->captures_bottom_type(_globalNames)) { + if (strncmp("MachCall", inst->mach_base_class(_globalNames), strlen("MachCall")) != 0 + && strncmp("MachIf", inst->mach_base_class(_globalNames), strlen("MachIf")) != 0) { + fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent); + } } - if( inst->is_ideal_if() ) { fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent); fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent); @@ -4022,8 +4026,10 @@ void InstructForm::define_cisc_version(ArchDesc& AD, FILE* fp_cpp) { fprintf(fp_cpp, "MachNode *%sNode::cisc_version(int offset) {\n", this->_ident); // Create the MachNode object fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); - // Fill in the bottom_type - fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); + // Fill in the bottom_type where requested + if ( this->captures_bottom_type(AD.globalNames()) ) { + fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); + } uint cur_num_opnds = num_opnds(); if (cur_num_opnds > 1 && cur_num_opnds != num_unique_opnds()) { @@ -4069,9 +4075,10 @@ void InstructForm::define_short_branch_methods(ArchDesc& AD, FILE* fp_cpp) { fprintf(fp_cpp, " node->_prob = _prob;\n"); fprintf(fp_cpp, " node->_fcnt = _fcnt;\n"); } - - // Fill in the bottom_type - fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); + // Fill in the bottom_type where requested + if ( this->captures_bottom_type(AD.globalNames()) ) { + fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n"); + } fprintf(fp_cpp, "\n"); // Short branch version must use same node index for access diff --git a/src/hotspot/share/adlc/output_h.cpp b/src/hotspot/share/adlc/output_h.cpp index f7389b5a1b1f..6cb82f4df7f7 100644 --- a/src/hotspot/share/adlc/output_h.cpp +++ b/src/hotspot/share/adlc/output_h.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1841,6 +1841,112 @@ void ArchDesc::declareClasses(FILE *fp) { fprintf(fp," virtual const Pipeline *pipeline() const;\n"); } + // Generate virtual function for MachNodeX::bottom_type when necessary + // + // Note on accuracy: Pointer-types of machine nodes need to be accurate, + // or else alias analysis on the matched graph may produce bad code. + // Moreover, the aliasing decisions made on machine-node graph must be + // no less accurate than those made on the ideal graph, or else the graph + // may fail to schedule. (Reason: Memory ops which are reordered in + // the ideal graph might look interdependent in the machine graph, + // thereby removing degrees of scheduling freedom that the optimizer + // assumed would be available.) + // + // %%% We should handle many of these cases with an explicit ADL clause: + // instruct foo() %{ ... bottom_type(TypeRawPtr::BOTTOM); ... %} + if( data_type != Form::none ) { + // A constant's bottom_type returns a Type containing its constant value + + // !!!!! + // Convert all ints, floats, ... to machine-independent TypeXs + // as is done for pointers + // + // Construct appropriate constant type containing the constant value. + fprintf(fp," virtual const class Type *bottom_type() const {\n"); + switch( data_type ) { + case Form::idealI: + fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n"); + break; + case Form::idealP: + case Form::idealN: + case Form::idealNKlass: + fprintf(fp," return opnd_array(1)->type();\n"); + break; + case Form::idealD: + fprintf(fp," return TypeD::make(opnd_array(1)->constantD());\n"); + break; + case Form::idealH: + fprintf(fp," return TypeH::make(opnd_array(1)->constantH());\n"); + break; + case Form::idealF: + fprintf(fp," return TypeF::make(opnd_array(1)->constantF());\n"); + break; + case Form::idealL: + fprintf(fp," return TypeLong::make(opnd_array(1)->constantL());\n"); + break; + default: + assert( false, "Unimplemented()" ); + break; + } + fprintf(fp," };\n"); + } +/* else if ( instr->_matrule && instr->_matrule->_rChild && + ( strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0 + || strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) { + // !!!!! !!!!! + // Provide explicit bottom type for conversions to int + // On Intel the result operand is a stackSlot, untyped. + fprintf(fp," virtual const class Type *bottom_type() const {"); + fprintf(fp, " return TypeInt::INT;"); + fprintf(fp, " };\n"); + }*/ + else if( instr->is_ideal_copy() && + !strcmp(instr->_matrule->_lChild->_opType,"stackSlotP") ) { + // !!!!! + // Special hack for ideal Copy of pointer. Bottom type is oop or not depending on input. + fprintf(fp," const Type *bottom_type() const { return in(1)->bottom_type(); } // Copy?\n"); + } + else if( instr->is_ideal_loadPC() ) { + // LoadPCNode provides the return address of a call to native code. + // Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM + // since it is a pointer to an internal VM location and must have a zero offset. + // Allocation detects derived pointers, in part, by their non-zero offsets. + fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // LoadPC?\n"); + } + else if( instr->is_ideal_box() ) { + // BoxNode provides the address of a stack slot. + // Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM + // This prevents raise_above_anti_dependences from complaining. It will + // complain if it sees that the pointer base is TypePtr::BOTTOM since + // it doesn't understand what that might alias. + fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // Box?\n"); + } + else if (instr->_matrule && instr->_matrule->_rChild && + (!strcmp(instr->_matrule->_rChild->_opType,"CMoveP") || !strcmp(instr->_matrule->_rChild->_opType,"CMoveN")) ) { + int offset = 1; + // Special special hack to see if the Cmp? has been incorporated in the conditional move + MatchNode *rl = instr->_matrule->_rChild->_lChild; + if (rl && !strcmp(rl->_opType, "Binary") && rl->_rChild && strncmp(rl->_rChild->_opType, "Cmp", 3) == 0) { + offset = 2; + fprintf(fp," const Type *bottom_type() const { if (req() == 3) return in(2)->bottom_type();\n\tconst Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // %s\n", + offset, offset+1, offset+1, instr->_matrule->_rChild->_opType); + } else { + // Special hack for ideal CMove; ideal type depends on inputs + fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // %s\n", + offset, offset+1, offset+1, instr->_matrule->_rChild->_opType); + } + } + else if (instr->is_tls_instruction()) { + // Special hack for tlsLoadP + fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // tlsLoadP\n"); + } + else if ( instr->is_ideal_if() ) { + fprintf(fp," const Type *bottom_type() const { return TypeTuple::IFBOTH; } // matched IfNode\n"); + } + else if ( instr->is_ideal_membar() ) { + fprintf(fp," const Type *bottom_type() const { return TypeTuple::MEMBAR; } // matched MemBar\n"); + } + // Check where 'ideal_type' must be customized /* if ( instr->_matrule && instr->_matrule->_rChild && diff --git a/src/hotspot/share/opto/machnode.cpp b/src/hotspot/share/opto/machnode.cpp index c35861df7350..ec861865ff59 100644 --- a/src/hotspot/share/opto/machnode.cpp +++ b/src/hotspot/share/opto/machnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -561,11 +561,7 @@ void MachNode::dump_spec(outputStream *st) const { if (barrier_data() != 0) { st->print(" barrier("); BarrierSet::barrier_set()->barrier_set_c2()->dump_barrier_data(this, st); - st->print(")"); - } - if (_bottom_type != nullptr) { - st->print(" "); - _bottom_type->dump_on(st); + st->print(") "); } } @@ -576,6 +572,19 @@ void MachNode::dump_format(PhaseRegAlloc *ra, outputStream *st) const { } #endif +//============================================================================= +#ifndef PRODUCT +void MachTypeNode::dump_spec(outputStream *st) const { + MachNode::dump_spec(st); + if (_bottom_type != nullptr) { + _bottom_type->dump_on(st); + } else { + st->print(" null"); + } +} +#endif + + //============================================================================= int MachConstantNode::constant_offset() { // Bind the offset lazily. diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index daa2aad960ad..b60313b7f758 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,7 +220,7 @@ class MachOper : public ResourceObj { // ADLC inherit from this class. class MachNode : public Node { public: - MachNode() : Node((uint)0), _bottom_type(nullptr), _barrier(0), _num_opnds(0), _opnds(nullptr) { + MachNode() : Node((uint)0), _barrier(0), _num_opnds(0), _opnds(nullptr) { init_class_id(Class_Mach); } // Required boilerplate @@ -282,9 +282,6 @@ class MachNode : public Node { // output have choices - but they must use the same choice. virtual uint two_adr( ) const { return 0; } - // Capture the type of the matched ideal node - const Type* _bottom_type; - // The GC might require some barrier metadata for machine code emission. uint8_t _barrier; @@ -334,17 +331,7 @@ class MachNode : public Node { virtual MachNode *Expand( State *, Node_List &proj_list, Node* mem ) { return this; } // Bottom_type call; value comes from operand0 - virtual const Type* bottom_type() const { - if (_bottom_type != nullptr) { - return _bottom_type; - } - const Type* res = _opnds[0]->type(); - // The type system around pointers is complex, do not rely on operand type then - assert(res != nullptr, "must be not null"); - assert(is_MachTemp() || res->isa_ptr() == nullptr, "must not be a pointer"); - return res; - } - + virtual const class Type *bottom_type() const { return _opnds[0]->type(); } virtual uint ideal_reg() const { const Type *t = _opnds[0]->type(); if (t == TypeInt::CC) { @@ -431,6 +418,20 @@ class MachIdealNode : public MachNode { virtual const class Type *bottom_type() const { return _opnds == nullptr ? Type::CONTROL : MachNode::bottom_type(); } }; +//------------------------------MachTypeNode---------------------------- +// Machine Nodes that need to retain a known Type. +class MachTypeNode : public MachNode { + virtual uint size_of() const { return sizeof(*this); } // Size is bigger +public: + MachTypeNode( ) {} + const Type *_bottom_type; + + virtual const class Type *bottom_type() const { return _bottom_type; } +#ifndef PRODUCT + virtual void dump_spec(outputStream *st) const; +#endif +}; + //------------------------------MachBreakpointNode---------------------------- // Machine breakpoint or interrupt Node class MachBreakpointNode : public MachIdealNode { @@ -476,12 +477,12 @@ class MachConstantBaseNode : public MachIdealNode { //------------------------------MachConstantNode------------------------------- // Machine node that holds a constant which is stored in the constant table. -class MachConstantNode : public MachNode { +class MachConstantNode : public MachTypeNode { protected: ConstantTable::Constant _constant; // This node's constant. public: - MachConstantNode() : MachNode() { + MachConstantNode() : MachTypeNode() { init_class_id(Class_MachConstant); } diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 31f4a7822477..a3d0f8e7d6c6 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -38,6 +38,7 @@ class Compile; class Node; class MachNode; +class MachTypeNode; class MachOper; //---------------------------Matcher------------------------------------------- diff --git a/test/hotspot/jtreg/compiler/types/TestCMovePMachType.java b/test/hotspot/jtreg/compiler/types/TestCMovePMachType.java deleted file mode 100644 index 48069fd900eb..000000000000 --- a/test/hotspot/jtreg/compiler/types/TestCMovePMachType.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. - * 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.types; - -/* - * @test - * @bug 8379667 - * @summary C2 crashes due to deep recursion in cmovP_regNode::bottom_type - * @run main/othervm -Xbatch -XX:CompileCommand=memlimit,${test.main.class}::test,50M~crash ${test.main.class} - */ -public class TestCMovePMachType { - interface I0 {} - interface I1 {} - interface I2 {} - interface I3 {} - interface I4 {} - interface I5 {} - interface I6 {} - interface I7 {} - interface I8 {} - interface I9 {} - interface I10 {} - interface I11 {} - interface I12 {} - interface I13 {} - interface I14 {} - interface I15 {} - interface I16 {} - interface I17 {} - interface I18 {} - interface I19 {} - interface IA {} - interface IB {} - - static class P implements I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, I16, I17, I18, I19 { - int v; - } - - static class A extends P implements IA {} - static class B extends P implements IB {} - - public static void main(String[] args) { - A a = new A(); - B b = new B(); - for (int i = 0; i < 20000; i++) { - test(a, b, false, false); - test(a, b, false, true); - test(a, b, true, false); - test(a, b, true, true); - } - } - - // This method is compiled into a giant chain of CMovePs, which leads to a deep recursion when - // invoking Node::bottom_type on the corresponding MachNodes - private static int test(A p1, B p2, boolean b1, boolean b2) { - P p = b1 ? p1 : p2; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - p = b2 ? p : p2; - p = b1 ? p : p1; - int r = p.v; - p.v = 0; - return r; - } -} From 3a55788874d475c8136897a44f55fbe10abdb2e4 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 13 May 2026 16:38:01 +0200 Subject: [PATCH 2/2] SapMachine #2236: Bump Bootstrap JDKs to current versions (May 2026) Bump boot JDK to SapMachine 26.0.1 for Linux x64, Alpine Linux x64, macOS aarch64, and Windows x64. For macOS x64 (no SapMachine build available), switch from OpenJDK to Temurin 26.0.1+8. --- make/conf/github-actions.conf | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index 26243a1e4e80..49696bc63e93 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -29,21 +29,21 @@ GTEST_VERSION=1.14.0 JTREG_VERSION=8.2.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz -LINUX_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26/sapmachine-jdk-26_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_SHA256=f5e7279cb0e456b471823fb258d5ae27af2077e27d03d202b3efefc3d85a8796 +LINUX_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26.0.1/sapmachine-jdk-26.0.1_linux-x64_bin.tar.gz +LINUX_X64_BOOT_JDK_SHA256=4422a642da9764419477a80bea1d614391c40b71060f0de1610467d4c70807a0 ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz -ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26/sapmachine-jdk-26_linux-x64-musl_bin.tar.gz -ALPINE_LINUX_X64_BOOT_JDK_SHA256=fed54c7ecfa6b66900a28dbb358e942b4699a3234beb826b890885c3501b0ff4 +ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26.0.1/sapmachine-jdk-26.0.1_linux-x64-musl_bin.tar.gz +ALPINE_LINUX_X64_BOOT_JDK_SHA256=58dad03eaf3ec5d40bc2f94d8c1bd5f6e47c650d2d6b52fe3572926285f62e04 MACOS_AARCH64_BOOT_JDK_EXT=tar.gz -MACOS_AARCH64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26/sapmachine-jdk-26_macos-aarch64_bin.tar.gz -MACOS_AARCH64_BOOT_JDK_SHA256=86be6e6cf1b13f0798dc3fe3667b0264ea697aae67c62de5577dcedd1e08897e +MACOS_AARCH64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26.0.1/sapmachine-jdk-26.0.1_macos-aarch64_bin.tar.gz +MACOS_AARCH64_BOOT_JDK_SHA256=3663faab53b08e20c87112166bae3399340ead434d8e3a58cbb2a28ef1e0c584 MACOS_X64_BOOT_JDK_EXT=tar.gz -MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_SHA256=8642b89d889c14ede2c446fd5bbe3621c8a3082e3df02013fd1658e39f52929a +MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin26-binaries/releases/download/jdk-26.0.1%2B8/OpenJDK26U-jdk_x64_mac_hotspot_26.0.1_8.tar.gz +MACOS_X64_BOOT_JDK_SHA256=032df492c8749864ee8b135e3d0ea5a17ef5c847309d5fdf8f1dd55e246b8319 WINDOWS_X64_BOOT_JDK_EXT=zip -WINDOWS_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26/sapmachine-jdk-26_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_SHA256=3387870d83372f5309f503c00e97d09d9f40f052051c6121a6708408be4793f8 +WINDOWS_X64_BOOT_JDK_URL=https://github.com/SAP/SapMachine/releases/download/sapmachine-26.0.1/sapmachine-jdk-26.0.1_windows-x64_bin.zip +WINDOWS_X64_BOOT_JDK_SHA256=1b7ff2fe4bb201047a7e43b83c318b9e0bf53bd8a9ea8e8ac95df2917ff0cbd8