diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index ca7174389cf..e3cf5d589c2 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -711,9 +711,7 @@ void InterpreterRuntime::resolve_get_put(Bytecodes::Code bytecode, int field_ind } ResolvedFieldEntry* entry = pool->resolved_field_entry_at(field_index); - entry->set_flags(info.access_flags().is_final(), info.access_flags().is_volatile()); - entry->fill_in(info.field_holder(), info.offset(), - checked_cast(info.index()), checked_cast(state), + entry->fill_in(info, checked_cast(state), static_cast(get_code), static_cast(put_code)); } @@ -1189,10 +1187,9 @@ JRT_LEAF(void, InterpreterRuntime::at_unwind(JavaThread* current)) JRT_END JRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread* current, oopDesc* obj, - ResolvedFieldEntry *entry)) + ResolvedFieldEntry* entry)) // check the access_flags for the field in the klass - InstanceKlass* ik = entry->field_holder(); int index = entry->field_index(); if (!ik->field_status(index).is_access_watched()) return; @@ -1212,11 +1209,10 @@ JRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread* current, oopDe JRT_END JRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread* current, oopDesc* obj, - ResolvedFieldEntry *entry, jvalue *value)) - - InstanceKlass* ik = entry->field_holder(); + ResolvedFieldEntry* entry, jvalue* value)) // check the access_flags for the field in the klass + InstanceKlass* ik = entry->field_holder(); int index = entry->field_index(); // bail out if field modifications are not watched if (!ik->field_status(index).is_modification_watched()) return; diff --git a/src/hotspot/share/oops/resolvedFieldEntry.cpp b/src/hotspot/share/oops/resolvedFieldEntry.cpp index 83f1a6919a6..49e9115ca9a 100644 --- a/src/hotspot/share/oops/resolvedFieldEntry.cpp +++ b/src/hotspot/share/oops/resolvedFieldEntry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -24,7 +24,12 @@ #include "cds/archiveBuilder.hpp" #include "cppstdlib/type_traits.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/instanceOop.hpp" #include "oops/resolvedFieldEntry.hpp" +#include "runtime/fieldDescriptor.inline.hpp" +#include "utilities/checkedCast.hpp" +#include "utilities/globalDefinitions.hpp" static_assert(std::is_trivially_copyable_v); @@ -34,6 +39,19 @@ class ResolvedFieldEntryWithExtra : public ResolvedFieldEntry { }; static_assert(sizeof(ResolvedFieldEntryWithExtra) > sizeof(ResolvedFieldEntry)); +void ResolvedFieldEntry::fill_in(const fieldDescriptor& info, u1 tos_state, u1 get_code, u1 put_code) { + set_flags(info.access_flags().is_final(), info.access_flags().is_volatile()); + _field_holder = info.field_holder(); + _field_offset = info.offset(); + _field_index = checked_cast(info.index()); + _tos_state = tos_state; + + // These must be set after the other fields + set_bytecode(&_get_code, get_code); + set_bytecode(&_put_code, put_code); + assert_is_valid(); +} + void ResolvedFieldEntry::print_on(outputStream* st) const { st->print_cr("Field Entry:"); @@ -52,6 +70,20 @@ void ResolvedFieldEntry::print_on(outputStream* st) const { st->print_cr(" - Put Bytecode: %s", Bytecodes::name((Bytecodes::Code)put_code())); } +#ifdef ASSERT +void ResolvedFieldEntry::assert_is_valid() const { + assert(field_holder()->is_instance_klass(), "should be instanceKlass"); + assert(field_offset() >= instanceOopDesc::base_offset_in_bytes(), + "field offset out of range %d >= %d", field_offset(), instanceOopDesc::base_offset_in_bytes()); + assert(as_BasicType((TosState)tos_state()) != T_ILLEGAL, "tos_state is ILLEGAL"); + assert(_flags < (1 << (max_flag_shift + 1)), "flags are too large %d", _flags); + assert((get_code() == 0 || get_code() == Bytecodes::_getstatic || get_code() == Bytecodes::_getfield), + "invalid get bytecode %d", get_code()); + assert((put_code() == 0 || put_code() == Bytecodes::_putstatic || put_code() == Bytecodes::_putfield), + "invalid put bytecode %d", put_code()); +} +#endif + #if INCLUDE_CDS void ResolvedFieldEntry::remove_unshareable_info() { *this = ResolvedFieldEntry(_cpool_index); diff --git a/src/hotspot/share/oops/resolvedFieldEntry.hpp b/src/hotspot/share/oops/resolvedFieldEntry.hpp index 77ad4815730..bdd9999dd63 100644 --- a/src/hotspot/share/oops/resolvedFieldEntry.hpp +++ b/src/hotspot/share/oops/resolvedFieldEntry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -26,7 +26,6 @@ #define SHARE_OOPS_RESOLVEDFIELDENTRY_HPP #include "interpreter/bytecodes.hpp" -#include "oops/instanceKlass.hpp" #include "runtime/atomicAccess.hpp" #include "utilities/checkedCast.hpp" #include "utilities/sizes.hpp" @@ -46,7 +45,8 @@ // The explicit paddings are necessary for generating deterministic CDS archives. They prevent // the C++ compiler from potentially inserting random values in unused gaps. -//class InstanceKlass; +class InstanceKlass; + class ResolvedFieldEntry { friend class VMStructs; @@ -84,6 +84,7 @@ public: enum { is_volatile_shift = 0, is_final_shift = 1, // unused + max_flag_shift = is_final_shift }; // Getters @@ -113,6 +114,7 @@ public: // Printing void print_on(outputStream* st) const; + private: void set_flags(bool is_final_flag, bool is_volatile_flag) { int new_flags = (is_final_flag << is_final_shift) | static_cast(is_volatile_flag); _flags = checked_cast(new_flags); @@ -129,17 +131,12 @@ public: AtomicAccess::release_store(code, new_code); } - // Populate the strucutre with resolution information - void fill_in(InstanceKlass* klass, int offset, u2 index, u1 tos_state, u1 b1, u1 b2) { - _field_holder = klass; - _field_offset = offset; - _field_index = index; - _tos_state = tos_state; + // Debug help + void assert_is_valid() const NOT_DEBUG_RETURN; - // These must be set after the other fields - set_bytecode(&_get_code, b1); - set_bytecode(&_put_code, b2); - } + public: + // Populate the strucutre with resolution information + void fill_in(const fieldDescriptor& info, u1 tos_state, u1 get_code, u1 put_code); // CDS #if INCLUDE_CDS @@ -155,7 +152,6 @@ public: static ByteSize put_code_offset() { return byte_offset_of(ResolvedFieldEntry, _put_code); } static ByteSize type_offset() { return byte_offset_of(ResolvedFieldEntry, _tos_state); } static ByteSize flags_offset() { return byte_offset_of(ResolvedFieldEntry, _flags); } - }; #endif //SHARE_OOPS_RESOLVEDFIELDENTRY_HPP