RFR(M): 8004073: Implement C2 Ideal node specific dump() method (original) (raw)

Vladimir Kozlov vladimir.kozlov at oracle.com
Tue Jul 28 17:24:30 UTC 2015


Some first observations.

Before looking to webrev, can you use whole word Node::related(), dump_related(), dump_related_compact(), dump_compact()? "comp" could be confused for "compiled". It is more typing in debugger but it is more clear.

Also from this->dump_rel() in your example I see that you dump a lot more input nodes than I expect (only up to inputs of CmpU node). But this->dump_rel_comp() produces correct set of nodes.

It would be nice if you can avoid using macro:

+#ifndef PRODUCT

"Arithmetic nodes" are most common data nodes (vs control nodes this->is_CFG() == true). May be instead specialized rel() method you can use some flags checks in Node::rel() method.

Thanks, Vladimir

On 7/28/15 1:56 AM, Michael Haupt wrote:

Dear all,

please review and sponsor this change. RFE: https://bugs.openjdk.java.net/browse/JDK-8004073 Webrev: http://cr.openjdk.java.net/~mhaupt/8004073/webrev.00 This change extends the dumping facilities of the C2 IR Node hierarchy. Node::dump() is used in debugging sessions to print information about an IR node. The API is extended by these new entry points: * void Node::dumpcomp() -> Dump the node in compact form. * void Node::dumprel(), void Node::dumprelcomp() -> Dump the node (in compact form) and all nodes related to it. Mark the current node in the output. The notion of "related" nodes is of course a property of the node itself, or rather, of its class. This is configured in this virtual method: * virtual void Node::rel(GrowableArray<Node*> *inrel, GrowableArray<Node*> *outrel, bool compact) -> Collect all related nodes. Store the incoming related nodes in the inrel array, and the outgoing related nodes in the outrel array. In case compact representation is desired, possibly collect less nodes. This method must be overridden by all subclasses of Node that, in their notion of what related nodes are, divert from the default behaviour as specified in the implementation of Node::rel() in the Node class itself. The default is to collect all inputs and outputs till depth 1, including both data and control nodes, ignoring compactness. There are several auxiliary methods. Node collection is chiefly facilitated by this method: * void Node::collectnodes(GrowableArray<Node*> *ns, int d, bool ctrl, bool data) -> Collect nodes till depth d (positive: inputs, negative: outputs), including only control or data nodes (this is controlled by the two bool arguments, and setting both to true is nonsensical). Furthermore, there exist pre-defined collectors for common cases: * void Node::collectnodesinalldata(GrowableArray<Node*> *ns, bool ctrl) -> Collect the entire data input graph. Include control nodes only if requested. * void Node::collectnodesinallctrl(GrowableArray<Node*> *ns, bool data) -> Collect the entire control input graph. Include data nodes only if requested. * void Node::collectnodesoutallctrlboundary(GrowableArray<Node*> *ns) -> Collect all output nodes, stopping at control nodes, including these. * void Node::collectnodesindataout1(GrowableArray<Node*> *is, GrowableArray<Node*> *os, bool compact) -> Collect the entire data input graph, and outputs till depth 1. Regarding compact dumping, subclasses of Node should override this virtual method: * virtual void dumpcompspec(outputStream *st) -> Dump the specifics of a node in compact form. This method is supposed to operate in the fashion of Node::dumpspec(). The default behaviour for compact dumping is to dump a node's name and index. Specific notions of "related" have been added to the following node classes: * AbsNode and subclasses * AddNode and subclasses * AddPNode * AtanDNode * BinaryNode * BoolNode * CosDNode * CountBitsNode and subclasses * Div{D,F,I,L}Node * ExpDNode * GotoNode * HaltNode * Log{10D,D}Node * LShift{I,L}Node * Mod{D,F,I,L}Node * MulHiLNode * Mul{D,F,I,L}Node and subclasses * DivModNode and subclasses * IfNode * JumpNode * SafePointNode and subclasses (may require more detail) * StartNode and subclass * NegNode and subclasses * PowDNode * IfProjNode and subclasses * JProjNode and subclass * ParmNode * ReductionNode and subclasses * Round{Double,Float}Node * RShift{I,L}Node * SqrtDNode * SubNode and subclasses * TanDNode * AddV{B,D,F,I,L,S,}Node * DivV{D,F}Node * LShiftV{B,I,L,S}Node * MulV{D,F,I,S}Node * OrVNode * RShiftV{B,I,L,S}Node * SubV{B,D,F,I,L,S}Node * URShiftV{B,I,L,S}Node * XorVNode * URShift{I,L}Node Here is a sample session in LLDB, showing the different dumps for an IfNode: * thread #28: tid = 0x10d1ce3, 0x000000010353be17 libjvm.dylibIfNode::Ideal(this=0x0000000104888760,_ _phase=0x000000011cf62368, canreshape=<unavailable>) + 77 at_ _ifnode.cpp:1297, name = 'Java: C2 CompilerThread0', stop reason =_ _breakpoint 1.1_ _frame #0: 0x000000010353be17_ _libjvm.dylibIfNode::Ideal(this=0x0000000104888760, phase=0x000000011cf62368, canreshape=) + 77 at ifnode.cpp:1297 1294 if (removedeadregion(phase, canreshape)) return this; 1295 // No Def-Use info? 1296 if (!canreshape) return NULL; -> 1297 PhaseIterGVN *igvn = phase->isIterGVN(); 1298 1299 // Don't bother trying to transform a dead if 1300 if (in(0)->istop()) return NULL; (lldb) expr -- this->dump() 82If=== 61 79 [[ 83 84 ]] P=0.999999, C=-1.000000 !jvms: String::charAt @ bci:27 (lldb) expr -- this->dumpcomp() If(82)P=0.999999, C=-1.000000 (lldb) expr -- this->dumprel() 10Parm=== 3 [[ 38 38 65 32 ]] Parm0: java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: String::charAt @ bci:-1 38AddP=== 10 10 37 [[ 39 ]] Oop:java/lang/String:NotNull:exact+12 * [narrow] !jvms: String::charAt @ bci:6 39LoadN=== 7 38 [[ 40 ]] @java/lang/String:exact+12 * [narrow], name=value, idx=4; #narrowoop: char[int:>=0]:exact * !jvms: String::charAt @ bci:6 40DecodeN=== 39 [[ 55 42 ]] #char[int:>=0]:exact * !jvms: String::charAt @ bci:6 37ConL=== 0 [[ 38 56 ]] #long:12 55CastPP=== 47 40 [[ 56 56 97 97 96 86 ]] #char[int:>=0]:NotNull:exact * !jvms: String::charAt @ bci:9 56AddP=== 55 55 37 [[ 57 ]] !jvms: String::charAt @ bci:9 7Parm=== 3 [[ 99 98 86 65 57 32 50 39 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: String::charAt @ bci:-1 57LoadRange=== 7 56 [[ 65 58 78 ]] @bottom[int:>=0]+12 * [narrow], idx=5; #int:>=0 !jvms: String::charAt @ bci:9 11Parm=== 3 [[ 78 93 65 32 24 32 65 58 86 ]] Parm1: int !jvms: String::charAt @ bci:-1 78CmpU=== 11 57 [[ 79 ]] !jvms: String::charAt @ bci:27 79Bool=== 78 [[ 82 ]] [lt] !jvms: String::charAt @ bci:27 82 >If=== 61 79 [[ 83 84 ]] P=0.999999, C=-1.000000 !jvms: String::charAt @ bci:27 83IfTrue=== 82 [[ 99 98 ]] #1 !jvms: String::charAt @ bci:27 84IfFalse=== 82 [[ 86 ]] #0 !jvms: String::charAt @ bci:27 99Return=== 83 6 7 8 9 returns 98 [[ 0 ]] 98LoadUS=== 83 7 96 [[ 99 ]] @char[int:>=0]:exact+any *, idx=6; #char !jvms: String::charAt @ bci:27 86CallStaticJava=== 84 6 7 8 9 ( 85 1 1 55 11 ) [[ 87 ]] # Static uncommontrap(reason='rangecheck' action='makenotentrant') void ( int ) C=0.000100 String::charAt @ bci:27 !jvms: String::charAt @ bci:27 (lldb) expr -- this->dumprelcomp() If(82)P=0.999999, C=-1.000000 Bool(79)[lt] CmpU(78) Parm(11)1:int LoadRange(57) @bottom[int:>=0]+12 * [narrow], idx=5; #int:>=0 IfTrue(83)[99][98]#1 IfFalse(84)[86]#0 Return(99) LoadUS(98) @char[int:>=0]:exact+any *, idx=6; #char CallStaticJava(86)uncommontrap Best, Michael -- Oracle <http://www.oracle.com/> Dr. Michael Haupt | Principal Member of Technical Staff Phone: +49 331 200 7277 | Fax: +49 331 200 7561 OracleJava Platform Group | LangTools Team | Nashorn Oracle Deutschland B.V. & Co. KG, Schiffbauergasse 14 | 14467 Potsdam, Germany Green Oracle <http://www.oracle.com/commitment> Oracle is committed to developing practices and products that help protect the environment



More information about the hotspot-compiler-dev mailing list