Skip to content
Permalink
Browse files
8252024: [lworld] Lock ordering issue when printing nmethod labels
  • Loading branch information
TobiHartmann committed Dec 14, 2020
1 parent 67f86bd commit 34232ad1f268d9b149250b8ee38bcb2b62e6556b
Showing 13 changed files with 108 additions and 152 deletions.
@@ -129,10 +129,6 @@ int ciInlineKlass::oop_count() const {
GUARDED_VM_ENTRY(return get_InlineKlass()->nonstatic_oop_count();)
}

Array<SigEntry>* ciInlineKlass::extended_sig() const {
GUARDED_VM_ENTRY(return get_InlineKlass()->extended_sig();)
}

address ciInlineKlass::pack_handler() const {
GUARDED_VM_ENTRY(return get_InlineKlass()->pack_handler();)
}
@@ -87,7 +87,6 @@ class ciInlineKlass : public ciInstanceKlass {
ciInstance* default_instance() const;
bool contains_oops() const;
int oop_count() const;
Array<SigEntry>* extended_sig() const;
address pack_handler() const;
address unpack_handler() const;
InlineKlass* get_InlineKlass() const;
@@ -3177,103 +3177,86 @@ void nmethod::print_nmethod_labels(outputStream* stream, address block_begin, bo
}

// Print the arguments for the 3 types of verified entry points
{
const CompiledEntrySignature* ces = _nmethod_to_print_ces;
const GrowableArray<SigEntry>* sig_cc;
const VMRegPair* regs;
if (block_begin == verified_entry_point()) {
sig_cc = &ces->sig_cc();
regs = ces->regs_cc();
} else if (block_begin == verified_inline_entry_point()) {
sig_cc = &ces->sig();
regs = ces->regs();
} else if (block_begin == verified_inline_ro_entry_point()) {
sig_cc = &ces->sig_cc_ro();
regs = ces->regs_cc_ro();
} else {
return;
}
const CompiledEntrySignature* ces = _nmethod_to_print_ces;
const GrowableArray<SigEntry>* sig_cc;
const VMRegPair* regs;
if (block_begin == verified_entry_point()) {
sig_cc = &ces->sig_cc();
regs = ces->regs_cc();
} else if (block_begin == verified_inline_entry_point()) {
sig_cc = &ces->sig();
regs = ces->regs();
} else if (block_begin == verified_inline_ro_entry_point()) {
sig_cc = &ces->sig_cc_ro();
regs = ces->regs_cc_ro();
} else {
return;
}

ResourceMark rm;
int sizeargs = 0;
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, 256);
TempNewSymbol sig = SigEntry::create_symbol(sig_cc);
for (SignatureStream ss(sig); !ss.at_return_type(); ss.next()) {
BasicType t = ss.type();
sig_bt[sizeargs++] = t;
if (type2size[t] == 2) {
sig_bt[sizeargs++] = T_VOID;
} else {
assert(type2size[t] == 1, "size is 1 or 2");
bool has_this = !m->is_static();
if (ces->has_inline_recv() && block_begin == verified_entry_point()) {
// <this> argument is scalarized for verified_entry_point()
has_this = false;
}
const char* spname = "sp"; // make arch-specific?
int stack_slot_offset = this->frame_size() * wordSize;
int tab1 = 14, tab2 = 24;
int sig_index = 0;
int arg_index = has_this ? -1 : 0;
bool did_old_sp = false;
for (ExtendedSignature sig = ExtendedSignature(sig_cc, SigEntryFilter()); !sig.at_end(); ++sig) {
bool at_this = (arg_index == -1);
bool at_old_sp = false;
BasicType t = (*sig)._bt;
if (at_this) {
stream->print(" # this: ");
} else {
stream->print(" # parm%d: ", arg_index);
}
stream->move_to(tab1);
VMReg fst = regs[sig_index].first();
VMReg snd = regs[sig_index].second();
if (fst->is_reg()) {
stream->print("%s", fst->name());
if (snd->is_valid()) {
stream->print(":%s", snd->name());
}
} else if (fst->is_stack()) {
int offset = fst->reg2stack() * VMRegImpl::stack_slot_size + stack_slot_offset;
if (offset == stack_slot_offset) at_old_sp = true;
stream->print("[%s+0x%x]", spname, offset);
} else {
stream->print("reg%d:%d??", (int)(intptr_t)fst, (int)(intptr_t)snd);
}
bool has_this = !m->is_static();
if (ces->has_inline_recv() && block_begin == verified_entry_point()) {
// <this> argument is scalarized for verified_entry_point()
has_this = false;
}
const char* spname = "sp"; // make arch-specific?
int stack_slot_offset = this->frame_size() * wordSize;
int tab1 = 14, tab2 = 24;
int sig_index = 0;
int arg_index = has_this ? -1 : 0;
bool did_old_sp = false;
for (SignatureStream ss(sig); !ss.at_return_type(); ) {
bool at_this = (arg_index == -1);
bool at_old_sp = false;
BasicType t = ss.type();
assert(t == sig_bt[sig_index], "sigs in sync");
if (at_this) {
stream->print(" # this: ");
} else {
stream->print(" # parm%d: ", arg_index);
}
stream->move_to(tab1);
VMReg fst = regs[sig_index].first();
VMReg snd = regs[sig_index].second();
if (fst->is_reg()) {
stream->print("%s", fst->name());
if (snd->is_valid()) {
stream->print(":%s", snd->name());
}
} else if (fst->is_stack()) {
int offset = fst->reg2stack() * VMRegImpl::stack_slot_size + stack_slot_offset;
if (offset == stack_slot_offset) at_old_sp = true;
stream->print("[%s+0x%x]", spname, offset);
} else {
stream->print("reg%d:%d??", (int)(intptr_t)fst, (int)(intptr_t)snd);
}
stream->print(" ");
stream->move_to(tab2);
stream->print("= ");
if (at_this) {
m->method_holder()->print_value_on(stream);
} else {
bool did_name = false;
if (ss.is_reference()) {
Symbol* name = ss.as_symbol();
name->print_value_on(stream);
did_name = true;
}
if (!did_name)
stream->print("%s", type2name(t));
}
if (at_old_sp) {
stream->print(" (%s of caller)", spname);
did_old_sp = true;
stream->print(" ");
stream->move_to(tab2);
stream->print("= ");
if (at_this) {
m->method_holder()->print_value_on(stream);
} else {
bool did_name = false;
if (is_reference_type(t)) {
Symbol* name = (*sig)._symbol;
name->print_value_on(stream);
did_name = true;
}
stream->cr();
sig_index += type2size[t];
arg_index += 1;
ss.next();
}
if (!did_old_sp) {
stream->print(" # ");
stream->move_to(tab1);
stream->print("[%s+0x%x]", spname, stack_slot_offset);
if (!did_name)
stream->print("%s", type2name(t));
}
if (at_old_sp) {
stream->print(" (%s of caller)", spname);
stream->cr();
did_old_sp = true;
}
stream->cr();
sig_index += type2size[t];
arg_index += 1;
}
if (!did_old_sp) {
stream->print(" # ");
stream->move_to(tab1);
stream->print("[%s+0x%x]", spname, stack_slot_offset);
stream->print(" (%s of caller)", spname);
stream->cr();
}
}

@@ -237,7 +237,7 @@ Klass* InlineKlass::array_klass_impl(bool or_null, TRAPS) {
// types is an argument: drop all T_INLINE_TYPE/T_VOID from the list).
int InlineKlass::collect_fields(GrowableArray<SigEntry>* sig, int base_off) {
int count = 0;
SigEntry::add_entry(sig, T_INLINE_TYPE, base_off);
SigEntry::add_entry(sig, T_INLINE_TYPE, name(), base_off);
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) continue;
int offset = base_off + fs.offset() - (base_off > 0 ? first_field_offset() : 0);
@@ -250,12 +250,12 @@ int InlineKlass::collect_fields(GrowableArray<SigEntry>* sig, int base_off) {
if (bt == T_INLINE_TYPE) {
bt = T_OBJECT;
}
SigEntry::add_entry(sig, bt, offset);
SigEntry::add_entry(sig, bt, fs.signature(), offset);
count += type2size[bt];
}
}
int offset = base_off + size_helper()*HeapWordSize - (base_off > 0 ? first_field_offset() : 0);
SigEntry::add_entry(sig, T_VOID, offset);
SigEntry::add_entry(sig, T_VOID, name(), offset);
if (base_off == 0) {
sig->sort(SigEntry::compare);
}
@@ -445,8 +445,7 @@ void LateInlineCallGenerator::do_late_inline() {
// Make enough space in the expression stack to transfer
// the incoming arguments and return value.
map->ensure_stack(jvms, jvms->method()->max_stack());
const TypeTuple *domain_sig = call->_tf->domain_sig();
ExtendedSignature sig_cc = ExtendedSignature(method()->get_sig_cc(), SigEntryFilter());
const TypeTuple* domain_sig = call->_tf->domain_sig();
uint nargs = method()->arg_size();
assert(domain_sig->cnt() - TypeFunc::Parms == nargs, "inconsistent signature");

@@ -457,7 +456,7 @@ void LateInlineCallGenerator::do_late_inline() {
// Inline type arguments are not passed by reference: we get an argument per
// field of the inline type. Build InlineTypeNodes from the inline type arguments.
GraphKit arg_kit(jvms, &gvn);
InlineTypeNode* vt = InlineTypeNode::make_from_multi(&arg_kit, call, sig_cc, t->inline_klass(), j, true);
InlineTypeNode* vt = InlineTypeNode::make_from_multi(&arg_kit, call, t->inline_klass(), j, true);
map->set_control(arg_kit.control());
map->set_argument(jvms, i1, vt);
} else {
@@ -1812,15 +1812,14 @@ void GraphKit::set_arguments_for_java_call(CallJavaNode* call, bool is_late_inli
}
// Add the call arguments
const TypeTuple* domain = call->tf()->domain_sig();
ExtendedSignature sig_cc = ExtendedSignature(call->method()->get_sig_cc(), SigEntryFilter());
uint nargs = domain->cnt();
for (uint i = TypeFunc::Parms, idx = TypeFunc::Parms; i < nargs; i++) {
Node* arg = argument(i-TypeFunc::Parms);
const Type* t = domain->field_at(i);
if (call->method()->has_scalarized_args() && t->is_inlinetypeptr() && !t->maybe_null() && t->inline_klass()->can_be_passed_as_fields()) {
// We don't pass inline type arguments by reference but instead pass each field of the inline type
InlineTypeNode* vt = arg->as_InlineType();
vt->pass_fields(this, call, sig_cc, idx);
vt->pass_fields(this, call, idx);
// If an inline type argument is passed as fields, attach the Method* to the call site
// to be able to access the extended signature later via attached_method_before_pc().
// For example, see CompiledMethod::preserve_callee_argument_oops().
@@ -1892,12 +1891,8 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p
// Return of multiple values (inline type fields): we create a
// InlineType node, each field is a projection from the call.
ciInlineKlass* vk = call->method()->return_type()->as_inline_klass();
const Array<SigEntry>* sig_array = vk->extended_sig();
GrowableArray<SigEntry> sig = GrowableArray<SigEntry>(sig_array->length());
sig.appendAll(sig_array);
ExtendedSignature sig_cc = ExtendedSignature(&sig, SigEntryFilter());
uint base_input = TypeFunc::Parms + 1;
ret = InlineTypeNode::make_from_multi(this, call, sig_cc, vk, base_input, false);
ret = InlineTypeNode::make_from_multi(this, call, vk, base_input, false);
} else {
ret = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
}
@@ -604,9 +604,9 @@ InlineTypeNode* InlineTypeNode::make_from_flattened(GraphKit* kit, ciInlineKlass
return kit->gvn().transform(vt)->as_InlineType();
}

InlineTypeNode* InlineTypeNode::make_from_multi(GraphKit* kit, MultiNode* multi, ExtendedSignature& sig, ciInlineKlass* vk, uint& base_input, bool in) {
InlineTypeNode* InlineTypeNode::make_from_multi(GraphKit* kit, MultiNode* multi, ciInlineKlass* vk, uint& base_input, bool in) {
InlineTypeNode* vt = make_uninitialized(kit->gvn(), vk);
vt->initialize_fields(kit, multi, sig, base_input, in);
vt->initialize_fields(kit, multi, base_input, in);
return kit->gvn().transform(vt)->as_InlineType();
}

@@ -713,7 +713,7 @@ Node* InlineTypeNode::tagged_klass(ciInlineKlass* vk, PhaseGVN& gvn) {
return gvn.makecon(TypeRawPtr::make((address)bits));
}

void InlineTypeNode::pass_fields(GraphKit* kit, Node* n, ExtendedSignature& sig, uint& base_input) {
void InlineTypeNode::pass_fields(GraphKit* kit, Node* n, uint& base_input) {
for (uint i = 0; i < field_count(); i++) {
int offset = field_offset(i);
ciType* type = field_type(i);
@@ -722,7 +722,7 @@ void InlineTypeNode::pass_fields(GraphKit* kit, Node* n, ExtendedSignature& sig,
if (field_is_flattened(i)) {
// Flattened inline type field
InlineTypeNode* vt = arg->as_InlineType();
vt->pass_fields(kit, n, sig, base_input);
vt->pass_fields(kit, n, base_input);
} else {
if (arg->is_InlineType()) {
// Non-flattened inline type field
@@ -740,15 +740,15 @@ void InlineTypeNode::pass_fields(GraphKit* kit, Node* n, ExtendedSignature& sig,
}
}

void InlineTypeNode::initialize_fields(GraphKit* kit, MultiNode* multi, ExtendedSignature& sig, uint& base_input, bool in) {
void InlineTypeNode::initialize_fields(GraphKit* kit, MultiNode* multi, uint& base_input, bool in) {
PhaseGVN& gvn = kit->gvn();
for (uint i = 0; i < field_count(); ++i) {
ciType* type = field_type(i);
Node* parm = NULL;
if (field_is_flattened(i)) {
// Flattened inline type field
InlineTypeNode* vt = make_uninitialized(gvn, type->as_inline_klass());
vt->initialize_fields(kit, multi, sig, base_input, in);
vt->initialize_fields(kit, multi, base_input, in);
parm = gvn.transform(vt);
} else {
if (multi->is_Start()) {
@@ -126,7 +126,7 @@ class InlineTypeNode : public InlineTypeBaseNode {
// Create and initialize by loading the field values from a flattened field or array
static InlineTypeNode* make_from_flattened(GraphKit* kit, ciInlineKlass* vk, Node* obj, Node* ptr, ciInstanceKlass* holder = NULL, int holder_offset = 0, DecoratorSet decorators = IN_HEAP | MO_UNORDERED);
// Create and initialize with the inputs or outputs of a MultiNode (method entry or call)
static InlineTypeNode* make_from_multi(GraphKit* kit, MultiNode* multi, ExtendedSignature& sig, ciInlineKlass* vk, uint& base_input, bool in);
static InlineTypeNode* make_from_multi(GraphKit* kit, MultiNode* multi, ciInlineKlass* vk, uint& base_input, bool in);

InlineTypeNode* make_larval(GraphKit* kit, bool allocate) const;
InlineTypeNode* finish_larval(GraphKit* kit) const;
@@ -139,9 +139,9 @@ class InlineTypeNode : public InlineTypeBaseNode {
}
static Node* tagged_klass(ciInlineKlass* vk, PhaseGVN& gvn);
// Pass inline type as fields at a call or return
void pass_fields(GraphKit* kit, Node* n, ExtendedSignature& sig, uint& base_input);
void pass_fields(GraphKit* kit, Node* n, uint& base_input);
// Initialize the inline type fields with the inputs or outputs of a MultiNode
void initialize_fields(GraphKit* kit, MultiNode* multi, ExtendedSignature& sig, uint& base_input, bool in);
void initialize_fields(GraphKit* kit, MultiNode* multi, uint& base_input, bool in);

// Allocation optimizations
void remove_redundant_allocations(PhaseIterGVN* igvn, PhaseIdealLoop* phase);
@@ -862,7 +862,6 @@ JVMState* Compile::build_start_state(StartNode* start, const TypeFunc* tf) {
}
PhaseGVN& gvn = *initial_gvn();
uint i = 0;
ExtendedSignature sig_cc = ExtendedSignature(method()->get_sig_cc(), SigEntryFilter());
for (uint j = 0; i < (uint)arg_size; i++) {
const Type* t = tf->domain_sig()->field_at(i);
Node* parm = NULL;
@@ -874,7 +873,7 @@ JVMState* Compile::build_start_state(StartNode* start, const TypeFunc* tf) {
Node* old_mem = map->memory();
// Use immutable memory for inline type loads and restore it below
kit.set_all_memory(C->immutable_memory());
parm = InlineTypeNode::make_from_multi(&kit, start, sig_cc, t->inline_klass(), j, true);
parm = InlineTypeNode::make_from_multi(&kit, start, t->inline_klass(), j, true);
map->set_control(kit.control());
map->set_memory(old_mem);
} else {
@@ -931,12 +930,8 @@ void Compile::return_values(JVMState* jvms) {
} else {
ret->init_req(TypeFunc::Parms, vt->tagged_klass(kit.gvn()));
}
const Array<SigEntry>* sig_array = vt->type()->inline_klass()->extended_sig();
GrowableArray<SigEntry> sig = GrowableArray<SigEntry>(sig_array->length());
sig.appendAll(sig_array);
ExtendedSignature sig_cc = ExtendedSignature(&sig, SigEntryFilter());
uint idx = TypeFunc::Parms+1;
vt->pass_fields(&kit, ret, sig_cc, idx);
uint idx = TypeFunc::Parms + 1;
vt->pass_fields(&kit, ret, idx);
} else {
ret->add_req(res);
// Note: The second dummy edge is not needed by a ReturnNode.

0 comments on commit 34232ad

Please sign in to comment.