diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 96fee925e5d..ecb8c2c1cd8 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -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 diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index c61c2a64278..4666cfbcf2d 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -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; }; diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 25ebcc94844..a730fcb30cf 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -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;