diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 50ed4750d47fd..e6f4745fcd5dd 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -837,6 +837,42 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, // C2 uses the value of ZF to determine the continuation. } +#ifdef ASSERT +void C2_MacroAssembler::checked_cast_int(const TypeInt* type, Register dst) { + Label fail; + Label succeed; + cmpl(dst, type->_lo); + jccb(Assembler::less, fail); + cmpl(dst, type->_hi); + jccb(Assembler::lessEqual, succeed); + bind(fail); + stop("Invalid CastII"); + bind(succeed); +} + +void C2_MacroAssembler::checked_cast_long(const TypeLong* type, Register dst, Register tmp) { + Label fail; + Label succeed; + if (is_simm32(type->_lo)) { + cmpq(dst, checked_cast(type->_lo)); + } else { + mov64(tmp, type->_lo); + cmpq(dst, tmp); + } + jccb(Assembler::less, fail); + if (is_simm32(type->_hi)) { + cmpq(dst, checked_cast(type->_hi)); + } else { + mov64(tmp, type->_hi); + cmpq(dst, tmp); + } + jccb(Assembler::lessEqual, succeed); + bind(fail); + stop("Invalid CastLL"); + bind(succeed); +} +#endif // ASSERT + //------------------------------------------------------------------------------------------- // Generic instructions support for use in .ad files C2 code generation diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 6e49cdefa6c94..3f37d910b8ece 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -44,6 +44,11 @@ Register t, Register thread); void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread); +#ifdef ASSERT + void checked_cast_int(const TypeInt* type, Register dst); + void checked_cast_long(const TypeLong* type, Register dst, Register tmp); +#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); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 4667922505cbc..d188583925a1f 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 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 @@ -6991,6 +6991,7 @@ instruct castPP(rRegP dst) instruct castII(rRegI dst) %{ + predicate(!VerifyConstraintCasts); match(Set dst (CastII dst)); size(0); @@ -7000,8 +7001,22 @@ instruct castII(rRegI dst) ins_pipe(empty); %} +instruct castII_checked(rRegI dst, rFlagsReg cr) +%{ + predicate(VerifyConstraintCasts); + match(Set dst (CastII dst)); + + effect(KILL cr); + format %{ "# checked_cast_II $dst" %} + ins_encode %{ + DEBUG_ONLY(__ checked_cast_int(bottom_type()->is_int(), $dst$$Register)); + %} + ins_pipe(pipe_slow); +%} + instruct castLL(rRegL dst) %{ + predicate(!VerifyConstraintCasts); match(Set dst (CastLL dst)); size(0); @@ -7011,6 +7026,19 @@ instruct castLL(rRegL dst) ins_pipe(empty); %} +instruct castLL_checked(rRegL dst, rRegL tmp, rFlagsReg cr) +%{ + predicate(VerifyConstraintCasts); + match(Set dst (CastLL dst)); + + effect(KILL cr, TEMP tmp); + format %{ "# checked_cast_LL $dst" %} + ins_encode %{ + DEBUG_ONLY(__ checked_cast_long(bottom_type()->is_long(), $dst$$Register, $tmp$$Register)); + %} + ins_pipe(pipe_slow); +%} + instruct castFF(regF dst) %{ match(Set dst (CastFF dst)); diff --git a/src/hotspot/share/opto/c2_MacroAssembler.hpp b/src/hotspot/share/opto/c2_MacroAssembler.hpp index 41347313a8cf1..1fb7714153dd8 100644 --- a/src/hotspot/share/opto/c2_MacroAssembler.hpp +++ b/src/hotspot/share/opto/c2_MacroAssembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -31,6 +31,8 @@ #include "utilities/macros.hpp" class C2EntryBarrierStub; +class TypeInt; +class TypeLong; class C2_MacroAssembler: public MacroAssembler { public: diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index d4b55ec2d8d12..d806b8b1472de 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -660,6 +660,10 @@ develop(bool, VerifyAliases, false, \ "perform extra checks on the results of alias analysis") \ \ + develop(bool, VerifyConstraintCasts, false, \ + "perform runtime check to verify the value of a " \ + "ConstraintCast lies inside its type") \ + \ product(intx, MaxInlineLevel, 15, \ "maximum number of nested calls that are inlined by high tier " \ "compiler") \ diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index 63ed54df4fd9d..694485aec9c44 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -506,6 +506,12 @@ const Type* ConstraintCastNode::widen_type(const PhaseGVN* phase, const Type* re if (!phase->C->post_loop_opts_phase()) { return res; } + + // Keep these casts for verification + if (VerifyConstraintCasts) { + return res; + } + const TypeInteger* this_type = res->is_integer(bt); const TypeInteger* in_type = phase->type(in(1))->isa_integer(bt); if (in_type != nullptr &&