Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/GenerateJfrFiles.java
32285 views
package build.tools.jfr;12import java.io.BufferedOutputStream;3import java.io.File;4import java.io.FileNotFoundException;5import java.io.FileOutputStream;6import java.io.IOException;7import java.io.PrintStream;8import java.util.ArrayList;9import java.util.Arrays;10import java.util.HashMap;11import java.util.Iterator;12import java.util.LinkedHashMap;13import java.util.LinkedList;14import java.util.List;15import java.util.Map;1617import javax.xml.XMLConstants;18import javax.xml.parsers.ParserConfigurationException;19import javax.xml.parsers.SAXParser;20import javax.xml.parsers.SAXParserFactory;21import javax.xml.validation.SchemaFactory;2223import org.xml.sax.Attributes;24import org.xml.sax.SAXException;25import org.xml.sax.SAXParseException;26import org.xml.sax.helpers.DefaultHandler;2728public class GenerateJfrFiles {2930public static void main(String... args) throws Exception {31if (args.length != 3) {32System.err.println("Incorrect number of command line arguments.");33System.err.println("Usage:");34System.err.println("java GenerateJfrFiles[.java] <path-to-metadata.xml> <path-to-metadata.xsd> <output-directory>");35System.exit(1);36}37try {38File metadataXml = new File(args[0]);39File metadataSchema = new File(args[1]);40File outputDirectory = new File(args[2]);4142Metadata metadata = new Metadata(metadataXml, metadataSchema);43metadata.verify();44metadata.wireUpTypes();4546printJfrPeriodicHpp(metadata, outputDirectory);47printJfrEventIdsHpp(metadata, outputDirectory);48printJfrEventControlHpp(metadata, outputDirectory);49printJfrTypesHpp(metadata, outputDirectory);50printJfrEventClassesHpp(metadata, outputDirectory);5152} catch (Exception e) {53e.printStackTrace();54System.exit(1);55}56}5758static class XmlType {59final String fieldType;60final String parameterType;61XmlType(String fieldType, String parameterType) {62this.fieldType = fieldType;63this.parameterType = parameterType;64}65}6667static class TypeElement {68List<FieldElement> fields = new ArrayList<>();69String name;70String fieldType;71String parameterType;72boolean supportStruct;73}7475interface TypePredicate {76boolean isType(TypeElement type);77}7879static class StringJoiner {80private final CharSequence delimiter;81private final List<CharSequence> elements;8283public StringJoiner(CharSequence delimiter) {84this.delimiter = delimiter;85elements = new LinkedList<CharSequence>();86}8788public StringJoiner add(CharSequence newElement) {89elements.add(newElement);90return this;91}9293@Override94public String toString() {95StringBuilder builder = new StringBuilder();96Iterator<CharSequence> i = elements.iterator();97while (i.hasNext()) {98builder.append(i.next());99if (i.hasNext()) {100builder.append(delimiter);101}102}103return builder.toString();104}105}106107static class Metadata {108final Map<String, TypeElement> types = new LinkedHashMap<>();109final Map<String, XmlType> xmlTypes = new HashMap<>();110Metadata(File metadataXml, File metadataSchema) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException {111SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);112SAXParserFactory factory = SAXParserFactory.newInstance();113factory.setSchema(schemaFactory.newSchema(metadataSchema));114SAXParser sp = factory.newSAXParser();115sp.parse(metadataXml, new MetadataHandler(this));116}117118List<EventElement> getEvents() {119return getList(new TypePredicate() {120@Override121public boolean isType(TypeElement t) {122return t.getClass() == EventElement.class;123}124});125}126127List<TypeElement> getEventsAndStructs() {128return getList(new TypePredicate() {129@Override130public boolean isType(TypeElement t) {131return t.getClass() == EventElement.class || t.supportStruct;132}133});134}135136List<TypeElement> getTypesAndStructs() {137return getList(new TypePredicate() {138@Override139public boolean isType(TypeElement t) {140return t.getClass() == TypeElement.class || t.supportStruct;141}142});143}144145@SuppressWarnings("unchecked")146<T> List<T> getList(TypePredicate pred) {147List<T> result = new ArrayList<>(types.size());148for (TypeElement t : types.values()) {149if (pred.isType(t)) {150result.add((T) t);151}152}153return result;154}155156List<EventElement> getPeriodicEvents() {157return getList(new TypePredicate() {158@Override159public boolean isType(TypeElement t) {160return t.getClass() == EventElement.class && ((EventElement) t).periodic;161}162});163}164165List<TypeElement> getNonEventsAndNonStructs() {166return getList(new TypePredicate() {167@Override168public boolean isType(TypeElement t) {169return t.getClass() != EventElement.class && !t.supportStruct;170}171});172}173174List<TypeElement> getTypes() {175return getList(new TypePredicate() {176@Override177public boolean isType(TypeElement t) {178return t.getClass() == TypeElement.class && !t.supportStruct;179}180});181}182183List<TypeElement> getStructs() {184return getList(new TypePredicate() {185@Override186public boolean isType(TypeElement t) {187return t.getClass() == TypeElement.class && t.supportStruct;188}189});190}191192void verify() {193for (TypeElement t : types.values()) {194for (FieldElement f : t.fields) {195if (!xmlTypes.containsKey(f.typeName)) { // ignore primitives196if (!types.containsKey(f.typeName)) {197throw new IllegalStateException("Could not find definition of type '" + f.typeName + "' used by " + t.name + "#" + f.name);198}199}200}201}202}203204void wireUpTypes() {205for (TypeElement t : types.values()) {206for (FieldElement f : t.fields) {207TypeElement type = types.get(f.typeName);208if (f.struct) {209type.supportStruct = true;210}211f.type = type;212}213}214}215}216217static class EventElement extends TypeElement {218String representation;219boolean thread;220boolean stackTrace;221boolean startTime;222boolean periodic;223boolean cutoff;224}225226static class FieldElement {227final Metadata metadata;228TypeElement type;229String name;230String typeName;231boolean struct;232233FieldElement(Metadata metadata) {234this.metadata = metadata;235}236237String getParameterType() {238if (struct) {239return "const JfrStruct" + typeName + "&";240}241XmlType xmlType = metadata.xmlTypes.get(typeName);242if (xmlType != null) {243return xmlType.parameterType;244}245return type != null ? "u8" : typeName;246}247248String getParameterName() {249return struct ? "value" : "new_value";250}251252String getFieldType() {253if (struct) {254return "JfrStruct" + typeName;255}256XmlType xmlType = metadata.xmlTypes.get(typeName);257if (xmlType != null) {258return xmlType.fieldType;259}260return type != null ? "u8" : typeName;261}262}263264static class MetadataHandler extends DefaultHandler {265final Metadata metadata;266FieldElement currentField;267TypeElement currentType;268MetadataHandler(Metadata metadata) {269this.metadata = metadata;270}271@Override272public void error(SAXParseException e) throws SAXException {273throw e;274}275@Override276public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {277switch (qName) {278case "XmlType":279String name = attributes.getValue("name");280String parameterType = attributes.getValue("parameterType");281String fieldType = attributes.getValue("fieldType");282metadata.xmlTypes.put(name, new XmlType(fieldType, parameterType));283break;284case "Type":285currentType = new TypeElement();286currentType.name = attributes.getValue("name");287break;288case "Event":289EventElement eventtType = new EventElement();290eventtType.name = attributes.getValue("name");291eventtType.thread = getBoolean(attributes, "thread", false);292eventtType.stackTrace = getBoolean(attributes, "stackTrace", false);293eventtType.startTime = getBoolean(attributes, "startTime", true);294eventtType.periodic = attributes.getValue("period") != null;295eventtType.cutoff = getBoolean(attributes, "cutoff", false);296currentType = eventtType;297break;298case "Field":299currentField = new FieldElement(metadata);300currentField.struct = getBoolean(attributes, "struct", false);301currentField.name = attributes.getValue("name");302currentField.typeName = attributes.getValue("type");303break;304}305}306307private boolean getBoolean(Attributes attributes, String name, boolean defaultValue) {308String value = attributes.getValue(name);309return value == null ? defaultValue : Boolean.valueOf(value);310}311312@Override313public void endElement(String uri, String localName, String qName) {314switch (qName) {315case "Type":316case "Event":317metadata.types.put(currentType.name, currentType);318currentType = null;319break;320case "Field":321currentType.fields.add(currentField);322currentField = null;323break;324}325}326}327328static class Printer implements AutoCloseable {329final PrintStream out;330Printer(File outputDirectory, String filename) throws FileNotFoundException {331out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(outputDirectory, filename))));332write("/* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */");333write("");334}335336void write(String text) {337out.print(text);338out.print("\n"); // Don't use Windows line endings339}340341@Override342public void close() throws Exception {343out.close();344}345}346347private static void printJfrPeriodicHpp(Metadata metadata, File outputDirectory) throws Exception {348try (Printer out = new Printer(outputDirectory, "jfrPeriodic.hpp")) {349out.write("#ifndef JFRFILES_JFRPERIODICEVENTSET_HPP");350out.write("#define JFRFILES_JFRPERIODICEVENTSET_HPP");351out.write("");352out.write("#include \"utilities/macros.hpp\"");353out.write("#if INCLUDE_JFR");354out.write("#include \"jfrfiles/jfrEventIds.hpp\"");355out.write("#include \"memory/allocation.hpp\"");356out.write("");357out.write("class JfrPeriodicEventSet : public AllStatic {");358out.write(" public:");359out.write(" static void requestEvent(JfrEventId id) {");360out.write(" switch(id) {");361out.write(" ");362for (EventElement e : metadata.getPeriodicEvents()) {363out.write(" case Jfr" + e.name + "Event:");364out.write(" request" + e.name + "();");365out.write(" break;");366out.write(" ");367}368out.write(" default:");369out.write(" break;");370out.write(" }");371out.write(" }");372out.write("");373out.write(" private:");374out.write("");375for (EventElement e : metadata.getPeriodicEvents()) {376out.write(" static void request" + e.name + "(void);");377out.write("");378}379out.write("};");380out.write("");381out.write("#endif // INCLUDE_JFR");382out.write("#endif // JFRFILES_JFRPERIODICEVENTSET_HPP");383}384}385386private static void printJfrEventControlHpp(Metadata metadata, File outputDirectory) throws Exception {387try (Printer out = new Printer(outputDirectory, "jfrEventControl.hpp")) {388out.write("#ifndef JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");389out.write("#define JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");390out.write("");391out.write("#include \"utilities/macros.hpp\"");392out.write("#if INCLUDE_JFR");393out.write("#include \"jfrfiles/jfrEventIds.hpp\"");394out.write("");395out.write("/**");396out.write(" * Event setting. We add some padding so we can use our");397out.write(" * event IDs as indexes into this.");398out.write(" */");399out.write("");400out.write("struct jfrNativeEventSetting {");401out.write(" jlong threshold_ticks;");402out.write(" jlong cutoff_ticks;");403out.write(" u1 stacktrace;");404out.write(" u1 enabled;");405out.write(" u1 pad[6]; // Because GCC on linux ia32 at least tries to pack this.");406out.write("};");407out.write("");408out.write("union JfrNativeSettings {");409out.write(" // Array version.");410out.write(" jfrNativeEventSetting bits[MaxJfrEventId];");411out.write(" // Then, to make it easy to debug,");412out.write(" // add named struct members also.");413out.write(" struct {");414out.write(" jfrNativeEventSetting pad[NUM_RESERVED_EVENTS];");415for (TypeElement t : metadata.getEventsAndStructs()) {416out.write(" jfrNativeEventSetting " + t.name + ";");417}418out.write(" } ev;");419out.write("};");420out.write("");421out.write("#endif // INCLUDE_JFR");422out.write("#endif // JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");423}424}425426private static void printJfrEventIdsHpp(Metadata metadata, File outputDirectory) throws Exception {427try (Printer out = new Printer(outputDirectory, "jfrEventIds.hpp")) {428out.write("#ifndef JFRFILES_JFREVENTIDS_HPP");429out.write("#define JFRFILES_JFREVENTIDS_HPP");430out.write("");431out.write("#include \"utilities/macros.hpp\"");432out.write("#if INCLUDE_JFR");433out.write("#include \"jfrfiles/jfrTypes.hpp\"");434out.write("");435out.write("/**");436out.write(" * Enum of the event types in the JVM");437out.write(" */");438out.write("enum JfrEventId {");439out.write(" _jfreventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index.");440out.write(" ");441out.write(" // Events -> enum entry");442for (TypeElement t : metadata.getEventsAndStructs()) {443out.write(" Jfr" + t.name + "Event,");444}445out.write("");446out.write(" MaxJfrEventId");447out.write("};");448out.write("");449out.write("/**");450out.write(" * Struct types in the JVM");451out.write(" */");452out.write("enum JfrStructId {");453for (TypeElement t : metadata.getNonEventsAndNonStructs()) {454out.write(" Jfr" + t.name + "Struct,");455}456for (TypeElement t : metadata.getEventsAndStructs()) {457out.write(" Jfr" + t.name + "Struct,");458}459out.write("");460out.write(" MaxJfrStructId");461out.write("};");462out.write("");463out.write("typedef enum JfrEventId JfrEventId;");464out.write("typedef enum JfrStructId JfrStructId;");465out.write("");466out.write("#endif // INCLUDE_JFR");467out.write("#endif // JFRFILES_JFREVENTIDS_HPP");468}469}470471private static void printJfrTypesHpp(Metadata metadata, File outputDirectory) throws Exception {472List<String> knownTypes = Arrays.asList(new String[] {"Thread", "StackTrace", "Class", "StackFrame"});473try (Printer out = new Printer(outputDirectory, "jfrTypes.hpp")) {474out.write("#ifndef JFRFILES_JFRTYPES_HPP");475out.write("#define JFRFILES_JFRTYPES_HPP");476out.write("");477out.write("#include \"utilities/macros.hpp\"");478out.write("#if INCLUDE_JFR");479out.write("");480out.write("enum JfrTypeId {");481out.write(" TYPE_NONE = 0,");482out.write(" TYPE_CLASS = 20,");483out.write(" TYPE_STRING = 21,");484out.write(" TYPE_THREAD = 22,");485out.write(" TYPE_STACKTRACE = 23,");486out.write(" TYPE_BYTES = 24,");487out.write(" TYPE_EPOCHMILLIS = 25,");488out.write(" TYPE_MILLIS = 26,");489out.write(" TYPE_NANOS = 27,");490out.write(" TYPE_TICKS = 28,");491out.write(" TYPE_ADDRESS = 29,");492out.write(" TYPE_PERCENTAGE = 30,");493out.write(" TYPE_DUMMY,");494out.write(" TYPE_DUMMY_1,");495for (TypeElement type : metadata.getTypes()) {496if (!knownTypes.contains(type.name)) {497out.write(" TYPE_" + type.name.toUpperCase() + ",");498}499}500out.write("");501out.write(" NUM_JFR_TYPES,");502out.write(" TYPES_END = 255");503out.write("};");504out.write("");505out.write("enum ReservedEvent {");506out.write(" EVENT_METADATA,");507out.write(" EVENT_CHECKPOINT,");508out.write(" EVENT_BUFFERLOST,");509out.write(" NUM_RESERVED_EVENTS = TYPES_END");510out.write("};");511out.write("");512out.write("#endif // INCLUDE_JFR");513out.write("#endif // JFRFILES_JFRTYPES_HPP");514};515}516517private static void printJfrEventClassesHpp(Metadata metadata, File outputDirectory) throws Exception {518try (Printer out = new Printer(outputDirectory, "jfrEventClasses.hpp")) {519out.write("#ifndef JFRFILES_JFREVENTCLASSES_HPP");520out.write("#define JFRFILES_JFREVENTCLASSES_HPP");521out.write("");522out.write("#include \"oops/klass.hpp\"");523out.write("#include \"jfrfiles/jfrTypes.hpp\"");524out.write("#include \"jfr/utilities/jfrTypes.hpp\"");525out.write("#include \"utilities/macros.hpp\"");526out.write("#include \"utilities/ticks.hpp\"");527out.write("#if INCLUDE_JFR");528out.write("#include \"jfr/recorder/service/jfrEvent.hpp\"");529out.write("/*");530out.write(" * Each event class has an assert member function verify() which is invoked");531out.write(" * just before the engine writes the event and its fields to the data stream.");532out.write(" * The purpose of verify() is to ensure that all fields in the event are initialized");533out.write(" * and set before attempting to commit.");534out.write(" *");535out.write(" * We enforce this requirement because events are generally stack allocated and therefore");536out.write(" * *not* initialized to default values. This prevents us from inadvertently committing");537out.write(" * uninitialized values to the data stream.");538out.write(" *");539out.write(" * The assert message contains both the index (zero based) as well as the name of the field.");540out.write(" */");541out.write("");542printTypes(out, metadata, false);543out.write("");544out.write("");545out.write("#else // !INCLUDE_JFR");546out.write("");547out.write("template <typename T>");548out.write("class JfrEvent {");549out.write(" public:");550out.write(" JfrEvent() {}");551out.write(" void set_starttime(const Ticks&) const {}");552out.write(" void set_endtime(const Ticks&) const {}");553out.write(" bool should_commit() const { return false; }");554out.write(" static bool is_enabled() { return false; }");555out.write(" void commit() {}");556out.write("};");557out.write("");558printTypes(out, metadata, true);559out.write("");560out.write("");561out.write("#endif // INCLUDE_JFR");562out.write("#endif // JFRFILES_JFREVENTCLASSES_HPP");563}564}565566private static void printTypes(Printer out, Metadata metadata, boolean empty) {567for (TypeElement t : metadata.getStructs()) {568printType(out, t, empty);569out.write("");570}571for (EventElement e : metadata.getEvents()) {572printEvent(out, e, empty);573out.write("");574}575}576577private static void printType(Printer out, TypeElement t, boolean empty) {578out.write("struct JfrStruct" + t.name);579out.write("{");580if (!empty) {581out.write(" private:");582for (FieldElement f : t.fields) {583printField(out, f);584}585out.write("");586}587out.write(" public:");588for (FieldElement f : t.fields) {589printTypeSetter(out, f, empty);590}591out.write("");592if (!empty) {593printWriteData(out, t.fields);594}595out.write("};");596out.write("");597}598599private static void printEvent(Printer out, EventElement event, boolean empty) {600out.write("class Event" + event.name + " : public JfrEvent<Event" + event.name + ">");601out.write("{");602if (!empty) {603out.write(" private:");604for (FieldElement f : event.fields) {605printField(out, f);606}607out.write("");608}609out.write(" public:");610if (!empty) {611out.write(" static const bool hasThread = " + event.thread + ";");612out.write(" static const bool hasStackTrace = " + event.stackTrace + ";");613out.write(" static const bool isInstant = " + !event.startTime + ";");614out.write(" static const bool hasCutoff = " + event.cutoff + ";");615out.write(" static const bool isRequestable = " + event.periodic + ";");616out.write(" static const JfrEventId eventId = Jfr" + event.name + "Event;");617out.write("");618}619if (!empty) {620out.write(" Event" + event.name + "(EventStartTime timing=TIMED) : JfrEvent<Event" + event.name + ">(timing) {}");621} else {622out.write(" Event" + event.name + "(EventStartTime timing=TIMED) {}");623}624out.write("");625int index = 0;626for (FieldElement f : event.fields) {627out.write(" void set_" + f.name + "(" + f.getParameterType() + " " + f.getParameterName() + ") {");628if (!empty) {629out.write(" this->_" + f.name + " = " + f.getParameterName() + ";");630out.write(" DEBUG_ONLY(set_field_bit(" + index++ + "));");631}632out.write(" }");633}634out.write("");635if (!empty) {636printWriteData(out, event.fields);637out.write("");638}639out.write(" using JfrEvent<Event" + event.name + ">::commit; // else commit() is hidden by overloaded versions in this class");640printConstructor2(out, event, empty);641printCommitMethod(out, event, empty);642if (!empty) {643printVerify(out, event.fields);644}645out.write("};");646}647648private static void printWriteData(Printer out, List<FieldElement> fields) {649out.write(" template <typename Writer>");650out.write(" void writeData(Writer& w) {");651for (FieldElement field : fields) {652if (field.struct) {653out.write(" _" + field.name + ".writeData(w);");654} else {655out.write(" w.write(_" + field.name + ");");656}657}658out.write(" }");659}660661private static void printTypeSetter(Printer out, FieldElement field, boolean empty) {662if (!empty) {663out.write(" void set_" + field.name + "(" + field.getParameterType() + " new_value) { this->_" + field.name + " = new_value; }");664} else {665out.write(" void set_" + field.name + "(" + field.getParameterType() + " new_value) { }");666}667}668669private static void printVerify(Printer out, List<FieldElement> fields) {670out.write("");671out.write("#ifdef ASSERT");672out.write(" void verify() const {");673int index = 0;674for (FieldElement f : fields) {675out.write(" assert(verify_field_bit(" + index++ + "), \"Attempting to write an uninitialized event field: " + f.name + "\");");676}677out.write(" }");678out.write("#endif");679}680681private static void printCommitMethod(Printer out, EventElement event, boolean empty) {682if (event.startTime) {683StringJoiner sj = new StringJoiner(",\n ");684for (FieldElement f : event.fields) {685sj.add(f.getParameterType() + " " + f.name);686}687out.write("");688out.write(" void commit(" + sj.toString() + ") {");689if (!empty) {690out.write(" if (should_commit()) {");691for (FieldElement f : event.fields) {692out.write(" set_" + f.name + "(" + f.name + ");");693}694out.write(" commit();");695out.write(" }");696}697out.write(" }");698}699out.write("");700StringJoiner sj = new StringJoiner(",\n ");701if (event.startTime) {702sj.add("const Ticks& startTicks");703sj.add("const Ticks& endTicks");704}705for (FieldElement f : event.fields) {706sj.add(f.getParameterType() + " " + f.name);707}708out.write(" static void commit(" + sj.toString() + ") {");709if (!empty) {710out.write(" Event" + event.name + " me(UNTIMED);");711out.write("");712out.write(" if (me.should_commit()) {");713if (event.startTime) {714out.write(" me.set_starttime(startTicks);");715out.write(" me.set_endtime(endTicks);");716}717for (FieldElement f : event.fields) {718out.write(" me.set_" + f.name + "(" + f.name + ");");719}720out.write(" me.commit();");721out.write(" }");722}723out.write(" }");724}725726private static void printConstructor2(Printer out, EventElement event, boolean empty) {727if (!event.startTime) {728out.write("");729out.write("");730}731if (event.startTime) {732out.write("");733out.write(" Event" + event.name + "(");734StringJoiner sj = new StringJoiner(",\n ");735for (FieldElement f : event.fields) {736sj.add(f.getParameterType() + " " + f.name);737}738if (!empty) {739out.write(" " + sj.toString() + ") : JfrEvent<Event" + event.name + ">(TIMED) {");740out.write(" if (should_commit()) {");741for (FieldElement f : event.fields) {742out.write(" set_" + f.name + "(" + f.name + ");");743}744out.write(" }");745} else {746out.write(" " + sj.toString() + ") {");747}748out.write(" }");749}750}751752private static void printField(Printer out, FieldElement field) {753out.write(" " + field.getFieldType() + " _" + field.name + ";");754}755}756757758