8378793: Add ResolvedFieldEntry is_valid assert

Reviewed-by: dholmes, dsimms, matsaave
This commit is contained in:
Coleen Phillimore 2026-03-02 13:39:44 +00:00
parent b7d0cb5fb3
commit 29a40c3c68
3 changed files with 47 additions and 23 deletions

View File

@ -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<u2>(info.index()), checked_cast<u1>(state),
entry->fill_in(info, checked_cast<u1>(state),
static_cast<u1>(get_code), static_cast<u1>(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;

View File

@ -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<ResolvedFieldEntry>);
@ -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<u2>(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);

View File

@ -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<int>(is_volatile_flag);
_flags = checked_cast<u1>(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