001/*
002 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package jdk.internal.jvmci.hotspot.jfr.events;
024
025import java.net.*;
026
027import jdk.internal.jvmci.hotspot.*;
028import jdk.internal.jvmci.hotspot.events.*;
029import jdk.internal.jvmci.hotspot.events.EmptyEventProvider.*;
030import jdk.internal.jvmci.service.*;
031
032import com.oracle.jrockit.jfr.*;
033
034/**
035 * A JFR implementation for {@link EventProvider}. This implementation is used when Flight Recorder
036 * is turned on.
037 */
038@ServiceProvider(EventProvider.class)
039public final class JFREventProvider implements EventProvider {
040
041    private final boolean enabled;
042
043    @SuppressWarnings("deprecation")
044    public JFREventProvider() {
045        enabled = HotSpotJVMCIRuntime.runtime().getConfig().flightRecorder;
046        if (enabled) {
047            try {
048                /*
049                 * The "HotSpot JVM" producer is a native producer and we cannot use it. So we
050                 * create our own. This has the downside that Mission Control is confused and
051                 * doesn't show JVMCI events in the "Code" tab. There are plans to revise the JFR
052                 * code for JDK 9.
053                 */
054                Producer producer = new Producer("HotSpot JVM", "Oracle Hotspot JVM", "http://www.oracle.com/hotspot/jvm/");
055                producer.register();
056                // Register event classes with Producer.
057                for (Class<?> c : JFREventProvider.class.getDeclaredClasses()) {
058                    if (c.isAnnotationPresent(EventDefinition.class)) {
059                        assert com.oracle.jrockit.jfr.InstantEvent.class.isAssignableFrom(c) : c;
060                        registerEvent(producer, c);
061                    }
062                }
063            } catch (URISyntaxException e) {
064                throw new InternalError(e);
065            }
066        }
067    }
068
069    /**
070     * Register an event class with the {@link Producer}.
071     *
072     * @param c event class
073     * @return the {@link EventToken event token}
074     */
075    @SuppressWarnings({"deprecation", "javadoc", "unchecked"})
076    private static EventToken registerEvent(Producer producer, Class<?> c) {
077        try {
078            return producer.addEvent((Class<? extends com.oracle.jrockit.jfr.InstantEvent>) c);
079        } catch (InvalidEventDefinitionException | InvalidValueException e) {
080            throw new InternalError(e);
081        }
082    }
083
084    public CompilationEvent newCompilationEvent() {
085        if (enabled) {
086            return new JFRCompilationEvent();
087        }
088        return new EmptyCompilationEvent();
089    }
090
091    /**
092     * A JFR compilation event.
093     *
094     * <p>
095     * See: event {@code Compilation} in {@code src/share/vm/trace/trace.xml}
096     */
097    @SuppressWarnings("deprecation")
098    @EventDefinition(name = "Compilation", path = "vm/compiler/compilation")
099    public static class JFRCompilationEvent extends com.oracle.jrockit.jfr.DurationEvent implements CompilationEvent {
100
101        /*
102         * FIXME method should be a Method* but we can't express that in Java.
103         */
104        @ValueDefinition(name = "Java Method") public String method;
105        @ValueDefinition(name = "Compilation ID", relationKey = "COMP_ID") public int compileId;
106        @ValueDefinition(name = "Compilation Level") public short compileLevel;
107        @ValueDefinition(name = "Succeeded") public boolean succeeded;
108        @ValueDefinition(name = "On Stack Replacement") public boolean isOsr;
109        @ValueDefinition(name = "Compiled Code Size", contentType = ContentType.Bytes) public int codeSize;
110        @ValueDefinition(name = "Inlined Code Size", contentType = ContentType.Bytes) public int inlinedBytes;
111
112        public void setMethod(String method) {
113            this.method = method;
114        }
115
116        public void setCompileId(int id) {
117            this.compileId = id;
118        }
119
120        public void setCompileLevel(int compileLevel) {
121            this.compileLevel = (short) compileLevel;
122        }
123
124        public void setSucceeded(boolean succeeded) {
125            this.succeeded = succeeded;
126        }
127
128        public void setIsOsr(boolean isOsr) {
129            this.isOsr = isOsr;
130        }
131
132        public void setCodeSize(int codeSize) {
133            this.codeSize = codeSize;
134        }
135
136        public void setInlinedBytes(int inlinedBytes) {
137            this.inlinedBytes = inlinedBytes;
138        }
139    }
140
141    public CompilerFailureEvent newCompilerFailureEvent() {
142        if (enabled) {
143            return new JFRCompilerFailureEvent();
144        }
145        return new EmptyCompilerFailureEvent();
146    }
147
148    /**
149     * A JFR compiler failure event.
150     *
151     * <p>
152     * See: event {@code CompilerFailure} in {@code src/share/vm/trace/trace.xml}
153     */
154    @SuppressWarnings("deprecation")
155    @EventDefinition(name = "Compilation Failure", path = "vm/compiler/failure")
156    public static class JFRCompilerFailureEvent extends com.oracle.jrockit.jfr.InstantEvent implements CompilerFailureEvent {
157
158        @ValueDefinition(name = "Compilation ID", relationKey = "COMP_ID") public int compileId;
159        @ValueDefinition(name = "Message", description = "The failure message") public String failure;
160
161        public void setCompileId(int id) {
162            this.compileId = id;
163        }
164
165        public void setMessage(String message) {
166            this.failure = message;
167        }
168    }
169
170}