51 */
52 //@formatter:off
53 @NodeInfo(size = SIZE_IGNORED,
54 sizeRationale = "Node is a debugging node that should not be used in production.",
55 cycles = CYCLES_IGNORED,
56 cyclesRationale = "Node is a debugging node that should not be used in production.")
57 //@formatter:on
58 public class DynamicCounterNode extends FixedWithNextNode implements LIRLowerable {
59
60 public static final NodeClass<DynamicCounterNode> TYPE = NodeClass.create(DynamicCounterNode.class);
61 @Input ValueNode increment;
62
63 protected final String group;
64 protected final String name;
65 protected final boolean withContext;
66
67 public DynamicCounterNode(String group, String name, ValueNode increment, boolean withContext) {
68 this(TYPE, group, name, increment, withContext);
69 }
70
71 protected DynamicCounterNode(NodeClass<? extends DynamicCounterNode> c, String group, String name, ValueNode increment, boolean withContext) {
72 super(c, StampFactory.forVoid());
73 this.group = group;
74 this.name = name;
75 this.increment = increment;
76 this.withContext = withContext;
77 }
78
79 public ValueNode getIncrement() {
80 return increment;
81 }
82
83 public String getName() {
84 return name;
85 }
86
87 public String getGroup() {
88 return group;
89 }
90
91 public boolean isWithContext() {
92 return withContext;
93 }
94
95 public static void addCounterBefore(String group, String name, long increment, boolean withContext, FixedNode position) {
96 StructuredGraph graph = position.graph();
97 graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(group, name, ConstantNode.forLong(increment, position.graph()), withContext)));
98 }
99
100 @NodeIntrinsic
101 public static native void counter(@ConstantNodeParameter String group, @ConstantNodeParameter String name, long increment, @ConstantNodeParameter boolean addContext);
102
103 @Override
104 public void generate(NodeLIRBuilderTool generator) {
105 LIRGeneratorTool lirGen = generator.getLIRGeneratorTool();
106 String nameWithContext;
107 if (isWithContext()) {
108 nameWithContext = getName() + " @ ";
109 if (graph().method() != null) {
110 StackTraceElement stackTraceElement = graph().method().asStackTraceElement(0);
111 if (stackTraceElement != null) {
112 nameWithContext += " " + stackTraceElement.toString();
113 } else {
114 nameWithContext += graph().method().format("%h.%n");
115 }
116 }
117 if (graph().name != null) {
118 nameWithContext += " (" + graph().name + ")";
119 }
120
121 } else {
122 nameWithContext = getName();
123 }
124 LIRInstruction counterOp = lirGen.createBenchmarkCounter(nameWithContext, getGroup(), generator.operand(increment));
125 if (counterOp != null) {
126 lirGen.append(counterOp);
127 } else {
128 throw GraalError.unimplemented("Benchmark counters not enabled or not implemented by the back end.");
129 }
130 }
131
132 }
|
51 */
52 //@formatter:off
53 @NodeInfo(size = SIZE_IGNORED,
54 sizeRationale = "Node is a debugging node that should not be used in production.",
55 cycles = CYCLES_IGNORED,
56 cyclesRationale = "Node is a debugging node that should not be used in production.")
57 //@formatter:on
58 public class DynamicCounterNode extends FixedWithNextNode implements LIRLowerable {
59
60 public static final NodeClass<DynamicCounterNode> TYPE = NodeClass.create(DynamicCounterNode.class);
61 @Input ValueNode increment;
62
63 protected final String group;
64 protected final String name;
65 protected final boolean withContext;
66
67 public DynamicCounterNode(String group, String name, ValueNode increment, boolean withContext) {
68 this(TYPE, group, name, increment, withContext);
69 }
70
71 public static final long MIN_INCREMENT = 0;
72 public static final long MAX_INCREMENT = 10_000;
73
74 /**
75 * Clamps {@code value} to a value between {@link #MIN_INCREMENT} and {@link #MAX_INCREMENT}.
76 * This mitigates the possibility of overflowing benchmark counters.
77 */
78 public static long clampIncrement(long value) {
79 return Math.min(Math.max(value, MIN_INCREMENT), MAX_INCREMENT);
80 }
81
82 private boolean checkIncrement() {
83 if (increment.isJavaConstant()) {
84 long incValue = increment.asJavaConstant().asLong();
85 if (incValue < MIN_INCREMENT || incValue > MAX_INCREMENT) {
86 String message = String.format("Benchmark counter %s:%s has increment out of range [%d .. %d]: %d", group, getNameWithContext(), MIN_INCREMENT, MAX_INCREMENT, incValue);
87 assert false : message;
88 }
89 }
90 return true;
91 }
92
93 protected DynamicCounterNode(NodeClass<? extends DynamicCounterNode> c, String group, String name, ValueNode increment, boolean withContext) {
94 super(c, StampFactory.forVoid());
95 this.group = group;
96 this.name = name;
97 this.increment = increment;
98 this.withContext = withContext;
99 assert checkIncrement();
100 }
101
102 public ValueNode getIncrement() {
103 return increment;
104 }
105
106 public String getName() {
107 return name;
108 }
109
110 public String getGroup() {
111 return group;
112 }
113
114 public boolean isWithContext() {
115 return withContext;
116 }
117
118 public static void addCounterBefore(String group, String name, long increment, boolean withContext, FixedNode position) {
119 StructuredGraph graph = position.graph();
120 graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(group, name, ConstantNode.forLong(increment, position.graph()), withContext)));
121 }
122
123 @NodeIntrinsic
124 public static native void counter(@ConstantNodeParameter String group, @ConstantNodeParameter String name, long increment, @ConstantNodeParameter boolean addContext);
125
126 @Override
127 public void generate(NodeLIRBuilderTool generator) {
128 LIRGeneratorTool lirGen = generator.getLIRGeneratorTool();
129 String nameWithContext = getNameWithContext();
130 LIRInstruction counterOp = lirGen.createBenchmarkCounter(nameWithContext, getGroup(), generator.operand(increment));
131 if (counterOp != null) {
132 lirGen.append(counterOp);
133 } else {
134 throw GraalError.unimplemented("Benchmark counters not enabled or not implemented by the back end.");
135 }
136 }
137
138 private String getNameWithContext() {
139 String nameWithContext;
140 if (isWithContext()) {
141 nameWithContext = getName() + " @ ";
142 if (graph().method() != null) {
143 StackTraceElement stackTraceElement = graph().method().asStackTraceElement(0);
144 if (stackTraceElement != null) {
145 nameWithContext += " " + stackTraceElement.toString();
146 } else {
147 nameWithContext += graph().method().format("%h.%n");
148 }
149 }
150 if (graph().name != null) {
151 nameWithContext += " (" + graph().name + ")";
152 }
153
154 } else {
155 nameWithContext = getName();
156 }
157 return nameWithContext;
158 }
159 }
|