< prev index next > src/hotspot/share/ci/ciField.cpp
Print this page
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
+ #include "ci/ciConstant.hpp"
#include "ci/ciField.hpp"
+ #include "ci/ciInlineKlass.hpp"
#include "ci/ciInstanceKlass.hpp"
+ #include "ci/ciSymbol.hpp"
#include "ci/ciSymbols.hpp"
#include "ci/ciUtilities.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/vmClasses.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
+ #include "jvm_io.h"
#include "oops/klass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/reflection.hpp"
+ #include "utilities/globalDefinitions.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
// decreases for complex compilation tasks.
// ------------------------------------------------------------------
// ciField::ciField
ciField::ciField(ciInstanceKlass* klass, int index, Bytecodes::Code bc) :
- _known_to_link_with_put(nullptr), _known_to_link_with_get(nullptr) {
+ _original_holder(nullptr), _is_flat(false), _known_to_link_with_put(nullptr), _known_to_link_with_get(nullptr) {
ASSERT_IN_VM;
CompilerThread *THREAD = CompilerThread::current();
assert(ciObjectFactory::is_initialized(), "not a shared field");
_type = ciEnv::current(THREAD)->get_klass_by_index(cpool, sig_index, ignore, klass);
} else {
_type = ciType::make(field_type);
}
+ _is_null_free = false;
+ _null_marker_offset = -1;
+
// Get the field's declared holder.
//
// Note: we actually create a ciInstanceKlass for this klass,
// even though we may not need to.
int holder_index = cpool->klass_ref_index_at(index, bc);
// Either (a) it is marked shared, or else (b) we are done bootstrapping.
assert(is_shared() || ciObjectFactory::is_initialized(),
"bootstrap classes must not create & cache unshared fields");
}
+ // Special copy constructor used to flatten inline type fields by
+ // copying the fields of the inline type to a new holder klass.
+ ciField::ciField(ciField* declared_field, ciField* subfield) {
+ assert(subfield->holder()->is_inlinetype() || subfield->holder()->is_abstract(), "should only be used for inline type field flattening");
+ assert(!subfield->is_flat(), "subfield must not be flat");
+ assert(declared_field->is_flat(), "declared field must be flat");
+
+ _flags = declared_field->flags();
+ _holder = declared_field->holder();
+ _offset = declared_field->offset_in_bytes() + (subfield->offset_in_bytes() - declared_field->type()->as_inline_klass()->payload_offset());
+
+ char buffer[256];
+ jio_snprintf(buffer, sizeof(buffer), "%s.%s", declared_field->name()->as_utf8(), subfield->name()->as_utf8());
+ _name = ciSymbol::make(buffer);
+
+ _signature = subfield->_signature;
+ _type = subfield->_type;
+ _is_constant = false;
+ _known_to_link_with_put = subfield->_known_to_link_with_put;
+ _known_to_link_with_get = subfield->_known_to_link_with_get;
+ _constant_value = ciConstant();
+
+ _is_flat = false;
+ _is_null_free = false;
+ _null_marker_offset = -1;
+ _original_holder = (subfield->_original_holder != nullptr) ? subfield->_original_holder : subfield->_holder;
+ }
+
+ // Constructor for the ciField of a null marker
+ ciField::ciField(ciField* declared_field) {
+ assert(declared_field->is_flat(), "declared field must be flat");
+ assert(!declared_field->is_null_free(), "must have a null marker");
+
+ _flags = declared_field->flags();
+ _holder = declared_field->holder();
+ _offset = declared_field->null_marker_offset();
+
+ char buffer[256];
+ jio_snprintf(buffer, sizeof(buffer), "%s.$nullMarker$", declared_field->name()->as_utf8());
+ _name = ciSymbol::make(buffer);
+
+ _signature = ciSymbols::bool_signature();
+ _type = ciType::make(T_BOOLEAN);
+
+ _is_constant = false;
+ _known_to_link_with_put = nullptr;
+ _known_to_link_with_get = nullptr;
+ _constant_value = ciConstant();
+
+ _is_flat = false;
+ _is_null_free = false;
+ _null_marker_offset = -1;
+ _original_holder = nullptr;
+ }
+
static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
if (holder == nullptr)
return false;
if (holder->name() == ciSymbols::java_lang_System())
// Never trust strangely unstable finals: System.out, etc.
return true;
// Trust hidden classes. They are created via Lookup.defineHiddenClass and
// can't be serialized, so there is no hacking of finals going on with them.
if (holder->is_hidden())
return true;
+ // Trust final fields in inline type buffers
+ if (holder->is_inlinetype())
+ return true;
// Trust final fields in all boxed classes
if (holder->is_box_klass())
return true;
// Trust final fields in records
if (holder->is_record())
void ciField::initialize_from(fieldDescriptor* fd) {
// Get the flags, offset, and canonical holder of the field.
_flags = ciFlags(fd->access_flags(), fd->field_flags().is_stable(), fd->field_status().is_initialized_final_update());
_offset = fd->offset();
- Klass* field_holder = fd->field_holder();
+ InstanceKlass* field_holder = fd->field_holder();
assert(field_holder != nullptr, "null field_holder");
_holder = CURRENT_ENV->get_instance_klass(field_holder);
+ _is_flat = fd->is_flat();
+ _is_null_free = fd->is_null_free_inline_type();
+ if (fd->has_null_marker()) {
+ InlineLayoutInfo* li = field_holder->inline_layout_info_adr(fd->index());
+ _null_marker_offset = li->null_marker_offset();
+ } else {
+ _null_marker_offset = -1;
+ }
+ _original_holder = nullptr;
// Check to see if the field is constant.
Klass* k = _holder->get_Klass();
bool is_stable_field = FoldStableValues && is_stable();
if ((is_final() && !has_initialized_final_update()) || is_stable_field) {
ciType* ciField::compute_type() {
GUARDED_VM_ENTRY(return compute_type_impl();)
}
ciType* ciField::compute_type_impl() {
- ciKlass* type = CURRENT_ENV->get_klass_by_name_impl(_holder, constantPoolHandle(), _signature, false);
+ // Use original holder for fields that came in through flattening
+ ciKlass* accessing_klass = (_original_holder != nullptr) ? _original_holder : _holder;
+ ciKlass* type = CURRENT_ENV->get_klass_by_name_impl(accessing_klass, constantPoolHandle(), _signature, false);
if (!type->is_primitive_type() && is_shared()) {
// We must not cache a pointer to an unshared type, in a shared field.
bool type_is_also_shared = false;
if (type->is_type_array_klass()) {
type_is_also_shared = true; // int[] etc. are explicitly bootstrapped
tty->print(" is_constant=%s", bool_to_str(_is_constant));
if (_is_constant && is_static()) {
tty->print(" constant_value=");
_constant_value.print();
}
+ tty->print(" is_flat=%s", bool_to_str(_is_flat));
+ tty->print(" is_null_free=%s", bool_to_str(_is_null_free));
+ tty->print(" null_marker_offset=%d", _null_marker_offset);
tty->print(">");
}
// ------------------------------------------------------------------
// ciField::print_name_on
< prev index next >