src/hotspot/share/jfr/metadata/GenerateJfrFiles.java
changeset 50113 caf115bb98ad
child 50124 781f36c0831e
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     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 }