Skip to content

Commit

Permalink
8261336: IGV: enhance default filters
Browse files Browse the repository at this point in the history
Add filters to color and hide parts of the graph based on node categories or
estimated execution frequency, and simplify remaining filters.

Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org>
Reviewed-by: vlivanov, chagedorn, thartmann
  • Loading branch information
robcasloz and chhagedorn committed Feb 16, 2021
1 parent 3f8819c commit 16bd7d3
Show file tree
Hide file tree
Showing 25 changed files with 331 additions and 83 deletions.
43 changes: 42 additions & 1 deletion src/hotspot/share/opto/idealGraphPrinter.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, 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
Expand Down Expand Up @@ -30,6 +30,7 @@
#include "opto/parse.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/threadSMR.hpp"
#include "utilities/stringUtils.hpp"

#ifndef PRODUCT

Expand Down Expand Up @@ -378,9 +379,39 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
print_prop("block", C->cfg()->get_block(0)->_pre_order);
} else {
print_prop("block", block->_pre_order);
// Print estimated execution frequency, normalized within a [0,1] range.
buffer[0] = 0;
stringStream freq(buffer, sizeof(buffer) - 1);
// Higher precision has no practical effect in visualizations.
freq.print("%.8f", block->_freq / _max_freq);
assert(freq.size() < sizeof(buffer), "size in range");
// Enforce dots as decimal separators, as required by IGV.
StringUtils::replace_no_expand(buffer, ",", ".");
print_prop("frequency", buffer);
}
}

switch (t->category()) {
case Type::Category::Data:
print_prop("category", "data");
break;
case Type::Category::Memory:
print_prop("category", "memory");
break;
case Type::Category::Mixed:
print_prop("category", "mixed");
break;
case Type::Category::Control:
print_prop("category", "control");
break;
case Type::Category::Other:
print_prop("category", "other");
break;
case Type::Category::Undef:
print_prop("category", "undef");
break;
}

const jushort flags = node->flags();
if (flags & Node::Flag_is_Copy) {
print_prop("is_copy", "true");
Expand Down Expand Up @@ -649,6 +680,16 @@ void IdealGraphPrinter::print(const char *name, Node *node) {
VectorSet temp_set;

head(NODES_ELEMENT);
if (C->cfg() != NULL) {
// Compute the maximum estimated frequency in the current graph.
_max_freq = 1.0e-6;
for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) {
Block* block = C->cfg()->get_block(i);
if (block->_freq > _max_freq) {
_max_freq = block->_freq;
}
}
}
walk_nodes(node, false, &temp_set);
tail(NODES_ELEMENT);

Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/opto/idealGraphPrinter.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, 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
Expand Down Expand Up @@ -92,6 +92,7 @@ class IdealGraphPrinter : public CHeapObj<mtCompiler> {
PhaseChaitin* _chaitin;
bool _traverse_outs;
Compile *C;
double _max_freq;

void print_method(ciMethod *method, int bci, InlineTree *tree);
void print_inline_tree(InlineTree *tree);
Expand Down
69 changes: 68 additions & 1 deletion src/hotspot/share/opto/type.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
Expand Down Expand Up @@ -1113,6 +1113,73 @@ void Type::dump_stats() {
}
#endif

//------------------------------category---------------------------------------
#ifndef PRODUCT
Type::Category Type::category() const {
const TypeTuple* tuple;
switch (base()) {
case Type::Int:
case Type::Long:
case Type::Half:
case Type::NarrowOop:
case Type::NarrowKlass:
case Type::Array:
case Type::VectorA:
case Type::VectorS:
case Type::VectorD:
case Type::VectorX:
case Type::VectorY:
case Type::VectorZ:
case Type::AnyPtr:
case Type::RawPtr:
case Type::OopPtr:
case Type::InstPtr:
case Type::AryPtr:
case Type::MetadataPtr:
case Type::KlassPtr:
case Type::Function:
case Type::Return_Address:
case Type::FloatTop:
case Type::FloatCon:
case Type::FloatBot:
case Type::DoubleTop:
case Type::DoubleCon:
case Type::DoubleBot:
return Category::Data;
case Type::Memory:
return Category::Memory;
case Type::Control:
return Category::Control;
case Type::Top:
case Type::Abio:
case Type::Bottom:
return Category::Other;
case Type::Bad:
case Type::lastype:
return Category::Undef;
case Type::Tuple:
// Recursive case. Return CatMixed if the tuple contains types of
// different categories (e.g. CallStaticJavaNode's type), or the specific
// category if all types are of the same category (e.g. IfNode's type).
tuple = is_tuple();
if (tuple->cnt() == 0) {
return Category::Undef;
} else {
Category first = tuple->field_at(0)->category();
for (uint i = 1; i < tuple->cnt(); i++) {
if (tuple->field_at(i)->category() != first) {
return Category::Mixed;
}
}
return first;
}
default:
assert(false, "unmatched base type: all base types must be categorized");
}
return Category::Undef;
}
#endif

//------------------------------typerr-----------------------------------------
void Type::typerr( const Type *t ) const {
#ifndef PRODUCT
Expand Down
13 changes: 12 additions & 1 deletion src/hotspot/share/opto/type.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
Expand Down Expand Up @@ -364,6 +364,17 @@ class Type {
}
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
static void dump_stats();
// Groups of types, for debugging and visualization only.
enum class Category {
Data,
Memory,
Mixed, // Tuples with types of different categories.
Control,
Other, // {Type::Top, Type::Abio, Type::Bottom}.
Undef // {Type::Bad, Type::lastype}, for completeness.
};
// Return the category of this type.
Category category() const;

static const char* str(const Type* t);
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2021, 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
Expand Down Expand Up @@ -63,10 +63,8 @@ public void apply(Diagram diagram) {
for (Figure f : figures) {
for (OutputSlot os : f.getOutputSlots()) {
for (Connection c : os.getConnections()) {
if (figures.contains(c.getInputSlot().getFigure())) {
c.setStyle(rule.getLineStyle());
c.setColor(rule.getLineColor());
}
c.setStyle(rule.getLineStyle());
c.setColor(rule.getLineColor());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,5 @@
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
<folder name="Filters">
<file name="Coloring" url="filters/color.filter">
<attr name="enabled" boolvalue="true"/>
</file>


<file name="Stamp Coloring" url="filters/stampColor.filter">
<attr name="enabled" boolvalue="false"/>
</file>

<file name="Probability Coloring" url="filters/probability.filter">
<attr name="enabled" boolvalue="false"/>
</file>

<file name="Call Graph Coloring" url="filters/callgraph.filter">
<attr name="enabled" boolvalue="false"/>
</file>

<file name="Reduce Edges" url="filters/reduceEdges.filter">
<attr name="enabled" boolvalue="true"/>
</file>

<file name="Remove State" url="filters/removeState.filter">
<attr name="enabled" boolvalue="false"/>
</file>

<file name="Remove Floating" url="filters/removeFloating.filter">
<attr name="enabled" boolvalue="false"/>
</file>
</folder>
</filesystem>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2021, 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
Expand Down Expand Up @@ -46,7 +46,8 @@ public enum ConnectionStyle {

NORMAL,
DASHED,
BOLD
BOLD,
INVISIBLE
}
private InputSlot inputSlot;
private OutputSlot outputSlot;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
colorize("name", ".*", yellow);
colorize("name", "Catch.*", blue);
colorize("name", "Region|Loop|CountedLoop|Root", red);
colorize("name", "CProj|IfFalse|IfTrue|JProj|CatchProj", magenta);
colorize("name", "Con.*", orange);
colorize("name", "Parm|Proj", lightGray);
var mixedNodeColor = java.awt.Color.decode("#ffaabb");
var controlNodeColor = java.awt.Color.decode("#ee8866");
var otherNodeColor = java.awt.Color.decode("#eedd88");
var dataNodeColor = java.awt.Color.decode("#adcbea");
var memoryNodeColor = java.awt.Color.decode("#babb00");

// Nodes with bci
colorize("bci", "..*", magenta);
var mixedEdgeColor = java.awt.Color.decode("#ff7f99");
var controlEdgeColor = java.awt.Color.decode("#e75828");
var otherEdgeColor = java.awt.Color.decode("#dfc025");
var dataEdgeColor = java.awt.Color.decode("#3178c2");
var memoryEdgeColor = java.awt.Color.decode("#828200");

colorize("category", "data", dataNodeColor);
colorize("category", "memory", memoryNodeColor);
colorize("category", "mixed", mixedNodeColor);
colorize("category", "control", controlNodeColor);
colorize("category", "other", otherNodeColor);

// Line style
var f = new ColorFilter("Line Style filter");
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")), null, dataEdgeColor, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory")), null, memoryEdgeColor, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed")), null, mixedEdgeColor, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")), null, controlEdgeColor, null));
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other")), null, otherEdgeColor, null));
f.apply(graph);
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Color nodes by estimated execution frequency. Applies only when control-flow
// graph information is available (from "Global Code Motion" on).

// These colors are generated by running:
// $ python3 extract-colors.py --steps 10 --colormap coolwarm
var step0Color = java.awt.Color.decode("#3b4cc0");
var step1Color = java.awt.Color.decode("#5977e3");
var step2Color = java.awt.Color.decode("#7b9ff9");
var step3Color = java.awt.Color.decode("#9ebeff");
var step4Color = java.awt.Color.decode("#c0d4f5");
var step5Color = java.awt.Color.decode("#dddcdc");
var step6Color = java.awt.Color.decode("#f2cbb7");
var step7Color = java.awt.Color.decode("#f7ac8e");
var step8Color = java.awt.Color.decode("#ee8468");
var step9Color = java.awt.Color.decode("#d65244");
var step10Color = java.awt.Color.decode("#b40426");

var colors = [step0Color, step1Color, step2Color, step3Color, step4Color, step5Color, step6Color, step7Color, step8Color, step9Color, step10Color]
var fractions = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

// The max value is set to 1.01 instead of 1.0 to workaround a (numerical?)
// issue where nodes with frequencies close (but not equal to) 1.0 are not colored.
colorizeGradientCustom("frequency", 0.0, 1.01, "logarithmic", colors, fractions, 1024);
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/python3
#
# Copyright (c) 2021, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.

import matplotlib.cm
import argparse
import sys

parser = argparse.ArgumentParser()
parser.add_argument('--steps', type=int, default=10)
parser.add_argument('--colormap', default='coolwarm')
args = parser.parse_args()

cmap = matplotlib.cm.get_cmap(args.colormap)
n = args.steps

for step in range(n + 1):
point = step / float(n)
rgb = tuple([int(round(c * 255)) for c in cmap(point)[0:3]])
hex = '#%02x%02x%02x' % rgb
print("var step" + str(step) + "Color" + " = java.awt.Color.decode(\"" + \
hex + "\");")
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var f = new RemoveFilter("Hide control subgraph");
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control"))));
f.apply(graph);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var f = new ConnectionFilter("Hide control edges");
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")),
white,
Connection.ConnectionStyle.INVISIBLE));
f.apply(graph);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var f = new RemoveFilter("Hide data subgraph");
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data"))));
f.apply(graph);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var f = new ConnectionFilter("Hide data edges");
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")),
white,
Connection.ConnectionStyle.INVISIBLE));
f.apply(graph);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var f = new RemoveFilter("Hide memory subgraph");
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory"))));
f.apply(graph);
Loading

1 comment on commit 16bd7d3

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.