Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
TobiHartmann committed Dec 12, 2024
1 parent a23916a commit 9110592
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 78 deletions.
3 changes: 2 additions & 1 deletion src/hotspot/share/c1/c1_LIRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2212,7 +2212,8 @@ void LIRGenerator::do_LoadField(LoadField* x) {
ciInlineKlass* vk = field->type()->as_inline_klass();
BasicType bt = size_to_basic_type(vk->nullable_size_in_bytes());

// Allocate buffer
// Allocate buffer (we can't easily do this conditionally on the null check below
// because branches added in the LIR are opaque to the register allocator).
NewInstance* buffer = new NewInstance(vk, x->state_before(), false, true);
do_NewInstance(buffer);
LIRItem dest(buffer, this);
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/ci/ciReplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,7 @@ class CompileReplay : public StackObj {
Klass* kelem = ObjArrayKlass::cast(actual_array_klass)->element_klass();
value = oopFactory::new_objArray(kelem, length, CHECK_(true));
} else if (field_signature[0] == JVM_SIGNATURE_ARRAY) {
// TODO this is dead, right?
Klass* kelem = resolve_klass(field_signature + 1, CHECK_(true));
parse_klass(CHECK_(true)); // eat up the array class name
value = oopFactory::new_valueArray(kelem, length, CHECK_(true));
Expand Down
146 changes: 70 additions & 76 deletions src/hotspot/share/opto/inlinetypenode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,22 @@ Node* InlineTypeNode::field_value(uint index) const {
return in(Values + index);
}

// TODO implement with a worklist
static Node* helper2(const InlineTypeNode* vt, int search_offset, int holder_offset = 0) {
for (uint i = 0; i < vt->field_count(); ++i) {
if (vt->field_is_flat(i)) {
InlineTypeNode* value = vt->field_value(i)->as_InlineType();
if (!vt->field_is_null_free(i)) {
int offset = holder_offset + vt->field_null_marker_offset(i);
if (offset == search_offset) {
// Get the value of the null marker at the given offset.
Node* InlineTypeNode::null_marker_by_offset(int offset, int holder_offset) const {
// Search through the null markers of all flat fields
for (uint i = 0; i < field_count(); ++i) {
if (field_is_flat(i)) {
InlineTypeNode* value = field_value(i)->as_InlineType();
if (!field_is_null_free(i)) {
int nm_offset = holder_offset + field_null_marker_offset(i);
if (nm_offset == offset) {
return value->get_is_init();
}
}
Node* ret = helper2(value->as_InlineType(), search_offset, holder_offset + vt->field_offset(i) - value->bottom_type()->inline_klass()->first_field_offset());
if (ret != nullptr) {
return ret;
int flat_holder_offset = holder_offset + field_offset(i) - value->inline_klass()->first_field_offset();
Node* nm_value = value->null_marker_by_offset(offset, flat_holder_offset);
if (nm_value != nullptr) {
return nm_value;
}
}
}
Expand All @@ -214,15 +216,17 @@ static Node* helper2(const InlineTypeNode* vt, int search_offset, int holder_off

// Get the value of the field at the given offset.
// If 'recursive' is true, flat inline type fields will be resolved recursively.
Node* InlineTypeNode::field_value_by_offset(int offset, bool recursive, bool root) const {
// If the field at 'offset' belongs to a flat inline type field, 'index' refers to the
// corresponding InlineTypeNode input and 'sub_offset' is the offset in the flattened inline type.
if (root && recursive) {
// Check if we are loading a null marker
Node* val = helper2(this, offset);
if (val != nullptr) return val;
Node* InlineTypeNode::field_value_by_offset(int offset, bool recursive, bool search_null_marker) const {
// First check if we are loading a null marker which is not a real field
if (recursive && search_null_marker) {
Node* value = null_marker_by_offset(offset);
if (value != nullptr){
return value;
}
}

// If the field at 'offset' belongs to a flat inline type field, 'index' refers to the
// corresponding InlineTypeNode input and 'sub_offset' is the offset in the flattened inline type.
int index = inline_klass()->field_index_by_offset(offset);
int sub_offset = offset - field_offset(index);
Node* value = field_value(index);
Expand Down Expand Up @@ -290,30 +294,29 @@ int InlineTypeNode::field_null_marker_offset(uint index) const {
return field->null_marker_offset();
}


// TODO implement with a worklist
static uint helper(InlineTypeNode* vt, Unique_Node_List& worklist, Node_List& null_markers, SafePointNode* sfpt) {
uint InlineTypeNode::add_fields_to_safepoint(Unique_Node_List& worklist, Node_List& null_markers, SafePointNode* sfpt) {
uint cnt = 0;
for (uint i = 0; i < vt->field_count(); ++i) {
Node* value = vt->field_value(i);
if (vt->field_is_flat(i)) {
cnt += helper(value->as_InlineType(), worklist, null_markers, sfpt);
if (!vt->field_is_null_free(i)) {
null_markers.push(value->as_InlineType()->get_is_init());
}
} else {
if (value->is_InlineType()) {
// Add inline type field to the worklist to process later
worklist.push(value);
for (uint i = 0; i < field_count(); ++i) {
Node* value = field_value(i);
if (field_is_flat(i)) {
InlineTypeNode* vt = value->as_InlineType();
cnt += vt->add_fields_to_safepoint(worklist, null_markers, sfpt);
if (!field_is_null_free(i)) {
null_markers.push(vt->get_is_init());
cnt++;
}
sfpt->add_req(value);
cnt++;
continue;
}
if (value->is_InlineType()) {
// Add inline type to the worklist to process later
worklist.push(value);
}
sfpt->add_req(value);
cnt++;
}
return cnt;
}


void InlineTypeNode::make_scalar_in_safepoint(PhaseIterGVN* igvn, Unique_Node_List& worklist, SafePointNode* sfpt) {
// We should not scalarize larvals in debug info of their constructor calls because their fields could still be
// updated. If we scalarize and update the fields in the constructor, the updates won't be visible in the caller after
Expand Down Expand Up @@ -345,12 +348,10 @@ void InlineTypeNode::make_scalar_in_safepoint(PhaseIterGVN* igvn, Unique_Node_Li
// Iterate over the inline type fields in order of increasing
// offset and add the field values to the safepoint.
Node_List null_markers;
uint nfields = helper(this, worklist, null_markers, sfpt);

uint nfields = add_fields_to_safepoint(worklist, null_markers, sfpt);
// Add null markers after the field values
for (uint i = 0; i < null_markers.size(); ++i) {
Node* is_init = null_markers.at(i);
sfpt->add_req(is_init);
nfields++;
sfpt->add_req(null_markers.at(i));
}
jvms->set_endoff(sfpt->req());
SafePointScalarObjectNode* sobj = new SafePointScalarObjectNode(type()->isa_instptr(),
Expand Down Expand Up @@ -712,28 +713,12 @@ bool InlineTypeNode::is_allocated(PhaseGVN* phase) const {
return !oop_type->maybe_null();
}

// TODO implement with a worklist
static void helper3(Compile* C, CallNode* call, const InlineTypeNode* vt, uint& proj_idx) {
for (uint i = 0; i < vt->field_count(); ++i) {
Node* value = vt->field_value(i);
if (vt->field_is_flat(i)) {
helper3(C, call, value->as_InlineType(), proj_idx);
if (!vt->field_is_null_free(i)) {
ProjNode* pn = call->proj_out_or_null(proj_idx++);
if (pn != nullptr) {
C->gvn_replace_by(pn, value->as_InlineType()->get_is_init());
C->initial_gvn()->hash_delete(pn);
pn->set_req(0, C->top());
}
}
continue;
}
ProjNode* pn = call->proj_out_or_null(proj_idx++);
if (pn != nullptr) {
C->gvn_replace_by(pn, value);
C->initial_gvn()->hash_delete(pn);
pn->set_req(0, C->top());
}
static void replace_proj(Compile* C, CallNode* call, uint& proj_idx, Node* value) {
ProjNode* pn = call->proj_out_or_null(proj_idx++);
if (pn != nullptr) {
C->gvn_replace_by(pn, value);
C->initial_gvn()->hash_delete(pn);
pn->set_req(0, C->top());
}
}

Expand All @@ -743,22 +728,31 @@ static void helper3(Compile* C, CallNode* call, const InlineTypeNode* vt, uint&
// projection, we find the corresponding inline type field.
void InlineTypeNode::replace_call_results(GraphKit* kit, CallNode* call, Compile* C) {
uint proj_idx = TypeFunc::Parms;
ProjNode* pn = call->proj_out_or_null(proj_idx++);
if (pn != nullptr) {
C->gvn_replace_by(pn, get_oop());
C->initial_gvn()->hash_delete(pn);
pn->set_req(0, C->top());
}

helper3(C, call, this, proj_idx);
// Replace oop projection
replace_proj(C, call, proj_idx, get_oop());
// Replace field projections
replace_field_projs(C, call, proj_idx);
// Replace is_init projection
replace_proj(C, call, proj_idx, get_is_init());
assert(proj_idx == call->tf()->range_cc()->cnt(), "missed a projection");
}

pn = call->proj_out_or_null(proj_idx++);
if (pn != nullptr) {
C->gvn_replace_by(pn, get_is_init());
C->initial_gvn()->hash_delete(pn);
pn->set_req(0, C->top());
void InlineTypeNode::replace_field_projs(Compile* C, CallNode* call, uint& proj_idx) {
for (uint i = 0; i < field_count(); ++i) {
Node* value = field_value(i);
if (field_is_flat(i)) {
InlineTypeNode* vt = value->as_InlineType();
// Replace field projections for flat field
vt->replace_field_projs(C, call, proj_idx);
if (!field_is_null_free(i)) {
// Replace is_init projection for nullable field
replace_proj(C, call, proj_idx, vt->get_is_init());
}
continue;
}
// Replace projection for field value
replace_proj(C, call, proj_idx, value);
}
assert(proj_idx == call->tf()->range_cc()->cnt(), "missed a projection");
}

Node* InlineTypeNode::allocate_fields(GraphKit* kit) {
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/share/opto/inlinetypenode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class InlineTypeNode : public TypeNode {
ciInlineKlass* inline_klass() const { return type()->inline_klass(); }

void make_scalar_in_safepoint(PhaseIterGVN* igvn, Unique_Node_List& worklist, SafePointNode* sfpt);
uint add_fields_to_safepoint(Unique_Node_List& worklist, Node_List& null_markers, SafePointNode* sfpt);

const TypePtr* field_adr_type(Node* base, int offset, ciInstanceKlass* holder, DecoratorSet decorators, PhaseGVN& gvn) const;

Expand Down Expand Up @@ -122,7 +123,8 @@ class InlineTypeNode : public TypeNode {
// Inline type fields
uint field_count() const { return req() - Values; }
Node* field_value(uint index) const;
Node* field_value_by_offset(int offset, bool recursive = false, bool root = true) const;
Node* field_value_by_offset(int offset, bool recursive = false, bool search_null_marker = true) const;
Node* null_marker_by_offset(int offset, int holder_offset = 0) const;
void set_field_value(uint index, Node* value);
void set_field_value_by_offset(int offset, Node* value);
int field_offset(uint index) const;
Expand All @@ -149,6 +151,7 @@ class InlineTypeNode : public TypeNode {
bool is_allocated(PhaseGVN* phase) const;

void replace_call_results(GraphKit* kit, CallNode* call, Compile* C);
void replace_field_projs(Compile* C, CallNode* call, uint& proj_idx);

// Allocate all non-flat inline type fields
Node* allocate_fields(GraphKit* kit);
Expand Down

0 comments on commit 9110592

Please sign in to comment.