--- a/make/autoconf/basics.m4 Fri May 25 09:35:02 2018 +0200
+++ b/make/autoconf/basics.m4 Fri May 25 10:14:27 2018 +0200
@@ -120,6 +120,33 @@
])
###############################################################################
+# Check if a list of space-separated words contains any word(s) from a list of
+# space-separated illegal words. Typical use is to see if a user-specified
+# set of words contains any from a set of illegal words.
+#
+# Sets the specified variable to list of matching illegal words, or to
+# the empty string if no words are matching the illegal set.
+#
+# $1: result variable name
+# $2: list of values to check
+# $3: list of illegal values
+AC_DEFUN([BASIC_GET_MATCHING_VALUES],
+[
+ # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326
+ # Notice that the original variant fails on SLES 10 and 11
+ # Some grep versions (at least bsd) behaves strangely on the base case with
+ # no legal_values, so make it explicit.
+ values_to_check=`$ECHO $2 | $TR ' ' '\n'`
+ illegal_values=`$ECHO $3 | $TR ' ' '\n'`
+ if test -z "$illegal_values"; then
+ $1=""
+ else
+ result=`$GREP -Fx "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'`
+ $1=${result//$'\n'/ }
+ fi
+])
+
+###############################################################################
# Sort a space-separated list, and remove duplicates.
#
# Sets the specified variable to the resulting list.
--- a/make/autoconf/hotspot.m4 Fri May 25 09:35:02 2018 +0200
+++ b/make/autoconf/hotspot.m4 Fri May 25 10:14:27 2018 +0200
@@ -28,6 +28,9 @@
graal vm-structs jni-check services management cmsgc g1gc parallelgc serialgc nmt cds \
static-build link-time-opt aot jfr"
+# Deprecated JVM features (these are ignored, but with a warning)
+DEPRECATED_JVM_FEATURES="trace"
+
# All valid JVM variants
VALID_JVM_VARIANTS="server client minimal core zero custom"
@@ -269,18 +272,27 @@
USER_JVM_FEATURE_LIST=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'`
AC_MSG_RESULT([$user_jvm_feature_list])
# These features will be added to all variant defaults
- JVM_FEATURES=`$ECHO $USER_JVM_FEATURE_LIST | $AWK '{ for (i=1; i<=NF; i++) if (!match($i, /^-.*/)) print $i }'`
+ JVM_FEATURES=`$ECHO $USER_JVM_FEATURE_LIST | $AWK '{ for (i=1; i<=NF; i++) if (!match($i, /^-.*/)) printf("%s ", $i) }'`
# These features will be removed from all variant defaults
- DISABLED_JVM_FEATURES=`$ECHO $USER_JVM_FEATURE_LIST | $AWK '{ for (i=1; i<=NF; i++) if (match($i, /^-.*/)) print substr($i, 2) }'`
+ DISABLED_JVM_FEATURES=`$ECHO $USER_JVM_FEATURE_LIST | $AWK '{ for (i=1; i<=NF; i++) if (match($i, /^-.*/)) printf("%s ", substr($i, 2))}'`
# Verify that the user has provided valid features
- BASIC_GET_NON_MATCHING_VALUES(INVALID_FEATURES, $JVM_FEATURES $DISABLED_JVM_FEATURES, $VALID_JVM_FEATURES)
+ BASIC_GET_NON_MATCHING_VALUES(INVALID_FEATURES, $JVM_FEATURES $DISABLED_JVM_FEATURES, $VALID_JVM_FEATURES $DEPRECATED_JVM_FEATURES)
if test "x$INVALID_FEATURES" != x; then
AC_MSG_NOTICE([Unknown JVM features specified: "$INVALID_FEATURES"])
AC_MSG_NOTICE([The available JVM features are: "$VALID_JVM_FEATURES"])
AC_MSG_ERROR([Cannot continue])
fi
+ # Check if the user has provided deprecated features
+ BASIC_GET_MATCHING_VALUES(DEPRECATED_FEATURES, $JVM_FEATURES $DISABLED_JVM_FEATURES, $DEPRECATED_JVM_FEATURES)
+ if test "x$DEPRECATED_FEATURES" != x; then
+ AC_MSG_WARN([Deprecated JVM features specified (will be ignored): "$DEPRECATED_FEATURES"])
+ # Filter out deprecated features
+ BASIC_GET_NON_MATCHING_VALUES(JVM_FEATURES, $JVM_FEATURES, $DEPRECATED_FEATURES)
+ BASIC_GET_NON_MATCHING_VALUES(DISABLED_JVM_FEATURES, $DISABLED_JVM_FEATURES, $DEPRECATED_FEATURES)
+ fi
+
fi
# Override hotspot cpu definitions for ARM platforms
--- a/make/hotspot/gensrc/GensrcJfr.gmk Fri May 25 09:35:02 2018 +0200
+++ b/make/hotspot/gensrc/GensrcJfr.gmk Fri May 25 10:14:27 2018 +0200
@@ -23,13 +23,11 @@
# questions.
#
-$(eval $(call IncludeCustomExtension, hotspot/gensrc/GensrcJfr.gmk))
+################################################################################
+# Build tools needed for the JFR source code generation
-################################################################################
-# Build tools needed for the Jfr source code generation
-
-JFR_TOOLS_SRCDIR := $(TOPDIR)/src/hotspot/share/jfr/metadata
-JFR_TOOLS_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/tools/jfr
+JFR_TOOLS_SRCDIR := $(TOPDIR)/make/src/classes
+JFR_TOOLS_OUTPUTDIR := $(OUTPUTDIR)/buildtools/tools_classes
$(eval $(call SetupJavaCompiler, GENERATE_JFRBYTECODE, \
JAVAC := $(JAVAC), \
@@ -42,53 +40,28 @@
$(eval $(call SetupJavaCompilation, BUILD_JFR_TOOLS, \
SETUP := GENERATE_JFRBYTECODE, \
SRC := $(JFR_TOOLS_SRCDIR), \
- INCLUDE_FILES := GenerateJfrFiles.java, \
BIN := $(JFR_TOOLS_OUTPUTDIR), \
))
-TOOL_JFR_GEN := $(JAVA_SMALL) -cp $(JFR_TOOLS_OUTPUTDIR) GenerateJfrFiles
+TARGETS += $(BUILD_JFR_TOOLS)
################################################################################
-# Setup make rules for Jfr file file generation.
-#
-# Parameter 1 is the name of the rule. This name is used as variable prefix,
-# and the targets generated are listed in a variable by that name. This name is
-# also used as the name of the output file.
+# Setup make rules for JFR gensrc file generation.
#
-# Remaining parameters are named arguments. These include:
-# XML_FILE -- The input source file to use
-# XSD_FILE -- The input schema for validation
-# OUTPUT_DIR -- The directory to put the generated file in
-SetupJfrGeneration = $(NamedParamsMacroTemplate)
-define SetupJfrGenerationBody
- $$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSD_FILE) $$(BUILD_JFR_TOOLS)
- $$(call LogInfo, Generating $$(@F))
- $$(call MakeDir, $$(@D))
- $$(call ExecuteWithLog, $$@, $$(TOOL_JFR_GEN) $$($1_XML_FILE) $$($1_XSD_FILE) $$($1_OUTPUT_DIR))
- test -f $$@
-
- TARGETS += $$($1_OUTPUT_DIR)/$1
-
-endef
-
-################################################################################
-# Create files in gensrc/jfrfiles
+TOOL_JFR_GEN := $(JAVA_SMALL) -cp $(JFR_TOOLS_OUTPUTDIR) build.tools.jfr.GenerateJfrFiles
JFR_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jfrfiles
JFR_SRCDIR := $(TOPDIR)/src/hotspot/share/jfr/metadata
-METADATA_XML ?= $(JFR_SRCDIR)/metadata.xml
-METADATA_XSD ?= $(JFR_SRCDIR)/metadata.xsd
+# Changing these will trigger a rebuild of generated jfr files.
+METADATA_XML := $(JFR_SRCDIR)/metadata.xml
+METADATA_XSD := $(JFR_SRCDIR)/metadata.xsd
-# Changing these will trigger a rebuild of generated jfr files.
-JFR_DEPS += \
- $(METADATA_XML) \
- $(METADATA_XSD) \
- #
+$(JFR_OUTPUTDIR)/jfrEventClasses.hpp: $(METADATA_XML) $(METADATA_XSD) \
+ $(BUILD_JFR_TOOLS)
+ $(call LogInfo, Generating $(@F))
+ $(call MakeDir, $(@D))
+ $(call ExecuteWithLog, $@, $(TOOL_JFR_GEN) $(METADATA_XML) $(METADATA_XSD) $(JFR_OUTPUTDIR))
+ test -f $@
-# our generator will generate all files in one go, so only need to setup one target rule
-$(eval $(call SetupJfrGeneration, jfrEventClasses.hpp, \
- XML_FILE := $(METADATA_XML), \
- XSD_FILE := $(METADATA_XSD), \
- OUTPUT_DIR := $(JFR_OUTPUTDIR), \
-))
\ No newline at end of file
+TARGETS += $(JFR_OUTPUTDIR)/jfrEventClasses.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java Fri May 25 10:14:27 2018 +0200
@@ -0,0 +1,695 @@
+package build.tools.jfr;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.function.Predicate;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.SchemaFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class GenerateJfrFiles {
+
+ public static void main(String... args) throws Exception {
+ if (args.length != 3) {
+ System.err.println("Incorrect number of command line arguments.");
+ System.err.println("Usage:");
+ System.err.println("java GenerateJfrFiles[.java] <path-to-metadata.xml> <path-to-metadata.xsd> <output-directory>");
+ System.exit(1);
+ }
+ try {
+ File metadataXml = new File(args[0]);
+ File metadataSchema = new File(args[1]);
+ File outputDirectory = new File(args[2]);
+
+ Metadata metadata = new Metadata(metadataXml, metadataSchema);
+ metadata.verify();
+ metadata.wireUpTypes();
+
+ printJfrPeriodicHpp(metadata, outputDirectory);
+ printJfrEventIdsHpp(metadata, outputDirectory);
+ printJfrEventControlHpp(metadata, outputDirectory);
+ printJfrTypesHpp(metadata, outputDirectory);
+ printJfrEventClassesHpp(metadata, outputDirectory);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ static class XmlType {
+ final String fieldType;
+ final String parameterType;
+ XmlType(String fieldType, String parameterType) {
+ this.fieldType = fieldType;
+ this.parameterType = parameterType;
+ }
+ }
+
+ static class TypeElement {
+ List<FieldElement> fields = new ArrayList<>();
+ String name;
+ String fieldType;
+ String parameterType;
+ boolean supportStruct;
+ }
+
+ static class Metadata {
+ final Map<String, TypeElement> types = new LinkedHashMap<>();
+ final Map<String, XmlType> xmlTypes = new HashMap<>();
+ Metadata(File metadataXml, File metadataSchema) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException {
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setSchema(schemaFactory.newSchema(metadataSchema));
+ SAXParser sp = factory.newSAXParser();
+ sp.parse(metadataXml, new MetadataHandler(this));
+ }
+
+ List<EventElement> getEvents() {
+ return getList(t -> t.getClass() == EventElement.class);
+ }
+
+ List<TypeElement> getEventsAndStructs() {
+ return getList(t -> t.getClass() == EventElement.class || t.supportStruct);
+ }
+
+ List<TypeElement> getTypesAndStructs() {
+ return getList(t -> t.getClass() == TypeElement.class || t.supportStruct);
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> List<T> getList(Predicate<? super TypeElement> pred) {
+ List<T> result = new ArrayList<>(types.size());
+ for (TypeElement t : types.values()) {
+ if (pred.test(t)) {
+ result.add((T) t);
+ }
+ }
+ return result;
+ }
+
+ List<EventElement> getPeriodicEvents() {
+ return getList(t -> t.getClass() == EventElement.class && ((EventElement) t).periodic);
+ }
+
+ List<TypeElement> getNonEventsAndNonStructs() {
+ return getList(t -> t.getClass() != EventElement.class && !t.supportStruct);
+ }
+
+ List<TypeElement> getTypes() {
+ return getList(t -> t.getClass() == TypeElement.class && !t.supportStruct);
+ }
+
+ List<TypeElement> getStructs() {
+ return getList(t -> t.getClass() == TypeElement.class && t.supportStruct);
+ }
+
+ void verify() {
+ for (TypeElement t : types.values()) {
+ for (FieldElement f : t.fields) {
+ if (!xmlTypes.containsKey(f.typeName)) { // ignore primitives
+ if (!types.containsKey(f.typeName)) {
+ throw new IllegalStateException("Could not find definition of type '" + f.typeName + "' used by " + t.name + "#" + f.name);
+ }
+ }
+ }
+ }
+ }
+
+ void wireUpTypes() {
+ for (TypeElement t : types.values()) {
+ for (FieldElement f : t.fields) {
+ TypeElement type = types.get(f.typeName);
+ if (f.struct) {
+ type.supportStruct = true;
+ }
+ f.type = type;
+ }
+ }
+ }
+ }
+
+ static class EventElement extends TypeElement {
+ String representation;
+ boolean thread;
+ boolean stackTrace;
+ boolean startTime;
+ boolean periodic;
+ boolean cutoff;
+ }
+
+ static class FieldElement {
+ final Metadata metadata;
+ TypeElement type;
+ String name;
+ String typeName;
+ boolean struct;
+
+ FieldElement(Metadata metadata) {
+ this.metadata = metadata;
+ }
+
+ String getParameterType() {
+ if (struct) {
+ return "const JfrStruct" + typeName + "&";
+ }
+ XmlType xmlType = metadata.xmlTypes.get(typeName);
+ if (xmlType != null) {
+ return xmlType.parameterType;
+ }
+ return type != null ? "u8" : typeName;
+ }
+
+ String getParameterName() {
+ return struct ? "value" : "new_value";
+ }
+
+ String getFieldType() {
+ if (struct) {
+ return "JfrStruct" + typeName;
+ }
+ XmlType xmlType = metadata.xmlTypes.get(typeName);
+ if (xmlType != null) {
+ return xmlType.fieldType;
+ }
+ return type != null ? "u8" : typeName;
+ }
+ }
+
+ static class MetadataHandler extends DefaultHandler {
+ final Metadata metadata;
+ FieldElement currentField;
+ TypeElement currentType;
+ MetadataHandler(Metadata metadata) {
+ this.metadata = metadata;
+ }
+ @Override
+ public void error(SAXParseException e) throws SAXException {
+ throw e;
+ }
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ switch (qName) {
+ case "XmlType":
+ String name = attributes.getValue("name");
+ String parameterType = attributes.getValue("parameterType");
+ String fieldType = attributes.getValue("fieldType");
+ metadata.xmlTypes.put(name, new XmlType(fieldType, parameterType));
+ break;
+ case "Type":
+ currentType = new TypeElement();
+ currentType.name = attributes.getValue("name");
+ break;
+ case "Event":
+ EventElement eventtType = new EventElement();
+ eventtType.name = attributes.getValue("name");
+ eventtType.thread = getBoolean(attributes, "thread", false);
+ eventtType.stackTrace = getBoolean(attributes, "stackTrace", false);
+ eventtType.startTime = getBoolean(attributes, "startTime", true);
+ eventtType.periodic = attributes.getValue("period") != null;
+ eventtType.cutoff = getBoolean(attributes, "cutoff", false);
+ currentType = eventtType;
+ break;
+ case "Field":
+ currentField = new FieldElement(metadata);
+ currentField.struct = getBoolean(attributes, "struct", false);
+ currentField.name = attributes.getValue("name");
+ currentField.typeName = attributes.getValue("type");
+ break;
+ }
+ }
+
+ private boolean getBoolean(Attributes attributes, String name, boolean defaultValue) {
+ String value = attributes.getValue(name);
+ return value == null ? defaultValue : Boolean.valueOf(value);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) {
+ switch (qName) {
+ case "Type":
+ case "Event":
+ metadata.types.put(currentType.name, currentType);
+ currentType = null;
+ break;
+ case "Field":
+ currentType.fields.add(currentField);
+ currentField = null;
+ break;
+ }
+ }
+ }
+
+ static class Printer implements AutoCloseable {
+ final PrintStream out;
+ Printer(File outputDirectory, String filename) throws FileNotFoundException {
+ out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(outputDirectory, filename))));
+ write("/* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */");
+ write("");
+ }
+
+ void write(String text) {
+ out.print(text);
+ out.print("\n"); // Don't use Windows line endings
+ }
+
+ @Override
+ public void close() throws Exception {
+ out.close();
+ }
+ }
+
+ private static void printJfrPeriodicHpp(Metadata metadata, File outputDirectory) throws Exception {
+ try (Printer out = new Printer(outputDirectory, "jfrPeriodic.hpp")) {
+ out.write("#ifndef JFRFILES_JFRPERIODICEVENTSET_HPP");
+ out.write("#define JFRFILES_JFRPERIODICEVENTSET_HPP");
+ out.write("");
+ out.write("#include \"utilities/macros.hpp\"");
+ out.write("#if INCLUDE_JFR");
+ out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
+ out.write("#include \"memory/allocation.hpp\"");
+ out.write("");
+ out.write("class JfrPeriodicEventSet : public AllStatic {");
+ out.write(" public:");
+ out.write(" static void requestEvent(JfrEventId id) {");
+ out.write(" switch(id) {");
+ out.write(" ");
+ for (EventElement e : metadata.getPeriodicEvents()) {
+ out.write(" case Jfr" + e.name + "Event:");
+ out.write(" request" + e.name + "();");
+ out.write(" break;");
+ out.write(" ");
+ }
+ out.write(" default:");
+ out.write(" break;");
+ out.write(" }");
+ out.write(" }");
+ out.write("");
+ out.write(" private:");
+ out.write("");
+ for (EventElement e : metadata.getPeriodicEvents()) {
+ out.write(" static void request" + e.name + "(void);");
+ out.write("");
+ }
+ out.write("};");
+ out.write("");
+ out.write("#endif // INCLUDE_JFR");
+ out.write("#endif // JFRFILES_JFRPERIODICEVENTSET_HPP");
+ }
+ }
+
+ private static void printJfrEventControlHpp(Metadata metadata, File outputDirectory) throws Exception {
+ try (Printer out = new Printer(outputDirectory, "jfrEventControl.hpp")) {
+ out.write("#ifndef JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
+ out.write("#define JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
+ out.write("");
+ out.write("#include \"utilities/macros.hpp\"");
+ out.write("#if INCLUDE_JFR");
+ out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
+ out.write("");
+ out.write("/**");
+ out.write(" * Event setting. We add some padding so we can use our");
+ out.write(" * event IDs as indexes into this.");
+ out.write(" */");
+ out.write("");
+ out.write("struct jfrNativeEventSetting {");
+ out.write(" jlong threshold_ticks;");
+ out.write(" jlong cutoff_ticks;");
+ out.write(" u1 stacktrace;");
+ out.write(" u1 enabled;");
+ out.write(" u1 pad[6]; // Because GCC on linux ia32 at least tries to pack this.");
+ out.write("};");
+ out.write("");
+ out.write("union JfrNativeSettings {");
+ out.write(" // Array version.");
+ out.write(" jfrNativeEventSetting bits[MaxJfrEventId];");
+ out.write(" // Then, to make it easy to debug,");
+ out.write(" // add named struct members also.");
+ out.write(" struct {");
+ out.write(" jfrNativeEventSetting pad[NUM_RESERVED_EVENTS];");
+ for (TypeElement t : metadata.getEventsAndStructs()) {
+ out.write(" jfrNativeEventSetting " + t.name + ";");
+ }
+ out.write(" } ev;");
+ out.write("};");
+ out.write("");
+ out.write("#endif // INCLUDE_JFR");
+ out.write("#endif // JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
+ }
+ }
+
+ private static void printJfrEventIdsHpp(Metadata metadata, File outputDirectory) throws Exception {
+ try (Printer out = new Printer(outputDirectory, "jfrEventIds.hpp")) {
+ out.write("#ifndef JFRFILES_JFREVENTIDS_HPP");
+ out.write("#define JFRFILES_JFREVENTIDS_HPP");
+ out.write("");
+ out.write("#include \"utilities/macros.hpp\"");
+ out.write("#if INCLUDE_JFR");
+ out.write("#include \"jfrfiles/jfrTypes.hpp\"");
+ out.write("");
+ out.write("/**");
+ out.write(" * Enum of the event types in the JVM");
+ out.write(" */");
+ out.write("enum JfrEventId {");
+ out.write(" _jfreventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index.");
+ out.write(" ");
+ out.write(" // Events -> enum entry");
+ for (TypeElement t : metadata.getEventsAndStructs()) {
+ out.write(" Jfr" + t.name + "Event,");
+ }
+ out.write("");
+ out.write(" MaxJfrEventId");
+ out.write("};");
+ out.write("");
+ out.write("/**");
+ out.write(" * Struct types in the JVM");
+ out.write(" */");
+ out.write("enum JfrStructId {");
+ for (TypeElement t : metadata.getNonEventsAndNonStructs()) {
+ out.write(" Jfr" + t.name + "Struct,");
+ }
+ for (TypeElement t : metadata.getEventsAndStructs()) {
+ out.write(" Jfr" + t.name + "Struct,");
+ }
+ out.write("");
+ out.write(" MaxJfrStructId");
+ out.write("};");
+ out.write("");
+ out.write("typedef enum JfrEventId JfrEventId;");
+ out.write("typedef enum JfrStructId JfrStructId;");
+ out.write("");
+ out.write("#endif // INCLUDE_JFR");
+ out.write("#endif // JFRFILES_JFREVENTIDS_HPP");
+ }
+ }
+
+ private static void printJfrTypesHpp(Metadata metadata, File outputDirectory) throws Exception {
+ List<String> knownTypes = List.of("Thread", "StackTrace", "Class", "StackFrame");
+ try (Printer out = new Printer(outputDirectory, "jfrTypes.hpp")) {
+ out.write("#ifndef JFRFILES_JFRTYPES_HPP");
+ out.write("#define JFRFILES_JFRTYPES_HPP");
+ out.write("");
+ out.write("#include \"utilities/macros.hpp\"");
+ out.write("#if INCLUDE_JFR");
+ out.write("");
+ out.write("enum JfrTypeId {");
+ out.write(" TYPE_NONE = 0,");
+ out.write(" TYPE_CLASS = 20,");
+ out.write(" TYPE_STRING = 21,");
+ out.write(" TYPE_THREAD = 22,");
+ out.write(" TYPE_STACKTRACE = 23,");
+ out.write(" TYPE_BYTES = 24,");
+ out.write(" TYPE_EPOCHMILLIS = 25,");
+ out.write(" TYPE_MILLIS = 26,");
+ out.write(" TYPE_NANOS = 27,");
+ out.write(" TYPE_TICKS = 28,");
+ out.write(" TYPE_ADDRESS = 29,");
+ out.write(" TYPE_PERCENTAGE = 30,");
+ out.write(" TYPE_DUMMY,");
+ out.write(" TYPE_DUMMY_1,");
+ for (TypeElement type : metadata.getTypes()) {
+ if (!knownTypes.contains(type.name)) {
+ out.write(" TYPE_" + type.name.toUpperCase() + ",");
+ }
+ }
+ out.write("");
+ out.write(" NUM_JFR_TYPES,");
+ out.write(" TYPES_END = 255");
+ out.write("};");
+ out.write("");
+ out.write("enum ReservedEvent {");
+ out.write(" EVENT_METADATA,");
+ out.write(" EVENT_CHECKPOINT,");
+ out.write(" EVENT_BUFFERLOST,");
+ out.write(" NUM_RESERVED_EVENTS = TYPES_END");
+ out.write("};");
+ out.write("");
+ out.write("#endif // INCLUDE_JFR");
+ out.write("#endif // JFRFILES_JFRTYPES_HPP");
+ };
+ }
+
+ private static void printJfrEventClassesHpp(Metadata metadata, File outputDirectory) throws Exception {
+ try (Printer out = new Printer(outputDirectory, "jfrEventClasses.hpp")) {
+ out.write("#ifndef JFRFILES_JFREVENTCLASSES_HPP");
+ out.write("#define JFRFILES_JFREVENTCLASSES_HPP");
+ out.write("");
+ out.write("#include \"oops/klass.hpp\"");
+ out.write("#include \"jfrfiles/jfrTypes.hpp\"");
+ out.write("#include \"jfr/utilities/jfrTypes.hpp\"");
+ out.write("#include \"utilities/macros.hpp\"");
+ out.write("#include \"utilities/ticks.hpp\"");
+ out.write("#if INCLUDE_JFR");
+ out.write("#include \"jfr/recorder/service/jfrEvent.hpp\"");
+ out.write("/*");
+ out.write(" * Each event class has an assert member function verify() which is invoked");
+ out.write(" * just before the engine writes the event and its fields to the data stream.");
+ out.write(" * The purpose of verify() is to ensure that all fields in the event are initialized");
+ out.write(" * and set before attempting to commit.");
+ out.write(" *");
+ out.write(" * We enforce this requirement because events are generally stack allocated and therefore");
+ out.write(" * *not* initialized to default values. This prevents us from inadvertently committing");
+ out.write(" * uninitialized values to the data stream.");
+ out.write(" *");
+ out.write(" * The assert message contains both the index (zero based) as well as the name of the field.");
+ out.write(" */");
+ out.write("");
+ printTypes(out, metadata, false);
+ out.write("");
+ out.write("");
+ out.write("#else // !INCLUDE_JFR");
+ out.write("");
+ out.write("class JfrEvent {");
+ out.write(" public:");
+ out.write(" JfrEvent() {}");
+ out.write(" void set_starttime(const Ticks&) const {}");
+ out.write(" void set_endtime(const Ticks&) const {}");
+ out.write(" bool should_commit() const { return false; }");
+ out.write(" static bool is_enabled() { return false; }");
+ out.write(" void commit() {}");
+ out.write("};");
+ out.write("");
+ printTypes(out, metadata, true);
+ out.write("");
+ out.write("");
+ out.write("#endif // INCLUDE_JFR");
+ out.write("#endif // JFRFILES_JFREVENTCLASSES_HPP");
+ }
+ }
+
+ private static void printTypes(Printer out, Metadata metadata, boolean empty) {
+ for (TypeElement t : metadata.getStructs()) {
+ if (empty) {
+ out.write("");
+ printEmptyType(out, t);
+ } else {
+ printType(out, t);
+ }
+ out.write("");
+ }
+ for (EventElement e : metadata.getEvents()) {
+ if (empty) {
+ printEmptyEvent(out, e);
+ } else {
+ printEvent(out, e);
+ }
+ out.write("");
+ }
+ }
+
+ private static void printEmptyEvent(Printer out, EventElement event) {
+ out.write("class Event" + event.name + " : public JfrEvent");
+ out.write("{");
+ out.write(" public:");
+ out.write(" Event" + event.name + "(EventStartTime ignore=TIMED) {}");
+ if (event.startTime) {
+ StringJoiner sj = new StringJoiner(",\n ");
+ for (FieldElement f : event.fields) {
+ sj.add(f.getParameterType());
+ }
+ out.write(" Event" + event.name + "(");
+ out.write(" " + sj.toString() + ") { }");
+ }
+ for (FieldElement f : event.fields) {
+ out.write(" void set_" + f.name + "(" + f.getParameterType() + ") { }");
+ }
+ out.write("};");
+ }
+
+ private static void printEmptyType(Printer out, TypeElement t) {
+ out.write("struct JfrStruct" + t.name);
+ out.write("{");
+ out.write(" public:");
+ for (FieldElement f : t.fields) {
+ out.write(" void set_" + f.name + "(" + f.getParameterType() + ") { }");
+ }
+ out.write("};");
+ }
+
+ private static void printType(Printer out, TypeElement t) {
+ out.write("struct JfrStruct" + t.name);
+ out.write("{");
+ out.write(" private:");
+ for (FieldElement f : t.fields) {
+ printField(out, f);
+ }
+ out.write("");
+ out.write(" public:");
+ for (FieldElement f : t.fields) {
+ printTypeSetter(out, f);
+ }
+ out.write("");
+ printWriteData(out, t.fields);
+ out.write("};");
+ out.write("");
+ }
+
+ private static void printEvent(Printer out, EventElement event) {
+ out.write("class Event" + event.name + " : public JfrEvent<Event" + event.name + ">");
+ out.write("{");
+ out.write(" private:");
+ for (FieldElement f : event.fields) {
+ printField(out, f);
+ }
+ out.write("");
+ out.write(" public:");
+ out.write(" static const bool hasThread = " + event.thread + ";");
+ out.write(" static const bool hasStackTrace = " + event.stackTrace + ";");
+ out.write(" static const bool isInstant = " + !event.startTime + ";");
+ out.write(" static const bool hasCutoff = " + event.cutoff + ";");
+ out.write(" static const bool isRequestable = " + event.periodic + ";");
+ out.write(" static const JfrEventId eventId = Jfr" + event.name + "Event;");
+ out.write("");
+ out.write(" Event" + event.name + "(EventStartTime timing=TIMED) : JfrEvent<Event" + event.name + ">(timing) {}");
+ out.write("");
+ int index = 0;
+ for (FieldElement f : event.fields) {
+ out.write(" void set_" + f.name + "(" + f.getParameterType() + " " + f.getParameterName() + ") {");
+ out.write(" this->_" + f.name + " = " + f.getParameterName() + ";");
+ out.write(" DEBUG_ONLY(set_field_bit(" + index++ + "));");
+ out.write(" }");
+ }
+ out.write("");
+ printWriteData(out, event.fields);
+ out.write("");
+ out.write(" using JfrEvent<Event" + event.name + ">::commit; // else commit() is hidden by overloaded versions in this class");
+ printConstructor2(out, event);
+ printCommitMethod(out, event);
+ printVerify(out, event.fields);
+ out.write("};");
+ }
+
+ private static void printWriteData(Printer out, List<FieldElement> fields) {
+ out.write(" template <typename Writer>");
+ out.write(" void writeData(Writer& w) {");
+ for (FieldElement field : fields) {
+ if (field.struct) {
+ out.write(" _" + field.name + ".writeData(w);");
+ } else {
+ out.write(" w.write(_" + field.name + ");");
+ }
+ }
+ out.write(" }");
+ }
+
+ private static void printTypeSetter(Printer out, FieldElement field) {
+ out.write(" void set_" + field.name + "(" + field.getParameterType() + " new_value) { this->_" + field.name + " = new_value; }");
+ }
+
+ private static void printVerify(Printer out, List<FieldElement> fields) {
+ out.write("");
+ out.write("#ifdef ASSERT");
+ out.write(" void verify() const {");
+ int index = 0;
+ for (FieldElement f : fields) {
+ out.write(" assert(verify_field_bit(" + index++ + "), \"Attempting to write an uninitialized event field: %s\", \"_" + f.name + "\");");
+ }
+ out.write(" }");
+ out.write("#endif");
+ }
+
+ private static void printCommitMethod(Printer out, EventElement event) {
+ if (event.startTime) {
+ StringJoiner sj = new StringJoiner(",\n ");
+ for (FieldElement f : event.fields) {
+ sj.add(f.getParameterType() + " " + f.name);
+ }
+ out.write("");
+ out.write(" void commit(" + sj.toString() + ") {");
+ out.write(" if (should_commit()) {");
+ for (FieldElement f : event.fields) {
+ out.write(" set_" + f.name + "(" + f.name + ");");
+ }
+ out.write(" commit();");
+ out.write(" }");
+ out.write(" }");
+ }
+ out.write("");
+ StringJoiner sj = new StringJoiner(",\n ");
+ if (event.startTime) {
+ sj.add("const Ticks& startTicks");
+ sj.add("const Ticks& endTicks");
+ }
+ for (FieldElement f : event.fields) {
+ sj.add(f.getParameterType() + " " + f.name);
+ }
+ out.write(" static void commit(" + sj.toString() + ") {");
+ out.write(" Event" + event.name + " me(UNTIMED);");
+ out.write("");
+ out.write(" if (me.should_commit()) {");
+ if (event.startTime) {
+ out.write(" me.set_starttime(startTicks);");
+ out.write(" me.set_endtime(endTicks);");
+ }
+ for (FieldElement f : event.fields) {
+ out.write(" me.set_" + f.name + "(" + f.name + ");");
+ }
+ out.write(" me.commit();");
+ out.write(" }");
+ out.write(" }");
+ }
+
+ private static void printConstructor2(Printer out, EventElement event) {
+ if (!event.startTime) {
+ out.write("");
+ out.write("");
+ }
+ if (event.startTime) {
+ out.write("");
+ out.write(" Event" + event.name + "(");
+ StringJoiner sj = new StringJoiner(",\n ");
+ for (FieldElement f : event.fields) {
+ sj.add(f.getParameterType() + " " + f.name);
+ }
+ out.write(" " + sj.toString() + ") : JfrEvent<Event" + event.name + ">(TIMED) {");
+ out.write(" if (should_commit()) {");
+ for (FieldElement f : event.fields) {
+ out.write(" set_" + f.name + "(" + f.name + ");");
+ }
+ out.write(" }");
+ out.write(" }");
+ }
+ }
+
+ private static void printField(Printer out, FieldElement field) {
+ out.write(" " + field.getFieldType() + " _" + field.name + ";");
+ }
+}
--- a/src/hotspot/share/jfr/metadata/GenerateJfrFiles.java Fri May 25 09:35:02 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,693 +0,0 @@
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.StringJoiner;
-import java.util.function.Predicate;
-
-import javax.xml.XMLConstants;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.validation.SchemaFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.helpers.DefaultHandler;
-
-public class GenerateJfrFiles {
-
- public static void main(String... args) throws Exception {
- if (args.length != 3) {
- System.err.println("Incorrect number of command line arguments.");
- System.err.println("Usage:");
- System.err.println("java GenerateJfrFiles[.java] <path-to-metadata.xml> <path-to-metadata.xsd> <output-directory>");
- System.exit(1);
- }
- try {
- File metadataXml = new File(args[0]);
- File metadataSchema = new File(args[1]);
- File outputDirectory = new File(args[2]);
-
- Metadata metadata = new Metadata(metadataXml, metadataSchema);
- metadata.verify();
- metadata.wireUpTypes();
-
- printJfrPeriodicHpp(metadata, outputDirectory);
- printJfrEventIdsHpp(metadata, outputDirectory);
- printJfrEventControlHpp(metadata, outputDirectory);
- printJfrTypesHpp(metadata, outputDirectory);
- printJfrEventClassesHpp(metadata, outputDirectory);
-
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
- }
-
- static class XmlType {
- final String fieldType;
- final String parameterType;
- XmlType(String fieldType, String parameterType) {
- this.fieldType = fieldType;
- this.parameterType = parameterType;
- }
- }
-
- static class TypeElement {
- List<FieldElement> fields = new ArrayList<>();
- String name;
- String fieldType;
- String parameterType;
- boolean supportStruct;
- }
-
- static class Metadata {
- final Map<String, TypeElement> types = new LinkedHashMap<>();
- final Map<String, XmlType> xmlTypes = new HashMap<>();
- Metadata(File metadataXml, File metadataSchema) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException {
- SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
- SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setSchema(schemaFactory.newSchema(metadataSchema));
- SAXParser sp = factory.newSAXParser();
- sp.parse(metadataXml, new MetadataHandler(this));
- }
-
- List<EventElement> getEvents() {
- return getList(t -> t.getClass() == EventElement.class);
- }
-
- List<TypeElement> getEventsAndStructs() {
- return getList(t -> t.getClass() == EventElement.class || t.supportStruct);
- }
-
- List<TypeElement> getTypesAndStructs() {
- return getList(t -> t.getClass() == TypeElement.class || t.supportStruct);
- }
-
- @SuppressWarnings("unchecked")
- <T> List<T> getList(Predicate<? super TypeElement> pred) {
- List<T> result = new ArrayList<>(types.size());
- for (TypeElement t : types.values()) {
- if (pred.test(t)) {
- result.add((T) t);
- }
- }
- return result;
- }
-
- List<EventElement> getPeriodicEvents() {
- return getList(t -> t.getClass() == EventElement.class && ((EventElement) t).periodic);
- }
-
- List<TypeElement> getNonEventsAndNonStructs() {
- return getList(t -> t.getClass() != EventElement.class && !t.supportStruct);
- }
-
- List<TypeElement> getTypes() {
- return getList(t -> t.getClass() == TypeElement.class && !t.supportStruct);
- }
-
- List<TypeElement> getStructs() {
- return getList(t -> t.getClass() == TypeElement.class && t.supportStruct);
- }
-
- void verify() {
- for (TypeElement t : types.values()) {
- for (FieldElement f : t.fields) {
- if (!xmlTypes.containsKey(f.typeName)) { // ignore primitives
- if (!types.containsKey(f.typeName)) {
- throw new IllegalStateException("Could not find definition of type '" + f.typeName + "' used by " + t.name + "#" + f.name);
- }
- }
- }
- }
- }
-
- void wireUpTypes() {
- for (TypeElement t : types.values()) {
- for (FieldElement f : t.fields) {
- TypeElement type = types.get(f.typeName);
- if (f.struct) {
- type.supportStruct = true;
- }
- f.type = type;
- }
- }
- }
- }
-
- static class EventElement extends TypeElement {
- String representation;
- boolean thread;
- boolean stackTrace;
- boolean startTime;
- boolean periodic;
- boolean cutoff;
- }
-
- static class FieldElement {
- final Metadata metadata;
- TypeElement type;
- String name;
- String typeName;
- boolean struct;
-
- FieldElement(Metadata metadata) {
- this.metadata = metadata;
- }
-
- String getParameterType() {
- if (struct) {
- return "const JfrStruct" + typeName + "&";
- }
- XmlType xmlType = metadata.xmlTypes.get(typeName);
- if (xmlType != null) {
- return xmlType.parameterType;
- }
- return type != null ? "u8" : typeName;
- }
-
- String getParameterName() {
- return struct ? "value" : "new_value";
- }
-
- String getFieldType() {
- if (struct) {
- return "JfrStruct" + typeName;
- }
- XmlType xmlType = metadata.xmlTypes.get(typeName);
- if (xmlType != null) {
- return xmlType.fieldType;
- }
- return type != null ? "u8" : typeName;
- }
- }
-
- static class MetadataHandler extends DefaultHandler {
- final Metadata metadata;
- FieldElement currentField;
- TypeElement currentType;
- MetadataHandler(Metadata metadata) {
- this.metadata = metadata;
- }
- @Override
- public void error(SAXParseException e) throws SAXException {
- throw e;
- }
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
- switch (qName) {
- case "XmlType":
- String name = attributes.getValue("name");
- String parameterType = attributes.getValue("parameterType");
- String fieldType = attributes.getValue("fieldType");
- metadata.xmlTypes.put(name, new XmlType(fieldType, parameterType));
- break;
- case "Type":
- currentType = new TypeElement();
- currentType.name = attributes.getValue("name");
- break;
- case "Event":
- EventElement eventtType = new EventElement();
- eventtType.name = attributes.getValue("name");
- eventtType.thread = getBoolean(attributes, "thread", false);
- eventtType.stackTrace = getBoolean(attributes, "stackTrace", false);
- eventtType.startTime = getBoolean(attributes, "startTime", true);
- eventtType.periodic = attributes.getValue("period") != null;
- eventtType.cutoff = getBoolean(attributes, "cutoff", false);
- currentType = eventtType;
- break;
- case "Field":
- currentField = new FieldElement(metadata);
- currentField.struct = getBoolean(attributes, "struct", false);
- currentField.name = attributes.getValue("name");
- currentField.typeName = attributes.getValue("type");
- break;
- }
- }
-
- private boolean getBoolean(Attributes attributes, String name, boolean defaultValue) {
- String value = attributes.getValue(name);
- return value == null ? defaultValue : Boolean.valueOf(value);
- }
-
- @Override
- public void endElement(String uri, String localName, String qName) {
- switch (qName) {
- case "Type":
- case "Event":
- metadata.types.put(currentType.name, currentType);
- currentType = null;
- break;
- case "Field":
- currentType.fields.add(currentField);
- currentField = null;
- break;
- }
- }
- }
-
- static class Printer implements AutoCloseable {
- final PrintStream out;
- Printer(File outputDirectory, String filename) throws FileNotFoundException {
- out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(outputDirectory, filename))));
- write("/* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */");
- write("");
- }
-
- void write(String text) {
- out.print(text);
- out.print("\n"); // Don't use Windows line endings
- }
-
- @Override
- public void close() throws Exception {
- out.close();
- }
- }
-
- private static void printJfrPeriodicHpp(Metadata metadata, File outputDirectory) throws Exception {
- try (Printer out = new Printer(outputDirectory, "jfrPeriodic.hpp")) {
- out.write("#ifndef JFRFILES_JFRPERIODICEVENTSET_HPP");
- out.write("#define JFRFILES_JFRPERIODICEVENTSET_HPP");
- out.write("");
- out.write("#include \"utilities/macros.hpp\"");
- out.write("#if INCLUDE_JFR");
- out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
- out.write("#include \"memory/allocation.hpp\"");
- out.write("");
- out.write("class JfrPeriodicEventSet : public AllStatic {");
- out.write(" public:");
- out.write(" static void requestEvent(JfrEventId id) {");
- out.write(" switch(id) {");
- out.write(" ");
- for (EventElement e : metadata.getPeriodicEvents()) {
- out.write(" case Jfr" + e.name + "Event:");
- out.write(" request" + e.name + "();");
- out.write(" break;");
- out.write(" ");
- }
- out.write(" default:");
- out.write(" break;");
- out.write(" }");
- out.write(" }");
- out.write("");
- out.write(" private:");
- out.write("");
- for (EventElement e : metadata.getPeriodicEvents()) {
- out.write(" static void request" + e.name + "(void);");
- out.write("");
- }
- out.write("};");
- out.write("");
- out.write("#endif // INCLUDE_JFR");
- out.write("#endif // JFRFILES_JFRPERIODICEVENTSET_HPP");
- }
- }
-
- private static void printJfrEventControlHpp(Metadata metadata, File outputDirectory) throws Exception {
- try (Printer out = new Printer(outputDirectory, "jfrEventControl.hpp")) {
- out.write("#ifndef JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
- out.write("#define JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
- out.write("");
- out.write("#include \"utilities/macros.hpp\"");
- out.write("#if INCLUDE_JFR");
- out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
- out.write("");
- out.write("/**");
- out.write(" * Event setting. We add some padding so we can use our");
- out.write(" * event IDs as indexes into this.");
- out.write(" */");
- out.write("");
- out.write("struct jfrNativeEventSetting {");
- out.write(" jlong threshold_ticks;");
- out.write(" jlong cutoff_ticks;");
- out.write(" u1 stacktrace;");
- out.write(" u1 enabled;");
- out.write(" u1 pad[6]; // Because GCC on linux ia32 at least tries to pack this.");
- out.write("};");
- out.write("");
- out.write("union JfrNativeSettings {");
- out.write(" // Array version.");
- out.write(" jfrNativeEventSetting bits[MaxJfrEventId];");
- out.write(" // Then, to make it easy to debug,");
- out.write(" // add named struct members also.");
- out.write(" struct {");
- out.write(" jfrNativeEventSetting pad[NUM_RESERVED_EVENTS];");
- for (TypeElement t : metadata.getEventsAndStructs()) {
- out.write(" jfrNativeEventSetting " + t.name + ";");
- }
- out.write(" } ev;");
- out.write("};");
- out.write("");
- out.write("#endif // INCLUDE_JFR");
- out.write("#endif // JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
- }
- }
-
- private static void printJfrEventIdsHpp(Metadata metadata, File outputDirectory) throws Exception {
- try (Printer out = new Printer(outputDirectory, "jfrEventIds.hpp")) {
- out.write("#ifndef JFRFILES_JFREVENTIDS_HPP");
- out.write("#define JFRFILES_JFREVENTIDS_HPP");
- out.write("");
- out.write("#include \"utilities/macros.hpp\"");
- out.write("#if INCLUDE_JFR");
- out.write("#include \"jfrfiles/jfrTypes.hpp\"");
- out.write("");
- out.write("/**");
- out.write(" * Enum of the event types in the JVM");
- out.write(" */");
- out.write("enum JfrEventId {");
- out.write(" _jfreventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index.");
- out.write(" ");
- out.write(" // Events -> enum entry");
- for (TypeElement t : metadata.getEventsAndStructs()) {
- out.write(" Jfr" + t.name + "Event,");
- }
- out.write("");
- out.write(" MaxJfrEventId");
- out.write("};");
- out.write("");
- out.write("/**");
- out.write(" * Struct types in the JVM");
- out.write(" */");
- out.write("enum JfrStructId {");
- for (TypeElement t : metadata.getNonEventsAndNonStructs()) {
- out.write(" Jfr" + t.name + "Struct,");
- }
- for (TypeElement t : metadata.getEventsAndStructs()) {
- out.write(" Jfr" + t.name + "Struct,");
- }
- out.write("");
- out.write(" MaxJfrStructId");
- out.write("};");
- out.write("");
- out.write("typedef enum JfrEventId JfrEventId;");
- out.write("typedef enum JfrStructId JfrStructId;");
- out.write("");
- out.write("#endif // INCLUDE_JFR");
- out.write("#endif // JFRFILES_JFREVENTIDS_HPP");
- }
- }
-
- private static void printJfrTypesHpp(Metadata metadata, File outputDirectory) throws Exception {
- List<String> knownTypes = List.of("Thread", "StackTrace", "Class", "StackFrame");
- try (Printer out = new Printer(outputDirectory, "jfrTypes.hpp")) {
- out.write("#ifndef JFRFILES_JFRTYPES_HPP");
- out.write("#define JFRFILES_JFRTYPES_HPP");
- out.write("");
- out.write("#include \"utilities/macros.hpp\"");
- out.write("#if INCLUDE_JFR");
- out.write("");
- out.write("enum JfrTypeId {");
- out.write(" TYPE_NONE = 0,");
- out.write(" TYPE_CLASS = 20,");
- out.write(" TYPE_STRING = 21,");
- out.write(" TYPE_THREAD = 22,");
- out.write(" TYPE_STACKTRACE = 23,");
- out.write(" TYPE_BYTES = 24,");
- out.write(" TYPE_EPOCHMILLIS = 25,");
- out.write(" TYPE_MILLIS = 26,");
- out.write(" TYPE_NANOS = 27,");
- out.write(" TYPE_TICKS = 28,");
- out.write(" TYPE_ADDRESS = 29,");
- out.write(" TYPE_PERCENTAGE = 30,");
- out.write(" TYPE_DUMMY,");
- out.write(" TYPE_DUMMY_1,");
- for (TypeElement type : metadata.getTypes()) {
- if (!knownTypes.contains(type.name)) {
- out.write(" TYPE_" + type.name.toUpperCase() + ",");
- }
- }
- out.write("");
- out.write(" NUM_JFR_TYPES,");
- out.write(" TYPES_END = 255");
- out.write("};");
- out.write("");
- out.write("enum ReservedEvent {");
- out.write(" EVENT_METADATA,");
- out.write(" EVENT_CHECKPOINT,");
- out.write(" EVENT_BUFFERLOST,");
- out.write(" NUM_RESERVED_EVENTS = TYPES_END");
- out.write("};");
- out.write("");
- out.write("#endif // INCLUDE_JFR");
- out.write("#endif // JFRFILES_JFRTYPES_HPP");
- };
- }
-
- private static void printJfrEventClassesHpp(Metadata metadata, File outputDirectory) throws Exception {
- try (Printer out = new Printer(outputDirectory, "jfrEventClasses.hpp")) {
- out.write("#ifndef JFRFILES_JFREVENTCLASSES_HPP");
- out.write("#define JFRFILES_JFREVENTCLASSES_HPP");
- out.write("");
- out.write("#include \"oops/klass.hpp\"");
- out.write("#include \"jfrfiles/jfrTypes.hpp\"");
- out.write("#include \"jfr/utilities/jfrTypes.hpp\"");
- out.write("#include \"utilities/macros.hpp\"");
- out.write("#include \"utilities/ticks.hpp\"");
- out.write("#if INCLUDE_JFR");
- out.write("#include \"jfr/recorder/service/jfrEvent.hpp\"");
- out.write("/*");
- out.write(" * Each event class has an assert member function verify() which is invoked");
- out.write(" * just before the engine writes the event and its fields to the data stream.");
- out.write(" * The purpose of verify() is to ensure that all fields in the event are initialized");
- out.write(" * and set before attempting to commit.");
- out.write(" *");
- out.write(" * We enforce this requirement because events are generally stack allocated and therefore");
- out.write(" * *not* initialized to default values. This prevents us from inadvertently committing");
- out.write(" * uninitialized values to the data stream.");
- out.write(" *");
- out.write(" * The assert message contains both the index (zero based) as well as the name of the field.");
- out.write(" */");
- out.write("");
- printTypes(out, metadata, false);
- out.write("");
- out.write("");
- out.write("#else // !INCLUDE_JFR");
- out.write("");
- out.write("class JfrEvent {");
- out.write(" public:");
- out.write(" JfrEvent() {}");
- out.write(" void set_starttime(const Ticks&) const {}");
- out.write(" void set_endtime(const Ticks&) const {}");
- out.write(" bool should_commit() const { return false; }");
- out.write(" static bool is_enabled() { return false; }");
- out.write(" void commit() {}");
- out.write("};");
- out.write("");
- printTypes(out, metadata, true);
- out.write("");
- out.write("");
- out.write("#endif // INCLUDE_JFR");
- out.write("#endif // JFRFILES_JFREVENTCLASSES_HPP");
- }
- }
-
- private static void printTypes(Printer out, Metadata metadata, boolean empty) {
- for (TypeElement t : metadata.getStructs()) {
- if (empty) {
- out.write("");
- printEmptyType(out, t);
- } else {
- printType(out, t);
- }
- out.write("");
- }
- for (EventElement e : metadata.getEvents()) {
- if (empty) {
- printEmptyEvent(out, e);
- } else {
- printEvent(out, e);
- }
- out.write("");
- }
- }
-
- private static void printEmptyEvent(Printer out, EventElement event) {
- out.write("class Event" + event.name + " : public JfrEvent");
- out.write("{");
- out.write(" public:");
- out.write(" Event" + event.name + "(EventStartTime ignore=TIMED) {}");
- if (event.startTime) {
- StringJoiner sj = new StringJoiner(",\n ");
- for (FieldElement f : event.fields) {
- sj.add(f.getParameterType());
- }
- out.write(" Event" + event.name + "(");
- out.write(" " + sj.toString() + ") { }");
- }
- for (FieldElement f : event.fields) {
- out.write(" void set_" + f.name + "(" + f.getParameterType() + ") { }");
- }
- out.write("};");
- }
-
- private static void printEmptyType(Printer out, TypeElement t) {
- out.write("struct JfrStruct" + t.name);
- out.write("{");
- out.write(" public:");
- for (FieldElement f : t.fields) {
- out.write(" void set_" + f.name + "(" + f.getParameterType() + ") { }");
- }
- out.write("};");
- }
-
- private static void printType(Printer out, TypeElement t) {
- out.write("struct JfrStruct" + t.name);
- out.write("{");
- out.write(" private:");
- for (FieldElement f : t.fields) {
- printField(out, f);
- }
- out.write("");
- out.write(" public:");
- for (FieldElement f : t.fields) {
- printTypeSetter(out, f);
- }
- out.write("");
- printWriteData(out, t.fields);
- out.write("};");
- out.write("");
- }
-
- private static void printEvent(Printer out, EventElement event) {
- out.write("class Event" + event.name + " : public JfrEvent<Event" + event.name + ">");
- out.write("{");
- out.write(" private:");
- for (FieldElement f : event.fields) {
- printField(out, f);
- }
- out.write("");
- out.write(" public:");
- out.write(" static const bool hasThread = " + event.thread + ";");
- out.write(" static const bool hasStackTrace = " + event.stackTrace + ";");
- out.write(" static const bool isInstant = " + !event.startTime + ";");
- out.write(" static const bool hasCutoff = " + event.cutoff + ";");
- out.write(" static const bool isRequestable = " + event.periodic + ";");
- out.write(" static const JfrEventId eventId = Jfr" + event.name + "Event;");
- out.write("");
- out.write(" Event" + event.name + "(EventStartTime timing=TIMED) : JfrEvent<Event" + event.name + ">(timing) {}");
- out.write("");
- int index = 0;
- for (FieldElement f : event.fields) {
- out.write(" void set_" + f.name + "(" + f.getParameterType() + " " + f.getParameterName() + ") {");
- out.write(" this->_" + f.name + " = " + f.getParameterName() + ";");
- out.write(" DEBUG_ONLY(set_field_bit(" + index++ + "));");
- out.write(" }");
- }
- out.write("");
- printWriteData(out, event.fields);
- out.write("");
- out.write(" using JfrEvent<Event" + event.name + ">::commit; // else commit() is hidden by overloaded versions in this class");
- printConstructor2(out, event);
- printCommitMethod(out, event);
- printVerify(out, event.fields);
- out.write("};");
- }
-
- private static void printWriteData(Printer out, List<FieldElement> fields) {
- out.write(" template <typename Writer>");
- out.write(" void writeData(Writer& w) {");
- for (FieldElement field : fields) {
- if (field.struct) {
- out.write(" _" + field.name + ".writeData(w);");
- } else {
- out.write(" w.write(_" + field.name + ");");
- }
- }
- out.write(" }");
- }
-
- private static void printTypeSetter(Printer out, FieldElement field) {
- out.write(" void set_" + field.name + "(" + field.getParameterType() + " new_value) { this->_" + field.name + " = new_value; }");
- }
-
- private static void printVerify(Printer out, List<FieldElement> fields) {
- out.write("");
- out.write("#ifdef ASSERT");
- out.write(" void verify() const {");
- int index = 0;
- for (FieldElement f : fields) {
- out.write(" assert(verify_field_bit(" + index++ + "), \"Attempting to write an uninitialized event field: %s\", \"_" + f.name + "\");");
- }
- out.write(" }");
- out.write("#endif");
- }
-
- private static void printCommitMethod(Printer out, EventElement event) {
- if (event.startTime) {
- StringJoiner sj = new StringJoiner(",\n ");
- for (FieldElement f : event.fields) {
- sj.add(f.getParameterType() + " " + f.name);
- }
- out.write("");
- out.write(" void commit(" + sj.toString() + ") {");
- out.write(" if (should_commit()) {");
- for (FieldElement f : event.fields) {
- out.write(" set_" + f.name + "(" + f.name + ");");
- }
- out.write(" commit();");
- out.write(" }");
- out.write(" }");
- }
- out.write("");
- StringJoiner sj = new StringJoiner(",\n ");
- if (event.startTime) {
- sj.add("const Ticks& startTicks");
- sj.add("const Ticks& endTicks");
- }
- for (FieldElement f : event.fields) {
- sj.add(f.getParameterType() + " " + f.name);
- }
- out.write(" static void commit(" + sj.toString() + ") {");
- out.write(" Event" + event.name + " me(UNTIMED);");
- out.write("");
- out.write(" if (me.should_commit()) {");
- if (event.startTime) {
- out.write(" me.set_starttime(startTicks);");
- out.write(" me.set_endtime(endTicks);");
- }
- for (FieldElement f : event.fields) {
- out.write(" me.set_" + f.name + "(" + f.name + ");");
- }
- out.write(" me.commit();");
- out.write(" }");
- out.write(" }");
- }
-
- private static void printConstructor2(Printer out, EventElement event) {
- if (!event.startTime) {
- out.write("");
- out.write("");
- }
- if (event.startTime) {
- out.write("");
- out.write(" Event" + event.name + "(");
- StringJoiner sj = new StringJoiner(",\n ");
- for (FieldElement f : event.fields) {
- sj.add(f.getParameterType() + " " + f.name);
- }
- out.write(" " + sj.toString() + ") : JfrEvent<Event" + event.name + ">(TIMED) {");
- out.write(" if (should_commit()) {");
- for (FieldElement f : event.fields) {
- out.write(" set_" + f.name + "(" + f.name + ");");
- }
- out.write(" }");
- out.write(" }");
- }
- }
-
- private static void printField(Printer out, FieldElement field) {
- out.write(" " + field.getFieldType() + " _" + field.name + ";");
- }
-}