< prev index next >

src/hotspot/share/ci/ciField.hpp

Print this page
*** 1,7 ***
  /*
!  * 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.
--- 1,7 ---
  /*
!  * 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.

*** 28,10 ***
--- 28,11 ---
  #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

*** 42,24 ***
--- 43,31 ---
    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:

*** 167,19 ***
    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
--- 175,71 ---
    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 >