|
1 import java.io.BufferedOutputStream; |
|
2 import java.io.File; |
|
3 import java.io.FileNotFoundException; |
|
4 import java.io.FileOutputStream; |
|
5 import java.io.IOException; |
|
6 import java.io.PrintStream; |
|
7 import java.util.ArrayList; |
|
8 import java.util.HashMap; |
|
9 import java.util.LinkedHashMap; |
|
10 import java.util.List; |
|
11 import java.util.Map; |
|
12 import java.util.StringJoiner; |
|
13 import java.util.function.Predicate; |
|
14 |
|
15 import javax.xml.XMLConstants; |
|
16 import javax.xml.parsers.ParserConfigurationException; |
|
17 import javax.xml.parsers.SAXParser; |
|
18 import javax.xml.parsers.SAXParserFactory; |
|
19 import javax.xml.validation.SchemaFactory; |
|
20 |
|
21 import org.xml.sax.Attributes; |
|
22 import org.xml.sax.SAXException; |
|
23 import org.xml.sax.SAXParseException; |
|
24 import org.xml.sax.helpers.DefaultHandler; |
|
25 |
|
26 public class GenerateJfrFiles { |
|
27 |
|
28 public static void main(String... args) throws Exception { |
|
29 if (args.length != 3) { |
|
30 System.err.println("Incorrect number of command line arguments."); |
|
31 System.err.println("Usage:"); |
|
32 System.err.println("java GenerateJfrFiles[.java] <path-to-metadata.xml> <path-to-metadata.xsd> <output-directory>"); |
|
33 System.exit(1); |
|
34 } |
|
35 try { |
|
36 File metadataXml = new File(args[0]); |
|
37 File metadataSchema = new File(args[1]); |
|
38 File outputDirectory = new File(args[2]); |
|
39 |
|
40 Metadata metadata = new Metadata(metadataXml, metadataSchema); |
|
41 metadata.verify(); |
|
42 metadata.wireUpTypes(); |
|
43 |
|
44 printJfrPeriodicHpp(metadata, outputDirectory); |
|
45 printJfrEventIdsHpp(metadata, outputDirectory); |
|
46 printJfrEventControlHpp(metadata, outputDirectory); |
|
47 printJfrTypesHpp(metadata, outputDirectory); |
|
48 printJfrEventClassesHpp(metadata, outputDirectory); |
|
49 |
|
50 } catch (Exception e) { |
|
51 e.printStackTrace(); |
|
52 System.exit(1); |
|
53 } |
|
54 } |
|
55 |
|
56 static class XmlType { |
|
57 final String fieldType; |
|
58 final String parameterType; |
|
59 XmlType(String fieldType, String parameterType) { |
|
60 this.fieldType = fieldType; |
|
61 this.parameterType = parameterType; |
|
62 } |
|
63 } |
|
64 |
|
65 static class TypeElement { |
|
66 List<FieldElement> fields = new ArrayList<>(); |
|
67 String name; |
|
68 String fieldType; |
|
69 String parameterType; |
|
70 boolean supportStruct; |
|
71 } |
|
72 |
|
73 static class Metadata { |
|
74 final Map<String, TypeElement> types = new LinkedHashMap<>(); |
|
75 final Map<String, XmlType> xmlTypes = new HashMap<>(); |
|
76 Metadata(File metadataXml, File metadataSchema) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException { |
|
77 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); |
|
78 SAXParserFactory factory = SAXParserFactory.newInstance(); |
|
79 factory.setSchema(schemaFactory.newSchema(metadataSchema)); |
|
80 SAXParser sp = factory.newSAXParser(); |
|
81 sp.parse(metadataXml, new MetadataHandler(this)); |
|
82 } |
|
83 |
|
84 List<EventElement> getEvents() { |
|
85 return getList(t -> t.getClass() == EventElement.class); |
|
86 } |
|
87 |
|
88 List<TypeElement> getEventsAndStructs() { |
|
89 return getList(t -> t.getClass() == EventElement.class || t.supportStruct); |
|
90 } |
|
91 |
|
92 List<TypeElement> getTypesAndStructs() { |
|
93 return getList(t -> t.getClass() == TypeElement.class || t.supportStruct); |
|
94 } |
|
95 |
|
96 @SuppressWarnings("unchecked") |
|
97 <T> List<T> getList(Predicate<? super TypeElement> pred) { |
|
98 List<T> result = new ArrayList<>(types.size()); |
|
99 for (TypeElement t : types.values()) { |
|
100 if (pred.test(t)) { |
|
101 result.add((T) t); |
|
102 } |
|
103 } |
|
104 return result; |
|
105 } |
|
106 |
|
107 List<EventElement> getPeriodicEvents() { |
|
108 return getList(t -> t.getClass() == EventElement.class && ((EventElement) t).periodic); |
|
109 } |
|
110 |
|
111 List<TypeElement> getNonEventsAndNonStructs() { |
|
112 return getList(t -> t.getClass() != EventElement.class && !t.supportStruct); |
|
113 } |
|
114 |
|
115 List<TypeElement> getTypes() { |
|
116 return getList(t -> t.getClass() == TypeElement.class && !t.supportStruct); |
|
117 } |
|
118 |
|
119 List<TypeElement> getStructs() { |
|
120 return getList(t -> t.getClass() == TypeElement.class && t.supportStruct); |
|
121 } |
|
122 |
|
123 void verify() { |
|
124 for (TypeElement t : types.values()) { |
|
125 for (FieldElement f : t.fields) { |
|
126 if (!xmlTypes.containsKey(f.typeName)) { // ignore primitives |
|
127 if (!types.containsKey(f.typeName)) { |
|
128 throw new IllegalStateException("Could not find definition of type '" + f.typeName + "' used by " + t.name + "#" + f.name); |
|
129 } |
|
130 } |
|
131 } |
|
132 } |
|
133 } |
|
134 |
|
135 void wireUpTypes() { |
|
136 for (TypeElement t : types.values()) { |
|
137 for (FieldElement f : t.fields) { |
|
138 TypeElement type = types.get(f.typeName); |
|
139 if (f.struct) { |
|
140 type.supportStruct = true; |
|
141 } |
|
142 f.type = type; |
|
143 } |
|
144 } |
|
145 } |
|
146 } |
|
147 |
|
148 static class EventElement extends TypeElement { |
|
149 String representation; |
|
150 boolean thread; |
|
151 boolean stackTrace; |
|
152 boolean startTime; |
|
153 boolean periodic; |
|
154 boolean cutoff; |
|
155 } |
|
156 |
|
157 static class FieldElement { |
|
158 final Metadata metadata; |
|
159 TypeElement type; |
|
160 String name; |
|
161 String typeName; |
|
162 boolean struct; |
|
163 |
|
164 FieldElement(Metadata metadata) { |
|
165 this.metadata = metadata; |
|
166 } |
|
167 |
|
168 String getParameterType() { |
|
169 if (struct) { |
|
170 return "const JfrStruct" + typeName + "&"; |
|
171 } |
|
172 XmlType xmlType = metadata.xmlTypes.get(typeName); |
|
173 if (xmlType != null) { |
|
174 return xmlType.parameterType; |
|
175 } |
|
176 return type != null ? "u8" : typeName; |
|
177 } |
|
178 |
|
179 String getParameterName() { |
|
180 return struct ? "value" : "new_value"; |
|
181 } |
|
182 |
|
183 String getFieldType() { |
|
184 if (struct) { |
|
185 return "JfrStruct" + typeName; |
|
186 } |
|
187 XmlType xmlType = metadata.xmlTypes.get(typeName); |
|
188 if (xmlType != null) { |
|
189 return xmlType.fieldType; |
|
190 } |
|
191 return type != null ? "u8" : typeName; |
|
192 } |
|
193 } |
|
194 |
|
195 static class MetadataHandler extends DefaultHandler { |
|
196 final Metadata metadata; |
|
197 FieldElement currentField; |
|
198 TypeElement currentType; |
|
199 MetadataHandler(Metadata metadata) { |
|
200 this.metadata = metadata; |
|
201 } |
|
202 @Override |
|
203 public void error(SAXParseException e) throws SAXException { |
|
204 throw e; |
|
205 } |
|
206 @Override |
|
207 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { |
|
208 switch (qName) { |
|
209 case "XmlType": |
|
210 String name = attributes.getValue("name"); |
|
211 String parameterType = attributes.getValue("parameterType"); |
|
212 String fieldType = attributes.getValue("fieldType"); |
|
213 metadata.xmlTypes.put(name, new XmlType(fieldType, parameterType)); |
|
214 break; |
|
215 case "Type": |
|
216 currentType = new TypeElement(); |
|
217 currentType.name = attributes.getValue("name"); |
|
218 break; |
|
219 case "Event": |
|
220 EventElement eventtType = new EventElement(); |
|
221 eventtType.name = attributes.getValue("name"); |
|
222 eventtType.thread = getBoolean(attributes, "thread", false); |
|
223 eventtType.stackTrace = getBoolean(attributes, "stackTrace", false); |
|
224 eventtType.startTime = getBoolean(attributes, "startTime", true); |
|
225 eventtType.periodic = attributes.getValue("period") != null; |
|
226 eventtType.cutoff = getBoolean(attributes, "cutoff", false); |
|
227 currentType = eventtType; |
|
228 break; |
|
229 case "Field": |
|
230 currentField = new FieldElement(metadata); |
|
231 currentField.struct = getBoolean(attributes, "struct", false); |
|
232 currentField.name = attributes.getValue("name"); |
|
233 currentField.typeName = attributes.getValue("type"); |
|
234 break; |
|
235 } |
|
236 } |
|
237 |
|
238 private boolean getBoolean(Attributes attributes, String name, boolean defaultValue) { |
|
239 String value = attributes.getValue(name); |
|
240 return value == null ? defaultValue : Boolean.valueOf(value); |
|
241 } |
|
242 |
|
243 @Override |
|
244 public void endElement(String uri, String localName, String qName) { |
|
245 switch (qName) { |
|
246 case "Type": |
|
247 case "Event": |
|
248 metadata.types.put(currentType.name, currentType); |
|
249 currentType = null; |
|
250 break; |
|
251 case "Field": |
|
252 currentType.fields.add(currentField); |
|
253 currentField = null; |
|
254 break; |
|
255 } |
|
256 } |
|
257 } |
|
258 |
|
259 static class Printer implements AutoCloseable { |
|
260 final PrintStream out; |
|
261 Printer(File outputDirectory, String filename) throws FileNotFoundException { |
|
262 out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(outputDirectory, filename)))); |
|
263 write("/* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */"); |
|
264 write(""); |
|
265 } |
|
266 |
|
267 void write(String text) { |
|
268 out.print(text); |
|
269 out.print("\n"); // Don't use Windows line endings |
|
270 } |
|
271 |
|
272 @Override |
|
273 public void close() throws Exception { |
|
274 out.close(); |
|
275 } |
|
276 } |
|
277 |
|
278 private static void printJfrPeriodicHpp(Metadata metadata, File outputDirectory) throws Exception { |
|
279 try (Printer out = new Printer(outputDirectory, "jfrPeriodic.hpp")) { |
|
280 out.write("#ifndef JFRFILES_JFRPERIODICEVENTSET_HPP"); |
|
281 out.write("#define JFRFILES_JFRPERIODICEVENTSET_HPP"); |
|
282 out.write(""); |
|
283 out.write("#include \"utilities/macros.hpp\""); |
|
284 out.write("#if INCLUDE_JFR"); |
|
285 out.write("#include \"jfrfiles/jfrEventIds.hpp\""); |
|
286 out.write("#include \"memory/allocation.hpp\""); |
|
287 out.write(""); |
|
288 out.write("class JfrPeriodicEventSet : public AllStatic {"); |
|
289 out.write(" public:"); |
|
290 out.write(" static void requestEvent(JfrEventId id) {"); |
|
291 out.write(" switch(id) {"); |
|
292 out.write(" "); |
|
293 for (EventElement e : metadata.getPeriodicEvents()) { |
|
294 out.write(" case Jfr" + e.name + "Event:"); |
|
295 out.write(" request" + e.name + "();"); |
|
296 out.write(" break;"); |
|
297 out.write(" "); |
|
298 } |
|
299 out.write(" default:"); |
|
300 out.write(" break;"); |
|
301 out.write(" }"); |
|
302 out.write(" }"); |
|
303 out.write(""); |
|
304 out.write(" private:"); |
|
305 out.write(""); |
|
306 for (EventElement e : metadata.getPeriodicEvents()) { |
|
307 out.write(" static void request" + e.name + "(void);"); |
|
308 out.write(""); |
|
309 } |
|
310 out.write("};"); |
|
311 out.write(""); |
|
312 out.write("#endif // INCLUDE_JFR"); |
|
313 out.write("#endif // JFRFILES_JFRPERIODICEVENTSET_HPP"); |
|
314 } |
|
315 } |
|
316 |
|
317 private static void printJfrEventControlHpp(Metadata metadata, File outputDirectory) throws Exception { |
|
318 try (Printer out = new Printer(outputDirectory, "jfrEventControl.hpp")) { |
|
319 out.write("#ifndef JFRFILES_JFR_NATIVE_EVENTSETTING_HPP"); |
|
320 out.write("#define JFRFILES_JFR_NATIVE_EVENTSETTING_HPP"); |
|
321 out.write(""); |
|
322 out.write("#include \"utilities/macros.hpp\""); |
|
323 out.write("#if INCLUDE_JFR"); |
|
324 out.write("#include \"jfrfiles/jfrEventIds.hpp\""); |
|
325 out.write(""); |
|
326 out.write("/**"); |
|
327 out.write(" * Event setting. We add some padding so we can use our"); |
|
328 out.write(" * event IDs as indexes into this."); |
|
329 out.write(" */"); |
|
330 out.write(""); |
|
331 out.write("struct jfrNativeEventSetting {"); |
|
332 out.write(" jlong threshold_ticks;"); |
|
333 out.write(" jlong cutoff_ticks;"); |
|
334 out.write(" u1 stacktrace;"); |
|
335 out.write(" u1 enabled;"); |
|
336 out.write(" u1 pad[6]; // Because GCC on linux ia32 at least tries to pack this."); |
|
337 out.write("};"); |
|
338 out.write(""); |
|
339 out.write("union JfrNativeSettings {"); |
|
340 out.write(" // Array version."); |
|
341 out.write(" jfrNativeEventSetting bits[MaxJfrEventId];"); |
|
342 out.write(" // Then, to make it easy to debug,"); |
|
343 out.write(" // add named struct members also."); |
|
344 out.write(" struct {"); |
|
345 out.write(" jfrNativeEventSetting pad[NUM_RESERVED_EVENTS];"); |
|
346 for (TypeElement t : metadata.getEventsAndStructs()) { |
|
347 out.write(" jfrNativeEventSetting " + t.name + ";"); |
|
348 } |
|
349 out.write(" } ev;"); |
|
350 out.write("};"); |
|
351 out.write(""); |
|
352 out.write("#endif // INCLUDE_JFR"); |
|
353 out.write("#endif // JFRFILES_JFR_NATIVE_EVENTSETTING_HPP"); |
|
354 } |
|
355 } |
|
356 |
|
357 private static void printJfrEventIdsHpp(Metadata metadata, File outputDirectory) throws Exception { |
|
358 try (Printer out = new Printer(outputDirectory, "jfrEventIds.hpp")) { |
|
359 out.write("#ifndef JFRFILES_JFREVENTIDS_HPP"); |
|
360 out.write("#define JFRFILES_JFREVENTIDS_HPP"); |
|
361 out.write(""); |
|
362 out.write("#include \"utilities/macros.hpp\""); |
|
363 out.write("#if INCLUDE_JFR"); |
|
364 out.write("#include \"jfrfiles/jfrTypes.hpp\""); |
|
365 out.write(""); |
|
366 out.write("/**"); |
|
367 out.write(" * Enum of the event types in the JVM"); |
|
368 out.write(" */"); |
|
369 out.write("enum JfrEventId {"); |
|
370 out.write(" _jfreventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index."); |
|
371 out.write(" "); |
|
372 out.write(" // Events -> enum entry"); |
|
373 for (TypeElement t : metadata.getEventsAndStructs()) { |
|
374 out.write(" Jfr" + t.name + "Event,"); |
|
375 } |
|
376 out.write(""); |
|
377 out.write(" MaxJfrEventId"); |
|
378 out.write("};"); |
|
379 out.write(""); |
|
380 out.write("/**"); |
|
381 out.write(" * Struct types in the JVM"); |
|
382 out.write(" */"); |
|
383 out.write("enum JfrStructId {"); |
|
384 for (TypeElement t : metadata.getNonEventsAndNonStructs()) { |
|
385 out.write(" Jfr" + t.name + "Struct,"); |
|
386 } |
|
387 for (TypeElement t : metadata.getEventsAndStructs()) { |
|
388 out.write(" Jfr" + t.name + "Struct,"); |
|
389 } |
|
390 out.write(""); |
|
391 out.write(" MaxJfrStructId"); |
|
392 out.write("};"); |
|
393 out.write(""); |
|
394 out.write("typedef enum JfrEventId JfrEventId;"); |
|
395 out.write("typedef enum JfrStructId JfrStructId;"); |
|
396 out.write(""); |
|
397 out.write("#endif // INCLUDE_JFR"); |
|
398 out.write("#endif // JFRFILES_JFREVENTIDS_HPP"); |
|
399 } |
|
400 } |
|
401 |
|
402 private static void printJfrTypesHpp(Metadata metadata, File outputDirectory) throws Exception { |
|
403 List<String> knownTypes = List.of("Thread", "StackTrace", "Class", "StackFrame"); |
|
404 try (Printer out = new Printer(outputDirectory, "jfrTypes.hpp")) { |
|
405 out.write("#ifndef JFRFILES_JFRTYPES_HPP"); |
|
406 out.write("#define JFRFILES_JFRTYPES_HPP"); |
|
407 out.write(""); |
|
408 out.write("#include \"utilities/macros.hpp\""); |
|
409 out.write("#if INCLUDE_JFR"); |
|
410 out.write(""); |
|
411 out.write("enum JfrTypeId {"); |
|
412 out.write(" TYPE_NONE = 0,"); |
|
413 out.write(" TYPE_CLASS = 20,"); |
|
414 out.write(" TYPE_STRING = 21,"); |
|
415 out.write(" TYPE_THREAD = 22,"); |
|
416 out.write(" TYPE_STACKTRACE = 23,"); |
|
417 out.write(" TYPE_BYTES = 24,"); |
|
418 out.write(" TYPE_EPOCHMILLIS = 25,"); |
|
419 out.write(" TYPE_MILLIS = 26,"); |
|
420 out.write(" TYPE_NANOS = 27,"); |
|
421 out.write(" TYPE_TICKS = 28,"); |
|
422 out.write(" TYPE_ADDRESS = 29,"); |
|
423 out.write(" TYPE_PERCENTAGE = 30,"); |
|
424 out.write(" TYPE_DUMMY,"); |
|
425 out.write(" TYPE_DUMMY_1,"); |
|
426 for (TypeElement type : metadata.getTypes()) { |
|
427 if (!knownTypes.contains(type.name)) { |
|
428 out.write(" TYPE_" + type.name.toUpperCase() + ","); |
|
429 } |
|
430 } |
|
431 out.write(""); |
|
432 out.write(" NUM_JFR_TYPES,"); |
|
433 out.write(" TYPES_END = 255"); |
|
434 out.write("};"); |
|
435 out.write(""); |
|
436 out.write("enum ReservedEvent {"); |
|
437 out.write(" EVENT_METADATA,"); |
|
438 out.write(" EVENT_CHECKPOINT,"); |
|
439 out.write(" EVENT_BUFFERLOST,"); |
|
440 out.write(" NUM_RESERVED_EVENTS = TYPES_END"); |
|
441 out.write("};"); |
|
442 out.write(""); |
|
443 out.write("#endif // INCLUDE_JFR"); |
|
444 out.write("#endif // JFRFILES_JFRTYPES_HPP"); |
|
445 }; |
|
446 } |
|
447 |
|
448 private static void printJfrEventClassesHpp(Metadata metadata, File outputDirectory) throws Exception { |
|
449 try (Printer out = new Printer(outputDirectory, "jfrEventClasses.hpp")) { |
|
450 out.write("#ifndef JFRFILES_JFREVENTCLASSES_HPP"); |
|
451 out.write("#define JFRFILES_JFREVENTCLASSES_HPP"); |
|
452 out.write(""); |
|
453 out.write("#include \"jfrfiles/jfrTypes.hpp\""); |
|
454 out.write("#include \"jfr/utilities/jfrTypes.hpp\""); |
|
455 out.write("#include \"utilities/macros.hpp\""); |
|
456 out.write("#include \"utilities/ticks.hpp\""); |
|
457 out.write("#if INCLUDE_JFR"); |
|
458 out.write("#include \"jfr/recorder/service/jfrEvent.hpp\""); |
|
459 out.write("/*"); |
|
460 out.write(" * Each event class has an assert member function verify() which is invoked"); |
|
461 out.write(" * just before the engine writes the event and its fields to the data stream."); |
|
462 out.write(" * The purpose of verify() is to ensure that all fields in the event are initialized"); |
|
463 out.write(" * and set before attempting to commit."); |
|
464 out.write(" *"); |
|
465 out.write(" * We enforce this requirement because events are generally stack allocated and therefore"); |
|
466 out.write(" * *not* initialized to default values. This prevents us from inadvertently committing"); |
|
467 out.write(" * uninitialized values to the data stream."); |
|
468 out.write(" *"); |
|
469 out.write(" * The assert message contains both the index (zero based) as well as the name of the field."); |
|
470 out.write(" */"); |
|
471 out.write(""); |
|
472 printTypes(out, metadata, false); |
|
473 out.write(""); |
|
474 out.write(""); |
|
475 out.write("#else // !INCLUDE_JFR"); |
|
476 out.write(""); |
|
477 out.write("class JfrEvent {"); |
|
478 out.write(" public:"); |
|
479 out.write(" JfrEvent() {}"); |
|
480 out.write(" void set_starttime(const Ticks&) const {}"); |
|
481 out.write(" void set_endtime(const Ticks&) const {}"); |
|
482 out.write(" bool should_commit() const { return false; }"); |
|
483 out.write(" static bool is_enabled() { return false; }"); |
|
484 out.write(" void commit() {}"); |
|
485 out.write("};"); |
|
486 out.write(""); |
|
487 printTypes(out, metadata, true); |
|
488 out.write(""); |
|
489 out.write(""); |
|
490 out.write("#endif // INCLUDE_JFR"); |
|
491 out.write("#endif // JFRFILES_JFREVENTCLASSES_HPP"); |
|
492 } |
|
493 } |
|
494 |
|
495 private static void printTypes(Printer out, Metadata metadata, boolean empty) { |
|
496 for (TypeElement t : metadata.getStructs()) { |
|
497 if (empty) { |
|
498 out.write(""); |
|
499 printEmptyType(out, t); |
|
500 } else { |
|
501 printType(out, t); |
|
502 } |
|
503 out.write(""); |
|
504 } |
|
505 for (EventElement e : metadata.getEvents()) { |
|
506 if (empty) { |
|
507 printEmptyEvent(out, e); |
|
508 } else { |
|
509 printEvent(out, e); |
|
510 } |
|
511 out.write(""); |
|
512 } |
|
513 } |
|
514 |
|
515 private static void printEmptyEvent(Printer out, EventElement event) { |
|
516 out.write("class Event" + event.name + " : public JfrEvent"); |
|
517 out.write("{"); |
|
518 out.write(" public:"); |
|
519 out.write(" Event" + event.name + "(EventStartTime ignore=TIMED) {}"); |
|
520 if (event.startTime) { |
|
521 StringJoiner sj = new StringJoiner(",\n "); |
|
522 for (FieldElement f : event.fields) { |
|
523 sj.add(f.getParameterType()); |
|
524 } |
|
525 out.write(" Event" + event.name + "("); |
|
526 out.write(" " + sj.toString() + ") { }"); |
|
527 } |
|
528 for (FieldElement f : event.fields) { |
|
529 out.write(" void set_" + f.name + "(" + f.getParameterType() + ") { }"); |
|
530 } |
|
531 out.write("};"); |
|
532 } |
|
533 |
|
534 private static void printEmptyType(Printer out, TypeElement t) { |
|
535 out.write("struct JfrStruct" + t.name); |
|
536 out.write("{"); |
|
537 out.write(" public:"); |
|
538 for (FieldElement f : t.fields) { |
|
539 out.write(" void set_" + f.name + "(" + f.getParameterType() + ") { }"); |
|
540 } |
|
541 out.write("};"); |
|
542 } |
|
543 |
|
544 private static void printType(Printer out, TypeElement t) { |
|
545 out.write("struct JfrStruct" + t.name); |
|
546 out.write("{"); |
|
547 out.write(" private:"); |
|
548 for (FieldElement f : t.fields) { |
|
549 printField(out, f); |
|
550 } |
|
551 out.write(""); |
|
552 out.write(" public:"); |
|
553 for (FieldElement f : t.fields) { |
|
554 printTypeSetter(out, f); |
|
555 } |
|
556 out.write(""); |
|
557 printWriteData(out, t.fields); |
|
558 out.write("};"); |
|
559 out.write(""); |
|
560 } |
|
561 |
|
562 private static void printEvent(Printer out, EventElement event) { |
|
563 out.write("class Event" + event.name + " : public JfrEvent<Event" + event.name + ">"); |
|
564 out.write("{"); |
|
565 out.write(" private:"); |
|
566 for (FieldElement f : event.fields) { |
|
567 printField(out, f); |
|
568 } |
|
569 out.write(""); |
|
570 out.write(" public:"); |
|
571 out.write(" static const bool hasThread = " + event.thread + ";"); |
|
572 out.write(" static const bool hasStackTrace = " + event.stackTrace + ";"); |
|
573 out.write(" static const bool isInstant = " + !event.startTime + ";"); |
|
574 out.write(" static const bool hasCutoff = " + event.cutoff + ";"); |
|
575 out.write(" static const bool isRequestable = " + event.periodic + ";"); |
|
576 out.write(" static const JfrEventId eventId = Jfr" + event.name + "Event;"); |
|
577 out.write(""); |
|
578 out.write(" Event" + event.name + "(EventStartTime timing=TIMED) : JfrEvent<Event" + event.name + ">(timing) {}"); |
|
579 out.write(""); |
|
580 int index = 0; |
|
581 for (FieldElement f : event.fields) { |
|
582 out.write(" void set_" + f.name + "(" + f.getParameterType() + " " + f.getParameterName() + ") {"); |
|
583 out.write(" this->_" + f.name + " = " + f.getParameterName() + ";"); |
|
584 out.write(" DEBUG_ONLY(set_field_bit(" + index++ + "));"); |
|
585 out.write(" }"); |
|
586 } |
|
587 out.write(""); |
|
588 printWriteData(out, event.fields); |
|
589 out.write(""); |
|
590 out.write(" using JfrEvent<Event" + event.name + ">::commit; // else commit() is hidden by overloaded versions in this class"); |
|
591 printConstructor2(out, event); |
|
592 printCommitMethod(out, event); |
|
593 printVerify(out, event.fields); |
|
594 out.write("};"); |
|
595 } |
|
596 |
|
597 private static void printWriteData(Printer out, List<FieldElement> fields) { |
|
598 out.write(" template <typename Writer>"); |
|
599 out.write(" void writeData(Writer& w) {"); |
|
600 for (FieldElement field : fields) { |
|
601 if (field.struct) { |
|
602 out.write(" _" + field.name + ".writeData(w);"); |
|
603 } else { |
|
604 out.write(" w.write(_" + field.name + ");"); |
|
605 } |
|
606 } |
|
607 out.write(" }"); |
|
608 } |
|
609 |
|
610 private static void printTypeSetter(Printer out, FieldElement field) { |
|
611 out.write(" void set_" + field.name + "(" + field.getParameterType() + " new_value) { this->_" + field.name + " = new_value; }"); |
|
612 } |
|
613 |
|
614 private static void printVerify(Printer out, List<FieldElement> fields) { |
|
615 out.write(""); |
|
616 out.write("#ifdef ASSERT"); |
|
617 out.write(" void verify() const {"); |
|
618 int index = 0; |
|
619 for (FieldElement f : fields) { |
|
620 out.write(" assert(verify_field_bit(" + index++ + "), \"Attempting to write an uninitialized event field: %s\", \"_" + f.name + "\");"); |
|
621 } |
|
622 out.write(" }"); |
|
623 out.write("#endif"); |
|
624 } |
|
625 |
|
626 private static void printCommitMethod(Printer out, EventElement event) { |
|
627 if (event.startTime) { |
|
628 StringJoiner sj = new StringJoiner(",\n "); |
|
629 for (FieldElement f : event.fields) { |
|
630 sj.add(f.getParameterType() + " " + f.name); |
|
631 } |
|
632 out.write(""); |
|
633 out.write(" void commit(" + sj.toString() + ") {"); |
|
634 out.write(" if (should_commit()) {"); |
|
635 for (FieldElement f : event.fields) { |
|
636 out.write(" set_" + f.name + "(" + f.name + ");"); |
|
637 } |
|
638 out.write(" commit();"); |
|
639 out.write(" }"); |
|
640 out.write(" }"); |
|
641 } |
|
642 out.write(""); |
|
643 StringJoiner sj = new StringJoiner(",\n "); |
|
644 if (event.startTime) { |
|
645 sj.add("const Ticks& startTicks"); |
|
646 sj.add("const Ticks& endTicks"); |
|
647 } |
|
648 for (FieldElement f : event.fields) { |
|
649 sj.add(f.getParameterType() + " " + f.name); |
|
650 } |
|
651 out.write(" static void commit(" + sj.toString() + ") {"); |
|
652 out.write(" Event" + event.name + " me(UNTIMED);"); |
|
653 out.write(""); |
|
654 out.write(" if (me.should_commit()) {"); |
|
655 if (event.startTime) { |
|
656 out.write(" me.set_starttime(startTicks);"); |
|
657 out.write(" me.set_endtime(endTicks);"); |
|
658 } |
|
659 for (FieldElement f : event.fields) { |
|
660 out.write(" me.set_" + f.name + "(" + f.name + ");"); |
|
661 } |
|
662 out.write(" me.commit();"); |
|
663 out.write(" }"); |
|
664 out.write(" }"); |
|
665 } |
|
666 |
|
667 private static void printConstructor2(Printer out, EventElement event) { |
|
668 if (!event.startTime) { |
|
669 out.write(""); |
|
670 out.write(""); |
|
671 } |
|
672 if (event.startTime) { |
|
673 out.write(""); |
|
674 out.write(" Event" + event.name + "("); |
|
675 StringJoiner sj = new StringJoiner(",\n "); |
|
676 for (FieldElement f : event.fields) { |
|
677 sj.add(f.getParameterType() + " " + f.name); |
|
678 } |
|
679 out.write(" " + sj.toString() + ") : JfrEvent<Event" + event.name + ">(TIMED) {"); |
|
680 out.write(" if (should_commit()) {"); |
|
681 for (FieldElement f : event.fields) { |
|
682 out.write(" set_" + f.name + "(" + f.name + ");"); |
|
683 } |
|
684 out.write(" }"); |
|
685 out.write(" }"); |
|
686 } |
|
687 } |
|
688 |
|
689 private static void printField(Printer out, FieldElement field) { |
|
690 out.write(" " + field.getFieldType() + " _" + field.name + ";"); |
|
691 } |
|
692 } |