# HG changeset patch # User twisti # Date 1400160757 -7200 # Node ID 7340fe377764125191c9d90fefc4f4dda2206a78 # Parent 50fbda571d99cf275d2b1c0a7c55e3e82ac7f79e added Java Flight Recorder (JFR) event support diff -r 50fbda571d99 -r 7340fe377764 graal/com.oracle.graal.hotspot.jfr/src/com/oracle/graal/hotspot/jfr/events/JFREventProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.jfr/src/com/oracle/graal/hotspot/jfr/events/JFREventProvider.java Thu May 15 15:32:37 2014 +0200 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.jfr.events; + +import java.net.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.hotspot.events.*; +import com.oracle.jrockit.jfr.*; + +/** + * A JFR implementation for {@link EventProvider}. This implementation is used when Flight Recorder + * is turned on. + */ +@ServiceProvider(EventProvider.class) +public final class JFREventProvider implements EventProvider { + + @SuppressWarnings("deprecation") private final Producer producer; + + @SuppressWarnings("deprecation") + public JFREventProvider() { + try { + /* + * The "HotSpot JVM" producer is a native producer and we cannot use it. So we create + * our own. This has the downside that Mission Control is confused and doesn't show + * Graal's events in the "Code" tab. There are plans to revise the JFR code for JDK 9. + */ + producer = new Producer("HotSpot JVM", "Oracle Hotspot JVM", "http://www.oracle.com/hotspot/jvm/"); + producer.register(); + } catch (URISyntaxException e) { + throw new InternalError(e); + } + + // Register event classes with Producer. + for (Class c : JFREventProvider.class.getDeclaredClasses()) { + if (c.isAnnotationPresent(EventDefinition.class)) { + assert com.oracle.jrockit.jfr.InstantEvent.class.isAssignableFrom(c) : c; + registerEvent(c); + } + } + } + + /** + * Register an event class with the {@link Producer}. + * + * @param c event class + * @return the {@link EventToken event token} + */ + @SuppressWarnings({"deprecation", "javadoc", "unchecked"}) + private final EventToken registerEvent(Class c) { + try { + return producer.addEvent((Class) c); + } catch (InvalidEventDefinitionException | InvalidValueException e) { + throw new InternalError(e); + } + } + + public CompilationEvent newCompilationEvent() { + return new JFRCompilationEvent(); + } + + /** + * A JFR compilation event. + * + *

+ * See: event {@code Compilation} in {@code src/share/vm/trace/trace.xml} + */ + @SuppressWarnings("deprecation") + @EventDefinition(name = "Compilation", path = "vm/compiler/compilation") + public static class JFRCompilationEvent extends com.oracle.jrockit.jfr.DurationEvent implements CompilationEvent { + + /* + * FIXME method should be a Method* but we can't express that in Java. + */ + @ValueDefinition(name = "Java Method") public String method; + @ValueDefinition(name = "Compilation ID", relationKey = "COMP_ID") public int compileId; + @ValueDefinition(name = "Compilation Level") public short compileLevel; + @ValueDefinition(name = "Succeeded") public boolean succeeded; + @ValueDefinition(name = "On Stack Replacement") public boolean isOsr; + @ValueDefinition(name = "Compiled Code Size", contentType = ContentType.Bytes) public int codeSize; + @ValueDefinition(name = "Inlined Code Size", contentType = ContentType.Bytes) public int inlinedBytes; + + public void setMethod(String method) { + this.method = method; + } + + public void setCompileId(int id) { + this.compileId = id; + } + + public void setCompileLevel(int compileLevel) { + this.compileLevel = (short) compileLevel; + } + + public void setSucceeded(boolean succeeded) { + this.succeeded = succeeded; + } + + public void setIsOsr(boolean isOsr) { + this.isOsr = isOsr; + } + + public void setCodeSize(int codeSize) { + this.codeSize = codeSize; + } + + public void setInlinedBytes(int inlinedBytes) { + this.inlinedBytes = inlinedBytes; + } + } + + public CompilerFailureEvent newCompilerFailureEvent() { + return new JFRCompilerFailureEvent(); + } + + /** + * A JFR compiler failure event. + * + *

+ * See: event {@code CompilerFailure} in {@code src/share/vm/trace/trace.xml} + */ + @SuppressWarnings("deprecation") + @EventDefinition(name = "Compilation Failure", path = "vm/compiler/failure") + public static class JFRCompilerFailureEvent extends com.oracle.jrockit.jfr.InstantEvent implements CompilerFailureEvent { + + @ValueDefinition(name = "Compilation ID", relationKey = "COMP_ID") public int compileId; + @ValueDefinition(name = "Message", description = "The failure message") public String failure; + + public void setCompileId(int id) { + this.compileId = id; + } + + public void setMessage(String message) { + this.failure = message; + } + } + +} diff -r 50fbda571d99 -r 7340fe377764 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu May 15 15:31:22 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu May 15 15:32:37 2014 +0200 @@ -40,6 +40,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.baseline.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.common.*; @@ -47,6 +48,9 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.events.*; +import com.oracle.graal.hotspot.events.EventProvider.CompilationEvent; +import com.oracle.graal.hotspot.events.EventProvider.CompilerFailureEvent; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; @@ -144,6 +148,11 @@ return method; } + /** + * Returns the compilation id of this task. + * + * @return compile id + */ public int getId() { return id; } @@ -237,12 +246,16 @@ long previousInlinedBytecodes = InlinedBytecodes.getCurrentValue(); long previousCompilationTime = CompilationTime.getCurrentValue(); HotSpotInstalledCode installedCode = null; + final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; + + // Log a compilation event. + EventProvider eventProvider = Graal.getRequiredCapability(EventProvider.class); + CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); try (TimerCloseable a = CompilationTime.start()) { if (!tryToChangeStatus(CompilationStatus.Queued, CompilationStatus.Running)) { return; } - boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; // If there is already compiled code for this method on our level we simply return. // Graal compiles are always at the highest compile level, even in non-tiered mode so we @@ -266,6 +279,8 @@ final long allocatedBytesBefore = threadMXBean.getThreadAllocatedBytes(threadId); try (Scope s = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) { + // Begin the compilation event. + compilationEvent.begin(); if (UseBaselineCompiler.getValue() == true) { HotSpotProviders providers = backend.getProviders(); @@ -307,6 +322,9 @@ } catch (Throwable e) { throw Debug.handle(e); } finally { + // End the compilation event. + compilationEvent.end(); + filter.remove(); final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed(); @@ -346,16 +364,37 @@ if (PrintStackTraceOnException.getValue() || ExitVMOnException.getValue()) { t.printStackTrace(TTY.cachedOut); } + + // Log a failure event. + CompilerFailureEvent event = eventProvider.newCompilerFailureEvent(); + if (event.shouldWrite()) { + event.setCompileId(getId()); + event.setMessage(t.getMessage()); + event.commit(); + } + if (ExitVMOnException.getValue()) { System.exit(-1); } } finally { - int processedBytes = (int) (InlinedBytecodes.getCurrentValue() - previousInlinedBytecodes); + final int processedBytes = (int) (InlinedBytecodes.getCurrentValue() - previousInlinedBytecodes); + + // Log a compilation event. + if (compilationEvent.shouldWrite()) { + compilationEvent.setMethod(MetaUtil.format("%H.%n(%p)", method)); + compilationEvent.setCompileId(getId()); + compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); + compilationEvent.setSucceeded(true); + compilationEvent.setIsOsr(isOSR); + compilationEvent.setCodeSize(installedCode.getSize()); + compilationEvent.setInlinedBytes(processedBytes); + compilationEvent.commit(); + } + if (ctask != 0L) { unsafe.putInt(ctask + config.compileTaskNumInlinedBytecodesOffset, processedBytes); } if ((config.ciTime || config.ciTimeEach || PrintCompRate.getValue() != 0) && installedCode != null) { - long time = CompilationTime.getCurrentValue() - previousCompilationTime; TimeUnit timeUnit = CompilationTime.getTimeUnit(); long timeUnitsPerSecond = timeUnit.convert(1, TimeUnit.SECONDS); diff -r 50fbda571d99 -r 7340fe377764 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu May 15 15:31:22 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu May 15 15:32:37 2014 +0200 @@ -43,6 +43,7 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.events.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.options.*; @@ -274,6 +275,8 @@ } registerBackend(factory.createBackend(this, hostBackend)); } + + eventProvider = createEventProvider(); } private HotSpotBackend registerBackend(HotSpotBackend backend) { @@ -379,6 +382,22 @@ private final NodeCollectionsProvider nodeCollectionsProvider = new DefaultNodeCollectionsProvider(); + private final EventProvider eventProvider; + + private EventProvider createEventProvider() { + if (config.flightRecorder) { + ServiceLoader sl = ServiceLoader.loadInstalled(EventProvider.class); + EventProvider singleProvider = null; + for (EventProvider ep : sl) { + assert singleProvider == null : String.format("multiple %s service implementations found: %s and %s", EventProvider.class.getName(), singleProvider.getClass().getName(), + ep.getClass().getName()); + singleProvider = ep; + } + return singleProvider; + } + return new EmptyEventProvider(); + } + @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { @@ -392,6 +411,8 @@ return (T) getHostProviders().getSnippetReflection(); } else if (clazz == MethodHandleAccessProvider.class) { return (T) getHostProviders().getMethodHandleAccess(); + } else if (clazz == EventProvider.class) { + return (T) eventProvider; } return null; } diff -r 50fbda571d99 -r 7340fe377764 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu May 15 15:31:22 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu May 15 15:32:37 2014 +0200 @@ -737,6 +737,8 @@ @HotSpotVMFlag(name = "AllocatePrefetchStepSize") @Stable public int allocatePrefetchStepSize; @HotSpotVMFlag(name = "AllocatePrefetchDistance") @Stable public int allocatePrefetchDistance; + @HotSpotVMFlag(name = "FlightRecorder", optional = true) @Stable public boolean flightRecorder; + @HotSpotVMField(name = "Universe::_collectedHeap", type = "CollectedHeap*", get = HotSpotVMField.Type.VALUE) @Stable private long universeCollectedHeap; @HotSpotVMField(name = "CollectedHeap::_total_collections", type = "unsigned int", get = HotSpotVMField.Type.OFFSET) @Stable private int collectedHeapTotalCollectionsOffset; diff -r 50fbda571d99 -r 7340fe377764 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/events/EmptyEventProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/events/EmptyEventProvider.java Thu May 15 15:32:37 2014 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.events; + +import com.oracle.graal.compiler.common.*; + +/** + * An empty implementation for {@link EventProvider}. This implementation is used when no logging is + * requested. + */ +public final class EmptyEventProvider implements EventProvider { + + public CompilationEvent newCompilationEvent() { + return new EmptyCompilationEvent(); + } + + class EmptyCompilationEvent implements CompilationEvent { + public void commit() { + throw GraalInternalError.shouldNotReachHere(); + } + + public boolean shouldWrite() { + // Events of this class should never been written. + return false; + } + + public void begin() { + } + + public void end() { + } + + public void setMethod(String method) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setCompileId(int compileId) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setCompileLevel(int compileLevel) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setSucceeded(boolean succeeded) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setIsOsr(boolean isOsr) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setCodeSize(int codeSize) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setInlinedBytes(int inlinedBytes) { + throw GraalInternalError.shouldNotReachHere(); + } + } + + public CompilerFailureEvent newCompilerFailureEvent() { + return new EmptyCompilerFailureEvent(); + } + + class EmptyCompilerFailureEvent implements CompilerFailureEvent { + public void commit() { + throw GraalInternalError.shouldNotReachHere(); + } + + public boolean shouldWrite() { + // Events of this class should never been written. + return false; + } + + public void setCompileId(int compileId) { + throw GraalInternalError.shouldNotReachHere(); + } + + public void setMessage(String message) { + throw GraalInternalError.shouldNotReachHere(); + } + } + +} diff -r 50fbda571d99 -r 7340fe377764 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/events/EventProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/events/EventProvider.java Thu May 15 15:32:37 2014 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.events; + +/** + * A provider that provides a specific implementation for events that can be logged in the compiler. + */ +public interface EventProvider { + + /** + * An instant event is an event that is not considered to have taken any time. + */ + interface InstantEvent { + /** + * Commits the event. + */ + void commit(); + + /** + * Determines if this particular event instance would be committed to the data stream right + * now if application called {@link #commit()}. This in turn depends on whether the event is + * enabled and possible other factors. + * + * @return if this event would be committed on a call to {@link #commit()}. + */ + boolean shouldWrite(); + } + + /** + * Timed events describe an operation that somehow consumes time. + */ + interface TimedEvent extends InstantEvent { + /** + * Starts the timing for this event. + */ + void begin(); + + /** + * Ends the timing period for this event. + */ + void end(); + } + + /** + * Creates a new {@link CompilationEvent}. + * + * @return a compilation event + */ + CompilationEvent newCompilationEvent(); + + /** + * A compilation event. + */ + interface CompilationEvent extends TimedEvent { + void setMethod(String method); + + void setCompileId(int compileId); + + void setCompileLevel(int compileLevel); + + void setSucceeded(boolean succeeded); + + void setIsOsr(boolean isOsr); + + void setCodeSize(int codeSize); + + void setInlinedBytes(int inlinedBytes); + } + + /** + * Creates a new {@link CompilerFailureEvent}. + * + * @return a compiler failure event + */ + CompilerFailureEvent newCompilerFailureEvent(); + + /** + * A compiler failure event. + */ + interface CompilerFailureEvent extends InstantEvent { + void setCompileId(int compileId); + + void setMessage(String message); + } +} diff -r 50fbda571d99 -r 7340fe377764 mx/projects --- a/mx/projects Thu May 15 15:31:22 2014 +0200 +++ b/mx/projects Thu May 15 15:32:37 2014 +0200 @@ -2,8 +2,7 @@ mxversion=1.0 suite=graal -library@JDK_TOOLS@path=${JAVA_HOME}/lib/tools.jar -library@JDK_TOOLS@optional=true +jrelibrary@JFR@jar=jfr.jar library@JUNIT@path=lib/junit-4.11.jar library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar @@ -75,6 +74,7 @@ com.oracle.graal.truffle.hotspot.amd64,\ com.oracle.graal.hotspot.sparc,\ com.oracle.graal.hotspot,\ +com.oracle.graal.hotspot.jfr,\ com.oracle.graal.hotspot.hsail distribution@GRAAL@exclude=FINDBUGS @@ -191,6 +191,16 @@ project@com.oracle.graal.hotspot@javaCompliance=1.8 project@com.oracle.graal.hotspot@workingSets=Graal,HotSpot +# graal.hotspot.jfr +project@com.oracle.graal.hotspot.jfr@subDir=graal +project@com.oracle.graal.hotspot.jfr@sourceDirs=src +project@com.oracle.graal.hotspot.jfr@dependencies=com.oracle.graal.hotspot,JFR +project@com.oracle.graal.hotspot.jfr@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.hotspot.jfr@annotationProcessors=com.oracle.graal.service.processor +project@com.oracle.graal.hotspot.jfr@javaCompliance=1.8 +project@com.oracle.graal.hotspot.jfr@profile= +project@com.oracle.graal.hotspot.jfr@workingSets=Graal,HotSpot + # graal.hotspot.amd64 project@com.oracle.graal.hotspot.amd64@subDir=graal project@com.oracle.graal.hotspot.amd64@sourceDirs=src