Skip to content

Commit

Permalink
8304310: Initial compilers and runtime handling for multifield backed…
Browse files Browse the repository at this point in the history
… vectors.

Reviewed-by: xgong, vlivanov
  • Loading branch information
Jatin Bhateja authored and TobiHartmann committed May 15, 2023
1 parent 05e4d0d commit d9f744f
Show file tree
Hide file tree
Showing 79 changed files with 1,488 additions and 490 deletions.
2 changes: 1 addition & 1 deletion make/Docs.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ JAVA_WARNINGS_ARE_ERRORS ?= -Werror
JAVADOC_OPTIONS := -XDignore.symbol.file=true -use -keywords -notimestamp \
-encoding ISO-8859-1 -docencoding UTF-8 -breakiterator \
-splitIndex --system none -javafx --expand-requires transitive \
-XDenableValueTypes \
-XDenableValueTypes -XDenablePrimitiveClasses \
--override-methods=summary

# The reference options must stay stable to allow for comparisons across the
Expand Down
2 changes: 1 addition & 1 deletion make/common/JavaCompilation.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ define SetupJavaCompilationBody
endif

# Allow overriding on the command line
JAVA_WARNINGS_ARE_ERRORS ?= -Werror
JAVA_WARNINGS_ARE_ERRORS ?=

# Tell javac to do exactly as told and no more
PARANOIA_FLAGS := -implicit:none -Xprefer:source -XDignore.symbol.file=true -encoding ascii
Expand Down
8 changes: 8 additions & 0 deletions src/hotspot/cpu/x86/interp_masm_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,14 @@ void InterpreterMacroAssembler::remove_activation(
Label skip;
test_oop_is_not_inline_type(rax, rscratch1, skip);

// Skip scalarization for vector value objects (concrete vectors and payloads).
load_klass(rdi, rax, rscratch1);
movptr(rscratch1, rax);
super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::skip_value_scalarization), rdi);
testptr(rax, rax);
movptr(rax, rscratch1);
jcc(Assembler::notZero, skip);

#ifndef _LP64
super_call_VM_leaf(StubRoutines::load_inline_type_fields_in_regs());
#else
Expand Down
17 changes: 10 additions & 7 deletions src/hotspot/share/c1/c1_GraphBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1863,13 +1863,16 @@ Value GraphBuilder::make_constant(ciConstant field_value, ciField* field) {
void GraphBuilder::copy_inline_content(ciInlineKlass* vk, Value src, int src_off, Value dest, int dest_off, ValueStack* state_before, ciField* enclosing_field) {
for (int i = 0; i < vk->nof_nonstatic_fields(); i++) {
ciField* inner_field = vk->nonstatic_field_at(i);
assert(!inner_field->is_flattened(), "the iteration over nested fields is handled by the loop itself");
int off = inner_field->offset() - vk->first_field_offset();
LoadField* load = new LoadField(src, src_off + off, inner_field, false, state_before, false);
Value replacement = append(load);
StoreField* store = new StoreField(dest, dest_off + off, inner_field, replacement, false, state_before, false);
store->set_enclosing_field(enclosing_field);
append(store);
for (int j = 0, sec_offset = 0; j < inner_field->secondary_fields_count(); j++) {
assert(!inner_field->is_flattened(), "the iteration over nested fields is handled by the loop itself");
int off = inner_field->offset() + sec_offset - vk->first_field_offset();
LoadField* load = new LoadField(src, src_off + off, inner_field, false, state_before, false);
sec_offset += type2aelembytes(as_BasicType(load->type()));
Value replacement = append(load);
StoreField* store = new StoreField(dest, dest_off + off, inner_field, replacement, false, state_before, false);
store->set_enclosing_field(enclosing_field);
append(store);
}
}
}

Expand Down
16 changes: 13 additions & 3 deletions src/hotspot/share/ci/ciField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ ciField::ciField(ciInstanceKlass* klass, int index) :
return;
}

int bundle_size = field_desc.secondary_fields_count(field_desc.index());
if (bundle_size > 1) {
_type = ciType::make(field_type, bundle_size);
}

// Access check based on declared_holder. canonical_holder should not be used
// to check access because it can erroneously succeed. If this check fails,
// propagate the declared holder to will_link() which in turn will bail out
Expand Down Expand Up @@ -204,16 +209,16 @@ ciField::ciField(fieldDescriptor *fd) :

BasicType field_type = fd->field_type();

initialize_from(fd);

// If the field is a pointer type, get the klass of the
// field.
if (is_reference_type(field_type)) {
_type = NULL; // must call compute_type on first access
} else {
_type = ciType::make(field_type);
_type = ciType::make(field_type, fd->secondary_fields_count(fd->index()));
}

initialize_from(fd);

// 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");
Expand Down Expand Up @@ -242,6 +247,8 @@ ciField::ciField(ciField* field, ciInstanceKlass* holder, int offset, bool is_fi
_is_flattened = false;
_is_null_free = field->_is_null_free;
_original_holder = (field->_original_holder != NULL) ? field->_original_holder : field->_holder;
_is_multifield = field->_is_multifield;
_is_multifield_base = field->_is_multifield_base;
}

static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
Expand Down Expand Up @@ -295,6 +302,9 @@ void ciField::initialize_from(fieldDescriptor* fd) {
_is_null_free = fd->signature()->is_Q_signature();
_original_holder = NULL;

_is_multifield = fd->is_multifield();
_is_multifield_base = fd->is_multifield_base();

// Check to see if the field is constant.
Klass* k = _holder->get_Klass();
bool is_stable_field = FoldStableValues && is_stable();
Expand Down
28 changes: 28 additions & 0 deletions src/hotspot/share/ci/ciField.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "ci/ciFlags.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciUtilities.hpp"
#include "utilities/growableArray.hpp"

// ciField
//
Expand All @@ -40,6 +41,7 @@ class ciField : public ArenaObj {
CI_PACKAGE_ACCESS
friend class ciEnv;
friend class ciInstanceKlass;
friend class ciMultiField;

private:
ciFlags _flags;
Expand All @@ -52,6 +54,8 @@ class ciField : public ArenaObj {
bool _is_constant;
bool _is_flattened;
bool _is_null_free;
bool _is_multifield;
bool _is_multifield_base;
ciMethod* _known_to_link_with_put;
ciInstanceKlass* _known_to_link_with_get;
ciConstant _constant_value;
Expand Down Expand Up @@ -105,6 +109,10 @@ class ciField : public ArenaObj {
// Of what type is this field?
ciType* type() { return (_type == NULL) ? compute_type() : _type; }

bool is_multifield() { return _is_multifield; }
bool is_multifield_base() { return _is_multifield_base; }
int secondary_fields_count() { return type()->bundle_size(); } const

// How is this field actually stored in memory?
BasicType layout_type() { return type2field[type()->basic_type()]; }

Expand Down Expand Up @@ -194,4 +202,24 @@ class ciField : public ArenaObj {
void print_name_on(outputStream* st);
};

class ciMultiField : public ciField {
private:
CI_PACKAGE_ACCESS
friend class ciInstanceKlass;

GrowableArray<ciField*>* _secondary_fields;

ciMultiField(ciInstanceKlass* klass, int index) : ciField(klass, index) {}
ciMultiField(fieldDescriptor* fd) : ciField(fd) {}
ciMultiField(ciField* field, ciInstanceKlass* holder, int offset, bool is_final) :
ciField(field, holder, offset, is_final) {}
public:
void add_secondary_fields(GrowableArray<ciField*>* fields) { _secondary_fields = fields; }
GrowableArray<ciField*>* secondary_fields() { return _secondary_fields; }
ciField* secondary_field_at(int i) {
assert(_secondary_fields->length() > i, "");
return _secondary_fields->at(i);
}
};

#endif // SHARE_CI_CIFIELD_HPP
16 changes: 15 additions & 1 deletion src/hotspot/share/ci/ciInlineKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include "precompiled.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInlineKlass.hpp"
#include "ci/ciUtilities.inline.hpp"
Expand Down Expand Up @@ -54,10 +55,23 @@ int ciInlineKlass::field_index_by_offset(int offset) {
int best_index = -1;
// Search the field with the given offset
for (int i = 0; i < nof_declared_nonstatic_fields(); ++i) {
int field_offset = _declared_nonstatic_fields->at(i)->offset();
ciField* field = _declared_nonstatic_fields->at(i);
int field_offset = field->offset();
if (field_offset == offset) {
// Exact match
return i;
} else if (field->is_multifield_base()) {
for (int j = 0; j < field->secondary_fields_count(); j++) {
ciField* sec_field = static_cast<ciMultiField*>(field)->secondary_field_at(j);
assert(sec_field != NULL, "");
int sec_field_offset = sec_field->offset();
if (sec_field_offset == offset) {
return i + j + 1;
} else if (sec_field_offset < offset && sec_field_offset > best_offset) {
best_offset = sec_field_offset;
best_index = i + j + 1;
}
}
} else if (field_offset < offset && field_offset > best_offset) {
// No exact match. Save the index of the field with the closest offset that
// is smaller than the given field offset. This index corresponds to the
Expand Down
18 changes: 17 additions & 1 deletion src/hotspot/share/ci/ciInlineKlass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "ci/ciConstantPoolCache.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciField.hpp"
#include "ci/ciFlags.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciSymbol.hpp"
Expand Down Expand Up @@ -70,7 +71,22 @@ class ciInlineKlass : public ciInstanceKlass {
// ith non-static declared field (presented by ascending address)
ciField* declared_nonstatic_field_at(int i) {
assert(_declared_nonstatic_fields != NULL, "should be initialized");
return _declared_nonstatic_fields->at(i);
// Look for field in preceding multi-field bundle;
for (int j = 0; j <= i; j++) {
int bundle_size = _declared_nonstatic_fields->at(j)->secondary_fields_count();
if (bundle_size > 1 && ((j + bundle_size) > i)) {
if (j == i) {
// Multifield base.
return _declared_nonstatic_fields->at(i);
} else {
// Secondary multifield.
return static_cast<ciMultiField*>(_declared_nonstatic_fields->at(j))->secondary_fields()->at(i - (j + 1));
}
} else if (j == i) {
return _declared_nonstatic_fields->at(i);
}
}
return NULL;
}

// Inline type fields
Expand Down
41 changes: 36 additions & 5 deletions src/hotspot/share/ci/ciInstanceKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,22 @@ ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static)
if (!is_static) {
for (int i = 0, len = nof_nonstatic_fields(); i < len; i++) {
ciField* field = _nonstatic_fields->at(i);
int field_off = field->offset_in_bytes();
if (field_off == field_offset)
int curr_field_offset = field->offset_in_bytes();
if (curr_field_offset == field_offset)
return field;
if (field_off > field_offset)
if (curr_field_offset > field_offset)
break;
// could do binary search or check bins, but probably not worth it
if (field->secondary_fields_count() > 1) {
for (int j = 0; j < field->secondary_fields_count(); j++) {
ciField* sec_field = static_cast<ciMultiField*>(field)->secondary_fields()->at(j);
int sec_field_offset = sec_field->offset_in_bytes();
if (sec_field_offset == field_offset)
return sec_field;
if (sec_field_offset > field_offset)
return NULL;
}
}
}
return NULL;
}
Expand Down Expand Up @@ -531,6 +541,7 @@ GrowableArray<ciField*>* ciInstanceKlass::compute_nonstatic_fields_impl(Growable
InstanceKlass* k = get_instanceKlass();
for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) continue;
if (fs.is_multifield()) continue;
flen += 1;
}

Expand All @@ -549,6 +560,13 @@ GrowableArray<ciField*>* ciInstanceKlass::compute_nonstatic_fields_impl(Growable

for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) continue;
if (fs.is_multifield()) {
assert(fields->last()->is_multifield_base(), "");
ciMultiField* multifield_base = static_cast<ciMultiField*>(fields->last());
fieldDescriptor& fd = fs.field_descriptor();
multifield_base->secondary_fields()->append(new (arena) ciField(&fd));
continue;
}
fieldDescriptor& fd = fs.field_descriptor();
if (fd.is_inlined() && flatten) {
// Inline type fields are embedded
Expand All @@ -565,11 +583,24 @@ GrowableArray<ciField*>* ciInstanceKlass::compute_nonstatic_fields_impl(Growable
// A flattened field can be treated as final if the non-flattened
// field is declared final or the holder klass is an inline type itself.
bool is_final = fd.is_final() || is_inlinetype();
ciField* field = new (arena) ciField(flattened_field, this, offset, is_final);
ciField* field = NULL;
if (flattened_field->is_multifield_base()) {
field = new (arena) ciMultiField(flattened_field, this, offset, is_final);
static_cast<ciMultiField*>(field)->add_secondary_fields(static_cast<ciMultiField*>(flattened_field)->secondary_fields());
} else {
field = new (arena) ciField(flattened_field, this, offset, is_final);
}
fields->append(field);
}
} else {
ciField* field = new (arena) ciField(&fd);
ciField* field = NULL;
if (fs.is_multifield_base()) {
field = new (arena) ciMultiField(&fd);
GrowableArray<ciField*>* sec_fields = new (arena) GrowableArray<ciField*>(arena, fd.secondary_fields_count(fd.index()), 0, NULL);
static_cast<ciMultiField*>(field)->add_secondary_fields(sec_fields);
} else {
field = new (arena) ciField(&fd);
}
fields->append(field);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/ci/ciInstanceKlass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ciInstanceKlass : public ciKlass {
friend class ciExceptionHandler;
friend class ciMethod;
friend class ciField;
friend class ciMultiField;
friend class ciReplay;

private:
Expand Down
22 changes: 14 additions & 8 deletions src/hotspot/share/ci/ciType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ ciType* ciType::_basic_types[T_CONFLICT+1];
// ------------------------------------------------------------------
// ciType::ciType
//
ciType::ciType(BasicType basic_type) : ciMetadata() {
ciType::ciType(BasicType basic_type, int bundle_size) : ciMetadata() {
assert(basic_type >= T_BOOLEAN && basic_type <= T_CONFLICT, "range check");
_basic_type = basic_type;
_bundle_size = bundle_size;
}

ciType::ciType(Klass* k) : ciMetadata(k) {
_basic_type = k->is_array_klass() ? T_ARRAY : (k->is_inline_klass() ? T_PRIMITIVE_OBJECT : T_OBJECT);
_bundle_size = 1;
}


Expand Down Expand Up @@ -106,13 +108,17 @@ ciInstance* ciType::java_mirror() {
// Produce the ciType for a given primitive BasicType.
// As a bonus, produce the right reference type for T_OBJECT.
// Does not work on T_ARRAY.
ciType* ciType::make(BasicType t) {
// short, etc.
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
assert((uint)t < T_CONFLICT+1, "range check");
if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object
assert(_basic_types[t] != NULL, "domain check");
return _basic_types[t];
ciType* ciType::make(BasicType t, int bundle_size) {
if (bundle_size == 1) {
// short, etc.
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
assert((uint)t < T_CONFLICT+1, "range check");
if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object
assert(_basic_types[t] != NULL, "domain check");
return _basic_types[t];
} else {
return new (CURRENT_ENV->arena()) ciType(t, bundle_size);
}
}

// ciReturnAddress
Expand Down
13 changes: 8 additions & 5 deletions src/hotspot/share/ci/ciType.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ class ciType : public ciMetadata {

private:
BasicType _basic_type;
int _bundle_size;

ciType(BasicType t); // for primitive and unloaded types
ciType(BasicType t, int bundle_size = 1); // for primitive and unloaded types
ciType(Klass* k); // for subclasses (reference types)

const char* type_string() { return "ciType"; }
Expand All @@ -63,10 +64,12 @@ class ciType : public ciMetadata {

// Returns true if this is not a klass or array (i.e., not a reference type).
bool is_primitive_type() const { return !is_reference_type(basic_type()); }
int size() const { return type2size[basic_type()]; }
int size() const { return _bundle_size * type2size[basic_type()]; }
int elem_word_count() const { return type2size[basic_type()]; }
int bundle_size() const { return _bundle_size; }
bool is_void() const { return basic_type() == T_VOID; }
bool is_one_word() const { return size() == 1; }
bool is_two_word() const { return size() == 2; }
bool is_one_word() const { return type2size[basic_type()] == 1; }
bool is_two_word() const { return type2size[basic_type()] == 2; }

// What kind of ciObject is this?
bool is_type() const { return true; }
Expand All @@ -81,7 +84,7 @@ class ciType : public ciMetadata {
print_name_on(tty);
}

static ciType* make(BasicType t);
static ciType* make(BasicType t, int bundle_size = 1);
};


Expand Down
Loading

0 comments on commit d9f744f

Please sign in to comment.