< prev index next > src/hotspot/share/ci/ciField.hpp
Print this page
/*
! * Copyright (c) 1999, 2023, 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.
/*
! * Copyright (c) 1999, 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.
#include "ci/ciClassList.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciFlags.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciUtilities.hpp"
+ #include "oops/layoutKind.hpp"
// ciField
//
// This class represents the result of a field lookup in the VM.
// The lookup may not succeed, in which case the information in
friend class ciInstanceKlass;
private:
ciFlags _flags;
ciInstanceKlass* _holder;
+ ciInstanceKlass* _original_holder; // For fields nested in flat fields
ciSymbol* _name;
ciSymbol* _signature;
ciType* _type;
int _offset;
+ LayoutKind _layout_kind;
bool _is_constant;
+ bool _is_flat;
+ bool _is_null_free;
+ int _null_marker_offset;
ciMethod* _known_to_link_with_put;
ciInstanceKlass* _known_to_link_with_get;
ciConstant _constant_value;
ciType* compute_type();
ciType* compute_type_impl();
ciField(ciInstanceKlass* klass, int index, Bytecodes::Code bc);
ciField(fieldDescriptor* fd);
+ ciField(ciField* declared_field, ciField* sudfield);
+ ciField(ciField* declared_field);
// shared constructor code
void initialize_from(fieldDescriptor* fd);
public:
bool is_static () const { return flags().is_static(); }
bool is_final () const { return flags().is_final(); }
bool is_stable () const { return flags().is_stable(); }
bool is_volatile () const { return flags().is_volatile(); }
bool is_transient () const { return flags().is_transient(); }
// The field is modified outside of instance initializer methods
// (or class/initializer methods if the field is static).
bool has_initialized_final_update() const { return flags().has_initialized_final_update(); }
bool is_call_site_target();
bool is_autobox_cache();
// Debugging output
! void print();
void print_name_on(outputStream* st);
};
#endif // SHARE_CI_CIFIELD_HPP
bool is_static () const { return flags().is_static(); }
bool is_final () const { return flags().is_final(); }
bool is_stable () const { return flags().is_stable(); }
bool is_volatile () const { return flags().is_volatile(); }
bool is_transient () const { return flags().is_transient(); }
+ bool is_strict () const { return flags().is_strict(); }
+ bool is_flat () const { return _is_flat; }
+ bool is_null_free () const { return _is_null_free; }
+ int null_marker_offset () const { return _null_marker_offset; }
+
+ // Whether this field needs to act atomically. Note that it does not actually need accessing
+ // atomically. For example, if there cannot be racy accesses to this field, then it can be
+ // accessed in a non-atomic manner. Unless this field must be in observably immutable memory,
+ // this method must not depend on the fact that the field cannot be accessed racily (e.g. it is a
+ // strict final field), as if the holder object is flattened as a field that is not strict final,
+ // this property is lost.
+ //
+ // A slice of memory is observably immutable if all stores to it must happen before all loads
+ // from it. A typical example is when the memory is a strict field and its immediate holder is
+ // not a field inside another object.
+ //
+ // For example:
+ // value class A {
+ // int x;
+ // int y;
+ // }
+ // value class AHolder {
+ // A v;
+ // }
+ // class AHolderHolder {
+ // AHolder v;
+ // }
+ // The field AHolder.v is flattened in AHolder, but AHolder cannot be flattened in AHolderHolder
+ // because we cannot access AHolderHolder.v atomically. As a result, we can say that the field is
+ // non-atomic. In this case, AHolder.v has its layout being NULLABLE_NON_ATOMIC_FLAT, this
+ // prevents its holder from being flattened in observably mutable memory.
+ //
+ // Another example:
+ // value class B {
+ // int v;
+ // }
+ // looselyconsistent value class BHolder {
+ // B v;
+ // byte b;
+ // }
+ // class BHolderHolder {
+ // null-free BHolder v;
+ // }
+ // The field BHolder.v is flattened in BHolder, and BHolder can be flattened further in
+ // BHolderHolder. In this case, while BHolder.v can be accessed in a non-atomic manner if BHolder
+ // is a standalone object, it must still be accessed atomically when it is a subfield in
+ // BHolderHolder.v. As a result, the field BHolder.v must still return true for this method, so
+ // that the compiler knows to access it correctly in all circumstances. Implementation-wise,
+ // BHolder.v has its layout being NULLABLE_ATOMIC_FLAT, which still allows its holder to be
+ // flattened in observably mutable memory.
+ bool is_atomic();
+
// The field is modified outside of instance initializer methods
// (or class/initializer methods if the field is static).
bool has_initialized_final_update() const { return flags().has_initialized_final_update(); }
bool is_call_site_target();
bool is_autobox_cache();
// Debugging output
! void print() const;
void print_name_on(outputStream* st);
};
#endif // SHARE_CI_CIFIELD_HPP
< prev index next >