8371789: C2: More explicit dump results for TypePtr

Reviewed-by: chagedorn, vlivanov
This commit is contained in:
Quan Anh Mai 2025-11-24 18:12:36 +00:00
parent 2177260094
commit 8bafc2f0ae
3 changed files with 109 additions and 166 deletions

View File

@ -45,6 +45,8 @@
#include "opto/type.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/ostream.hpp"
#include "utilities/powerOfTwo.hpp"
#include "utilities/stringUtils.hpp"
@ -2979,15 +2981,22 @@ const char *const TypePtr::ptr_msg[TypePtr::lastPTR] = {
#ifndef PRODUCT
void TypePtr::dump2( Dict &d, uint depth, outputStream *st ) const {
if( _ptr == Null ) st->print("null");
else st->print("%s *", ptr_msg[_ptr]);
if( _offset == OffsetTop ) st->print("+top");
else if( _offset == OffsetBot ) st->print("+bot");
else if( _offset ) st->print("+%d", _offset);
st->print("ptr:%s", ptr_msg[_ptr]);
dump_offset(st);
dump_inline_depth(st);
dump_speculative(st);
}
void TypePtr::dump_offset(outputStream* st) const {
if (_offset == OffsetBot) {
st->print("+bot");
} else if (_offset == OffsetTop) {
st->print("+top");
} else {
st->print("+%d", _offset);
}
}
/**
*dump the speculative part of the type
*/
@ -3159,11 +3168,12 @@ uint TypeRawPtr::hash(void) const {
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
if( _ptr == Constant )
st->print(INTPTR_FORMAT, p2i(_bits));
else
void TypeRawPtr::dump2(Dict& d, uint depth, outputStream* st) const {
if (_ptr == Constant) {
st->print("rawptr:Constant:" INTPTR_FORMAT, p2i(_bits));
} else {
st->print("rawptr:%s", ptr_msg[_ptr]);
}
}
#endif
@ -3798,24 +3808,29 @@ uint TypeOopPtr::hash(void) const {
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
void TypeOopPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
void TypeOopPtr::dump2(Dict& d, uint depth, outputStream* st) const {
st->print("oopptr:%s", ptr_msg[_ptr]);
if( _klass_is_exact ) st->print(":exact");
if( const_oop() ) st->print(INTPTR_FORMAT, p2i(const_oop()));
switch( _offset ) {
case OffsetTop: st->print("+top"); break;
case OffsetBot: st->print("+any"); break;
case 0: break;
default: st->print("+%d",_offset); break;
if (_klass_is_exact) {
st->print(":exact");
}
if (_instance_id == InstanceTop)
st->print(",iid=top");
else if (_instance_id != InstanceBot)
st->print(",iid=%d",_instance_id);
if (const_oop() != nullptr) {
st->print(":" INTPTR_FORMAT, p2i(const_oop()));
}
dump_offset(st);
dump_instance_id(st);
dump_inline_depth(st);
dump_speculative(st);
}
void TypeOopPtr::dump_instance_id(outputStream* st) const {
if (_instance_id == InstanceTop) {
st->print(",iid=top");
} else if (_instance_id == InstanceBot) {
st->print(",iid=bot");
} else {
st->print(",iid=%d", _instance_id);
}
}
#endif
//------------------------------singleton--------------------------------------
@ -4453,50 +4468,30 @@ bool TypeInstPtr::maybe_java_subtype_of_helper(const TypeOopPtr* other, bool thi
#ifndef PRODUCT
void TypeInstPtr::dump2(Dict &d, uint depth, outputStream* st) const {
// Print the name of the klass.
st->print("instptr:");
klass()->print_name_on(st);
_interfaces->dump(st);
switch( _ptr ) {
case Constant:
if (WizardMode || Verbose) {
ResourceMark rm;
stringStream ss;
if (_ptr == Constant && (WizardMode || Verbose)) {
ResourceMark rm;
stringStream ss;
st->print(" ");
const_oop()->print_oop(&ss);
// 'const_oop->print_oop()' may emit newlines('\n') into ss.
// suppress newlines from it so -XX:+Verbose -XX:+PrintIdeal dumps one-liner for each node.
char* buf = ss.as_string(/* c_heap= */false);
StringUtils::replace_no_expand(buf, "\n", "");
st->print_raw(buf);
}
case BotPTR:
if (!WizardMode && !Verbose) {
if( _klass_is_exact ) st->print(":exact");
break;
}
case TopPTR:
case AnyNull:
case NotNull:
st->print(":%s", ptr_msg[_ptr]);
if( _klass_is_exact ) st->print(":exact");
break;
default:
break;
st->print(" ");
const_oop()->print_oop(&ss);
// 'const_oop->print_oop()' may emit newlines('\n') into ss.
// suppress newlines from it so -XX:+Verbose -XX:+PrintIdeal dumps one-liner for each node.
char* buf = ss.as_string(/* c_heap= */false);
StringUtils::replace_no_expand(buf, "\n", "");
st->print_raw(buf);
}
if( _offset ) { // Dump offset, if any
if( _offset == OffsetBot ) st->print("+any");
else if( _offset == OffsetTop ) st->print("+unknown");
else st->print("+%d", _offset);
st->print(":%s", ptr_msg[_ptr]);
if (_klass_is_exact) {
st->print(":exact");
}
st->print(" *");
if (_instance_id == InstanceTop)
st->print(",iid=top");
else if (_instance_id != InstanceBot)
st->print(",iid=%d",_instance_id);
dump_offset(st);
dump_instance_id(st);
dump_inline_depth(st);
dump_speculative(st);
}
@ -5089,26 +5084,17 @@ const Type *TypeAryPtr::xdual() const {
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
_ary->dump2(d,depth,st);
st->print("aryptr:");
_ary->dump2(d, depth, st);
_interfaces->dump(st);
switch( _ptr ) {
case Constant:
if (_ptr == Constant) {
const_oop()->print(st);
break;
case BotPTR:
if (!WizardMode && !Verbose) {
if( _klass_is_exact ) st->print(":exact");
break;
}
case TopPTR:
case AnyNull:
case NotNull:
st->print(":%s", ptr_msg[_ptr]);
if( _klass_is_exact ) st->print(":exact");
break;
default:
break;
}
st->print(":%s", ptr_msg[_ptr]);
if (_klass_is_exact) {
st->print(":exact");
}
if( _offset != 0 ) {
@ -5126,12 +5112,8 @@ void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
}
}
}
st->print(" *");
if (_instance_id == InstanceTop)
st->print(",iid=top");
else if (_instance_id != InstanceBot)
st->print(",iid=%d",_instance_id);
dump_instance_id(st);
dump_inline_depth(st);
dump_speculative(st);
}
@ -5490,13 +5472,10 @@ const Type *TypeMetadataPtr::xdual() const {
#ifndef PRODUCT
void TypeMetadataPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
st->print("metadataptr:%s", ptr_msg[_ptr]);
if( metadata() ) st->print(INTPTR_FORMAT, p2i(metadata()));
switch( _offset ) {
case OffsetTop: st->print("+top"); break;
case OffsetBot: st->print("+any"); break;
case 0: break;
default: st->print("+%d",_offset); break;
if (metadata() != nullptr) {
st->print(":" INTPTR_FORMAT, p2i(metadata()));
}
dump_offset(st);
}
#endif
@ -5644,44 +5623,6 @@ intptr_t TypeKlassPtr::get_con() const {
return (intptr_t)k->constant_encoding();
}
//------------------------------dump2------------------------------------------
// Dump Klass Type
#ifndef PRODUCT
void TypeKlassPtr::dump2(Dict & d, uint depth, outputStream *st) const {
switch(_ptr) {
case Constant:
st->print("precise ");
case NotNull:
{
const char *name = klass()->name()->as_utf8();
if (name) {
st->print("%s: " INTPTR_FORMAT, name, p2i(klass()));
} else {
ShouldNotReachHere();
}
_interfaces->dump(st);
}
case BotPTR:
if (!WizardMode && !Verbose && _ptr != Constant) break;
case TopPTR:
case AnyNull:
st->print(":%s", ptr_msg[_ptr]);
if (_ptr == Constant) st->print(":exact");
break;
default:
break;
}
if (_offset) { // Dump offset, if any
if (_offset == OffsetBot) { st->print("+any"); }
else if (_offset == OffsetTop) { st->print("+unknown"); }
else { st->print("+%d", _offset); }
}
st->print(" *");
}
#endif
//=============================================================================
// Convenience common pre-built types.
@ -6036,6 +5977,15 @@ const TypeKlassPtr* TypeInstKlassPtr::try_improve() const {
return this;
}
#ifndef PRODUCT
void TypeInstKlassPtr::dump2(Dict& d, uint depth, outputStream* st) const {
st->print("instklassptr:");
klass()->print_name_on(st);
_interfaces->dump(st);
st->print(":%s", ptr_msg[_ptr]);
dump_offset(st);
}
#endif // PRODUCT
const TypeAryKlassPtr *TypeAryKlassPtr::make(PTR ptr, const Type* elem, ciKlass* k, int offset) {
return (TypeAryKlassPtr*)(new TypeAryKlassPtr(ptr, elem, k, offset))->hashcons();
@ -6507,34 +6457,11 @@ ciKlass* TypeAryKlassPtr::klass() const {
// Dump Klass Type
#ifndef PRODUCT
void TypeAryKlassPtr::dump2( Dict & d, uint depth, outputStream *st ) const {
switch( _ptr ) {
case Constant:
st->print("precise ");
case NotNull:
{
st->print("[");
_elem->dump2(d, depth, st);
_interfaces->dump(st);
st->print(": ");
}
case BotPTR:
if( !WizardMode && !Verbose && _ptr != Constant ) break;
case TopPTR:
case AnyNull:
st->print(":%s", ptr_msg[_ptr]);
if( _ptr == Constant ) st->print(":exact");
break;
default:
break;
}
if( _offset ) { // Dump offset, if any
if( _offset == OffsetBot ) { st->print("+any"); }
else if( _offset == OffsetTop ) { st->print("+unknown"); }
else { st->print("+%d", _offset); }
}
st->print(" *");
st->print("aryklassptr:[");
_elem->dump2(d, depth, st);
_interfaces->dump(st);
st->print(":%s", ptr_msg[_ptr]);
dump_offset(st);
}
#endif

View File

@ -1176,15 +1176,15 @@ protected:
int hash_speculative() const;
const TypePtr* add_offset_speculative(intptr_t offset) const;
const TypePtr* with_offset_speculative(intptr_t offset) const;
#ifndef PRODUCT
void dump_speculative(outputStream *st) const;
#endif
// utility methods to work on the inline depth of the type
int dual_inline_depth() const;
int meet_inline_depth(int depth) const;
#ifndef PRODUCT
void dump_inline_depth(outputStream *st) const;
void dump_speculative(outputStream* st) const;
void dump_inline_depth(outputStream* st) const;
void dump_offset(outputStream* st) const;
#endif
// TypeInstPtr (TypeAryPtr resp.) and TypeInstKlassPtr (TypeAryKlassPtr resp.) implement very similar meet logic.
@ -1364,6 +1364,10 @@ protected:
virtual ciKlass* exact_klass_helper() const { return nullptr; }
virtual ciKlass* klass() const { return _klass; }
#ifndef PRODUCT
void dump_instance_id(outputStream* st) const;
#endif // PRODUCT
public:
bool is_java_subtype_of(const TypeOopPtr* other) const {
@ -1832,9 +1836,6 @@ public:
virtual const TypeKlassPtr* try_improve() const { return this; }
#ifndef PRODUCT
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
#endif
private:
virtual bool is_meet_subtype_of(const TypePtr* other) const {
return is_meet_subtype_of_helper(other->is_klassptr(), klass_is_exact(), other->is_klassptr()->klass_is_exact());
@ -1914,6 +1915,11 @@ public:
// Convenience common pre-built types.
static const TypeInstKlassPtr* OBJECT; // Not-null object klass or below
static const TypeInstKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same
#ifndef PRODUCT
virtual void dump2(Dict& d, uint depth, outputStream* st) const;
#endif // PRODUCT
private:
virtual bool is_meet_subtype_of_helper(const TypeKlassPtr* other, bool this_xk, bool other_xk) const;
};

View File

@ -3208,16 +3208,26 @@ public class IRNode {
}
// Typename in load/store have the structure:
// @fully/qualified/package/name/to/TheClass+12 *
// @ptrtype:fully/qualified/package/name/to/TheClass:ptrlattice+12
// with ptrtype being the kind of the type such as instptr, aryptr, etc, and ptrlattice being
// the kind of the value such as BotPTR, NotNull, etc.
// And variation:
// - after @, we can have "stable:" or other labels, with optional space after ':'
// - the class can actually be a subclass, with $ separator (and it must be ok to give only the deepest one
// - after ptrtype, we can have "stable:" or other labels, with optional space after ':'
// - the class can actually be a nested class, with $ separator (and it must be ok to give only the deepest one
// - after the class name, we can have a comma-separated list of implemented interfaces enclosed in parentheses
// - before the offset, we can have something like ":NotNull", either way, seeing "+" or ":" means the end of the type
// Worst case, it can be something like:
// @bla: bli:a/b/c$d$e (f/g,h/i/j):NotNull+24 *
private static final String LOAD_STORE_PREFIX = "@(\\w+: ?)*[\\w/\\$]*\\b";
private static final String LOAD_STORE_SUFFIX = "( \\([^\\)]+\\))?(:|\\+)\\S* \\*";
// @bla: bli:a/b/c$d$e (f/g,h/i/j):NotNull+24
// @ matches the start character of the pattern
// (\w+: ?)+ tries to match the pattern 'ptrtype:' or 'stable:' with optional trailing whitespaces
// (\w/)* tries to match the pattern 'a/b/`
// (\w$)* tries to match the pattern 'c$d$'
// \b asserts that the next character is a word character
private static final String LOAD_STORE_PREFIX = "@(\\w+: ?)+(\\w/)*(\\w$)*\\b";
// ( \([^\)]+\))? tries to match the pattern ' (f/g,h/i/j)'
// :\w+ tries to match the pattern ':NotNull'
// .* tries to match the remaining of the pattern
private static final String LOAD_STORE_SUFFIX = "( \\([^\\)]+\\))?:\\w+.*";
private static void loadOfNodes(String irNodePlaceholder, String irNodeRegex) {
String regex = START + irNodeRegex + MID + LOAD_STORE_PREFIX + IS_REPLACED + LOAD_STORE_SUFFIX + END;