diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 0873d6d235b..244e6b64694 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1669,7 +1669,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // // Generic interpreted method entry to (asm) interpreter // -address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { +address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized, bool object_init) { // determine code generation flags bool inc_counter = UseCompiler || CountCompiledCalls; @@ -1796,6 +1796,12 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #endif } + // Issue a StoreStore barrier on entry to Object_init if the + // class has strict field fields. Be lazy, always do it. + if (object_init) { + __ membar(MacroAssembler::StoreStore); + } + // start execution #ifdef ASSERT { diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index 8abefe39b2d..6ecdc29cf45 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -1139,7 +1139,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // // Generic interpreted method entry to (asm) interpreter // -address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { +address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized, bool object_init) { // determine code generation flags bool inc_counter = UseCompiler || CountCompiledCalls; @@ -1254,6 +1254,12 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #endif } + // Issue a StoreStore barrier on entry to Object_init if the + // class has strict field fields. Be lazy, always do it. + if (object_init) { + __ membar(MacroAssembler::StoreStore, R1_tmp); + } + // start execution #ifdef ASSERT { Label L; diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index b5f1c76c5da..827ad59babc 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -1706,7 +1706,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Generic interpreted method entry to (asm) interpreter. // -address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { +address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized, bool object_init) { bool inc_counter = UseCompiler || CountCompiledCalls; address entry = __ pc(); // Generate the code to allocate the interpreter stack frame. @@ -1801,6 +1801,13 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // JVMTI support __ notify_method_entry(); + // -------------------------------------------------------------------------- + // Issue a StoreStore barrier on entry to Object_init if the + // class has strict field fields. Be lazy, always do it. + if (object_init) { + __ membar(Assembler::StoreStore); + } + // -------------------------------------------------------------------------- // Start executing instructions. __ dispatch_next(vtos); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 21164107053..2416d830545 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1545,6 +1545,12 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #endif } + // Issue a StoreStore barrier on entry to Object_init if the + // class has strict field fields. Be lazy, always do it. + if (object_init) { + __ membar(MacroAssembler::StoreStore); + } + // start execution #ifdef ASSERT __ verify_frame_setup(); diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index 3f568572966..2e031932261 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -1797,6 +1797,12 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #endif // ASSERT } + // If object_init == true, we should insert a StoreStore barrier here to + // prevent strict fields initial default values from being observable. + // However, s390 is a TSO platform, so if `this` escapes, strict fields + // initialized values are guaranteed to be the ones observed, so the + // barrier can be elided. + // start execution #ifdef ASSERT diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index 5d36b7b9a26..35ae1a2c75f 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -1239,7 +1239,7 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) { // // Generic interpreted method entry to (asm) interpreter // -address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { +address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized, bool object_init) { // determine code generation flags bool inc_counter = UseCompiler || CountCompiledCalls; @@ -1360,6 +1360,12 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #endif } + // If object_init == true, we should insert a StoreStore barrier here to + // prevent strict fields initial default values from being observable. + // However, x86 is a TSO platform, so if `this` escapes, strict fields + // initialized values are guaranteed to be the ones observed, so the + // barrier can be elided. + // start execution #ifdef ASSERT { diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp index 0d6ccf3a710..d582db400d9 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp @@ -154,7 +154,13 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan if (m->code_size() == 1) { // We need to execute the special return bytecode to check for // finalizer registration so create a normal frame. + // No need to use the method kind with a memory barrier on entry + // because the method is empty and already has a memory barrier on return return zerolocals; + } else if (EnableValhalla) { + // For non-empty Object constructors, we need a memory barrier + // when entering the method to ensure correctness of strict fields + return object_init; } break; default: break; @@ -303,6 +309,7 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) { case getter : tty->print("getter" ); break; case setter : tty->print("setter" ); break; case abstract : tty->print("abstract" ); break; + case object_init : tty->print("object_init" ); break; case java_lang_math_sin : tty->print("java_lang_math_sin" ); break; case java_lang_math_cos : tty->print("java_lang_math_cos" ); break; case java_lang_math_tan : tty->print("java_lang_math_tan" ); break; diff --git a/src/hotspot/share/interpreter/abstractInterpreter.hpp b/src/hotspot/share/interpreter/abstractInterpreter.hpp index 6f7523fd00a..2e7cab6dd0d 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.hpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.hpp @@ -65,6 +65,7 @@ class AbstractInterpreter: AllStatic { getter, // getter method setter, // setter method abstract, // abstract method (throws an AbstractMethodException) + object_init, // special barrier on entry method_handle_invoke_FIRST, // java.lang.invoke.MethodHandles::invokeExact, etc. method_handle_invoke_LAST = (method_handle_invoke_FIRST + (static_cast(vmIntrinsics::LAST_MH_SIG_POLY) diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp index 9a316f3ba46..00528c3340d 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp @@ -190,6 +190,7 @@ void TemplateInterpreterGenerator::generate_all() { method_entry(getter) method_entry(setter) method_entry(abstract) + method_entry(object_init) method_entry(java_lang_math_sin ) method_entry(java_lang_math_cos ) method_entry(java_lang_math_tan ) @@ -417,6 +418,7 @@ address TemplateInterpreterGenerator::generate_method_entry( case Interpreter::empty : break; case Interpreter::getter : break; case Interpreter::setter : break; + case Interpreter::object_init : break; case Interpreter::abstract : entry_point = generate_abstract_entry(); break; default: entry_point = generate_intrinsic_entry(kind); // process the rest @@ -429,14 +431,17 @@ address TemplateInterpreterGenerator::generate_method_entry( // We expect the normal and native entry points to be generated first so we can reuse them. if (native) { + assert(kind != Interpreter::object_init, "Not supported"); entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::native_synchronized : Interpreter::native); if (entry_point == nullptr) { entry_point = generate_native_entry(synchronized); } } else { - entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals); + entry_point = kind == Interpreter::object_init ? + Interpreter::entry_for_kind(Interpreter::object_init) : + Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals); if (entry_point == nullptr) { - entry_point = generate_normal_entry(synchronized); + entry_point = generate_normal_entry(synchronized, kind == Interpreter::object_init); } } diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp index 07a7ca6169d..74da0824fb8 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, 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 @@ -90,7 +90,7 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator { // generate intrinsic method entries address generate_intrinsic_entry(AbstractInterpreter::MethodKind kind); - address generate_normal_entry(bool synchronized); + address generate_normal_entry(bool synchronized, bool object_init); address generate_native_entry(bool synchronized); address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind);