diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index bd2e7e36262..d5858b4bb3f 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -374,9 +374,28 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { #ifndef PRODUCT Compile::current()->_in_dump_cnt++; print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); + print_prop("idx", node->_idx); const Type *t = node->bottom_type(); print_prop("type", t->msg()); - print_prop("idx", node->_idx); + if (t->category() != Type::Category::Control && + t->category() != Type::Category::Memory) { + // Print detailed type information for nodes whose type is not trivial. + buffer[0] = 0; + stringStream bottom_type_stream(buffer, sizeof(buffer) - 1); + t->dump_on(&bottom_type_stream); + print_prop("bottom_type", buffer); + if (C->types() != nullptr && C->matcher() == nullptr) { + // Phase types maintained during optimization (GVN, IGVN, CCP) are + // available and valid (not in code generation phase). + const Type* pt = (*C->types())[node->_idx]; + if (pt != nullptr) { + buffer[0] = 0; + stringStream phase_type_stream(buffer, sizeof(buffer) - 1); + pt->dump_on(&phase_type_stream); + print_prop("phase_type", buffer); + } + } + } if (C->cfg() != nullptr) { Block* block = C->cfg()->get_block_for_node(node); diff --git a/src/hotspot/share/opto/idealGraphPrinter.hpp b/src/hotspot/share/opto/idealGraphPrinter.hpp index 091560d9231..aff139a82e3 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.hpp +++ b/src/hotspot/share/opto/idealGraphPrinter.hpp @@ -89,7 +89,7 @@ class IdealGraphPrinter : public CHeapObj { outputStream *_output; ciMethod *_current_method; int _depth; - char buffer[128]; + char buffer[512]; bool _should_send_method; PhaseChaitin* _chaitin; bool _traverse_outs; diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 4469c396528..535c476ab03 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -124,11 +124,10 @@ class Type_Array : public AnyObj { uint _max; const Type **_types; void grow( uint i ); // Grow array node to fit - const Type *operator[] ( uint i ) const // Lookup, or null for not mapped - { return (i<_max) ? _types[i] : (Type*)nullptr; } - friend class PhaseValues; public: Type_Array(Arena *a) : _a(a), _max(0), _types(0) {} + const Type *operator[] ( uint i ) const // Lookup, or null for not mapped + { return (i<_max) ? _types[i] : (Type*)nullptr; } const Type *fast_lookup(uint i) const{assert(i<_max,"oob");return _types[i];} // Extend the mapping: index i maps to Type *n. void map( uint i, const Type *n ) { if( i>=_max ) grow(i); _types[i] = n; } diff --git a/src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/EditPropertyFilter.java b/src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/EditPropertyFilter.java index b26e34049c8..aaab56e3241 100644 --- a/src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/EditPropertyFilter.java +++ b/src/utils/IdealGraphVisualizer/Filter/src/main/java/com/sun/hotspot/igv/filter/EditPropertyFilter.java @@ -26,23 +26,23 @@ package com.sun.hotspot.igv.filter; import com.sun.hotspot.igv.graph.Diagram; import com.sun.hotspot.igv.graph.Figure; import com.sun.hotspot.igv.graph.Selector; -import java.util.function.UnaryOperator; +import java.util.function.Function; import java.util.List; public class EditPropertyFilter extends AbstractFilter { private String name; private Selector selector; - private final String inputPropertyName; + private final String[] inputPropertyNames; private final String outputPropertyName; - private final UnaryOperator editFunction; + private final Function editFunction; public EditPropertyFilter(String name, Selector selector, - String inputPropertyName, String outputPropertyName, - UnaryOperator editFunction) { + String[] inputPropertyNames, String outputPropertyName, + Function editFunction) { this.name = name; this.selector = selector; - this.inputPropertyName = inputPropertyName; + this.inputPropertyNames = inputPropertyNames; this.outputPropertyName = outputPropertyName; this.editFunction = editFunction; } @@ -55,9 +55,12 @@ public class EditPropertyFilter extends AbstractFilter { @Override public void apply(Diagram diagram) { List
list = selector.selected(diagram); + String[] inputVals = new String[inputPropertyNames.length]; for (Figure f : list) { - String inputVal = f.getProperties().get(inputPropertyName); - String outputVal = editFunction.apply(inputVal); + for (int i = 0; i < inputPropertyNames.length; i++) { + inputVals[i] = f.getProperties().get(inputPropertyNames[i]); + } + String outputVal = editFunction.apply(inputVals); f.getProperties().setProperty(outputPropertyName, outputVal); } } diff --git a/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/helper.js b/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/helper.js index 92b3c3ab5eb..78c71c0fdb0 100644 --- a/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/helper.js +++ b/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/helper.js @@ -190,15 +190,15 @@ var white = Color.white; // function that takes as input the old property value and returns the new // property value. function editSameProperty(selector, propertyName, editFunction) { - var f = new EditPropertyFilter("", selector, propertyName, propertyName, editFunction); + var f = new EditPropertyFilter("", selector, [propertyName], propertyName, editFunction); f.apply(graph); } // Update the value of the given property ('outputPropertyName') in the selected -// nodes according to a function that takes as input the value of a possibly -// different property ('inputPropertyName') and returns the new property value. -function editProperty(selector, inputPropertyName, outputPropertyName, editFunction) { - var f = new EditPropertyFilter("", selector, inputPropertyName, outputPropertyName, editFunction); +// nodes according to a function that takes as input the values of multiple +// properties ('inputPropertyNames') and returns the new property value. +function editProperty(selector, inputPropertyNames, outputPropertyName, editFunction) { + var f = new EditPropertyFilter("", selector, inputPropertyNames, outputPropertyName, editFunction); f.apply(graph); } diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/condenseGraph.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/condenseGraph.filter index 02232647a47..6919f06da00 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/condenseGraph.filter +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/condenseGraph.filter @@ -3,7 +3,8 @@ // combination with "Simplify graph". // Pretty-print Bool nodes to be shown as output slots. -function replaceComparisonWithSign(dump_spec) { +function replaceComparisonWithSign(propertyValues) { + dump_spec = propertyValues[0] var comparison = dump_spec.replace('[','').replace(']','') switch (comparison) { case "eq": return "="; @@ -23,21 +24,22 @@ editSameProperty(and([matches("name", "ConP|ConN"), matches("dump_spec", "#.*NUL function(t) {return "null";}); // Pretty-print CatchProj nodes. -function catchProjShortText(con) { +function catchProjShortText(propertyValues) { + con = propertyValues[0] switch (con) { case "0": return "F"; // fall-through case "1": return "T"; // throw default: return "?"; } } -editProperty(matches("name", "CatchProj"), "con", "short_name", catchProjShortText); +editProperty(matches("name", "CatchProj"), ["con"], "short_name", catchProjShortText); // Add short text to inlined Mach data parameters. editProperty(and([matches("name", "MachProj"), matches("category", "data"), successorOf(matches("name", "Start"))]), - "dump_spec", "short_name", - function(dump_spec) {return dump_spec;}); + ["dump_spec"], "short_name", + function(dump_spec) {return dump_spec[0];}); // Condense inputs in all nodes. var anyNode = matches("name", ".*"); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/customNodeInfo.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/customNodeInfo.filter index a272b7420ca..3f7956dc1ee 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/customNodeInfo.filter +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/customNodeInfo.filter @@ -14,10 +14,10 @@ function callJavaInfo(dump_spec, regularPos, trapPos) { } return "trap: " + tm[2]; } -editProperty(matches("name", "CallStaticJava|CallDynamicJava|CallJava"), "dump_spec", "extra_label", - function(dump_spec) {return callJavaInfo(dump_spec, 2, 2);}); -editProperty(matches("name", "CallStaticJavaDirect|CallDynamicJavaDirect"), "dump_spec", "extra_label", - function(dump_spec) {return callJavaInfo(dump_spec, 1, 3);}); +editProperty(matches("name", "CallStaticJava|CallDynamicJava|CallJava"), ["dump_spec"], "extra_label", + function(dump_spec) {return callJavaInfo(dump_spec[0], 2, 2);}); +editProperty(matches("name", "CallStaticJavaDirect|CallDynamicJavaDirect"), ["dump_spec"], "extra_label", + function(dump_spec) {return callJavaInfo(dump_spec[0], 1, 3);}); function callLeafInfo(dump_spec, pos) { dump_components = split_string(dump_spec); @@ -26,21 +26,7 @@ function callLeafInfo(dump_spec, pos) { } return dump_components[pos]; } -editProperty(matches("name", "CallLeaf|CallLeafNoFP"), "dump_spec", "extra_label", - function(dump_spec) {return callLeafInfo(dump_spec, 1);}); -editProperty(matches("name", "CallLeafDirect|CallLeafDirectVector|CallLeafNoFPDirect"), "dump_spec", "extra_label", - function(dump_spec) {return callLeafInfo(dump_spec, 0);}); - -// Add extra line to exception creation nodes with the name of the exception. -function exceptionInfo(dump_spec) { - dump_spec2 = dump_spec.replace('#','') - dump_components = split_string(dump_spec2); - if (dump_components.length < 1) { - return null; - } - // dump_components[0] has a form like e.g. java/lang/NumberFormatException:NotNull, - // we want to return only the simple class name ("NumberFormatException"). - simple_classname = dump_components[0].split("/").pop(); - return simple_classname.split(":")[0]; -} -editProperty(matches("name", "CreateEx|CreateException"), "dump_spec", "extra_label", exceptionInfo); +editProperty(matches("name", "CallLeaf|CallLeafNoFP"), ["dump_spec"], "extra_label", + function(dump_spec) {return callLeafInfo(dump_spec[0], 1);}); +editProperty(matches("name", "CallLeafDirect|CallLeafDirectVector|CallLeafNoFPDirect"), ["dump_spec"], "extra_label", + function(dump_spec) {return callLeafInfo(dump_spec[0], 0);}); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/showTypes.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/showTypes.filter new file mode 100644 index 00000000000..16360d78c18 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters/showTypes.filter @@ -0,0 +1,72 @@ +// This filter appends simplified type information to the (possibly already +// existing) extra-label line. +// If the phase type is available, show it. If the bottom type is available and +// differs from the bottom type, show it too (prefixed with 'B:'). + +// Simplify a reference type of the form +// "[5:]my/package/Class (package1/Class1,package2/Class2,..)" +// into +// "[5:]Class" +function simplify_reference_type(type) { + // Clean up interface lists in reference types. + var m = /(.*)\(.*\)(.*)/.exec(type); + if (m != null && typeof m[1] != 'undefined' && typeof m[2] != 'undefined') { + type = m[1] + m[2]; + } + // Remove package name in reference types. + var m2 = /(\d+:)?.*\/(.*)/.exec(type); + if (m2 != null && typeof m2[2] != 'undefined') { + type = (typeof m2[1] != 'undefined' ? m2[1] : "") + m2[2]; + } + return type; +} + +// Remove fixed input types for calls and simplify references. +function simplifyType(type) { + var callTypeStart = "{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address"; + if (type.startsWith(callTypeStart)) { + // Exclude types of the first five outputs of call-like nodes. + type = type.replace(callTypeStart, "").replace("}", ""); + prefix = ", "; + if (type.startsWith(prefix)) { + type = type.slice(prefix.length); + } + components = type.split(", "); + for (i = 0; i < components.length; i++) { + components[i] = simplify_reference_type(components[i]); + } + type = "{" + components.join(", ") + "}"; + } else { + type = simplify_reference_type(type); + } + type = type.replace(">=", "≥").replace("<=", "≤"); + return type; +} + +// Merge a possibly existing extra label, bottom type, and phase type into a +// new, single extra label. +function mergeAndAppendTypeInfo(extra_label, bottom_type, phase_type) { + if (phase_type == null && bottom_type == null) { + return extra_label; + } + type = ""; + // Always show phase type, if available. + if (phase_type != null) { + type += simplifyType(phase_type); + } + // Show bottom type, if available and different from phase type. + if (bottom_type != null && bottom_type != phase_type) { + if (phase_type != null) { + type += " | "; + } + type += "B: "; + type += simplifyType(bottom_type); + } + new_extra_label = extra_label == null ? "" : (extra_label + " "); + return new_extra_label + type; +} + +editProperty(not(or([matches("bottom_type", "bottom"), + matches("bottom_type", "abIO")])), + ["extra_label", "bottom_type", "phase_type"], "extra_label", + function(propertyValues) {return mergeAndAppendTypeInfo(propertyValues[0], propertyValues[1], propertyValues[2]);}); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml index 6372b5a1e84..24533b75af0 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml @@ -15,11 +15,15 @@ - + + + + + - + diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java index 8bbc562a7d2..7ac76fdefba 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,6 +84,16 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe return middleWidget.isHitAt(localLocation); } + private void formatExtraLabel(boolean selected) { + // If the figure contains an extra label, use a light italic font to + // differentiate it from the regular label. + if (getFigure().getProperties().get("extra_label") != null) { + LabelWidget extraLabelWidget = labelWidgets.get(labelWidgets.size() - 1); + extraLabelWidget.setFont(Diagram.FONT.deriveFont(Font.ITALIC)); + extraLabelWidget.setForeground(selected ? getTextColor() : Color.DARK_GRAY); + } + } + public FigureWidget(final Figure f, DiagramScene scene) { super(scene); @@ -139,6 +149,7 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe lw.setBorder(BorderFactory.createEmptyBorder()); lw.setCheckClipping(false); } + formatExtraLabel(false); if (getFigure().getWarning() != null) { ImageWidget warningWidget = new ImageWidget(scene, warningSign); @@ -194,6 +205,7 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe for (LabelWidget labelWidget : labelWidgets) { labelWidget.setFont(font); } + formatExtraLabel(state.isSelected()); repaint(); }