# HG changeset patch
# User ecaspole
# Date 1512075634 18000
# Node ID 3af0ab7d1d903125a5ee68fe0498fc6f243f0d00
# Parent 9289fcb41aae902b6a1db16a4591a13d1bd5d779
8192821: Make LogCompilation into a maven project
Summary: Add a maven project setup while preserving make build.
Reviewed-by: kvn
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/Makefile
--- a/src/utils/LogCompilation/Makefile Thu Nov 30 20:37:20 2017 +0100
+++ b/src/utils/LogCompilation/Makefile Thu Nov 30 16:00:34 2017 -0500
@@ -25,7 +25,7 @@
com.sun.hotspot.tools.compiler
#END PKGLIST
-FILELIST = com/sun/hotspot/tools/compiler/*.java
+FILELIST = main/java/com/sun/hotspot/tools/compiler/*.java
ifneq "x$(ALT_BOOTDIR)" "x"
BOOTDIR := $(ALT_BOOTDIR)
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/README
--- a/src/utils/LogCompilation/README Thu Nov 30 20:37:20 2017 +0100
+++ b/src/utils/LogCompilation/README Thu Nov 30 16:00:34 2017 -0500
@@ -16,3 +16,10 @@
https://wiki.openjdk.java.net/display/HotSpot/LogCompilation+overview
https://wiki.openjdk.java.net/display/HotSpot/PrintCompilation
https://wiki.openjdk.java.net/display/HotSpot/LogCompilation+tool
+
+The project layout is now for Maven. To build the project with Maven do:
+
+ mvn clean install
+
+The build also copies the resulting target jar to ./logc.jar for easy
+interop with the Makefile build.
\ No newline at end of file
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/pom.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/pom.xml Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,110 @@
+
+
+
+ 4.0.0
+ com.sun.hotspot.tools.compiler
+ LogCompilation
+ jar
+ 1.0-SNAPSHOT
+ LogCompilation
+ http://maven.apache.org
+
+
+ junit
+ junit
+ 4.8.2
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+ com.sun.hotspot.tools.compiler.LogCompilation
+
+
+ false
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.3
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.0.0-M1
+
+
+ maven-antrun-plugin
+ 1.8
+
+
+ copy
+ package
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/BasicLogEvent.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-
-/**
- * Provide basic data structures and behaviour for {@link LogEvent}s.
- */
-public abstract class BasicLogEvent implements LogEvent {
-
- /**
- * The event's ID. This is a number; we represent it as a string for
- * convenience.
- */
- protected final String id;
-
- /**
- * The event's start time.
- */
- protected final double start;
-
- /**
- * The event's end time.
- */
- protected double end;
-
- /**
- * The compilation during which this event was signalled.
- */
- protected Compilation compilation;
-
- BasicLogEvent(double start, String id) {
- this.start = start;
- this.end = start;
- this.id = id;
- }
-
- public final double getStart() {
- return start;
- }
-
- public final double getEnd() {
- return end;
- }
-
- public final void setEnd(double end) {
- this.end = end;
- }
-
- public final double getElapsedTime() {
- return ((int) ((getEnd() - getStart()) * 1000)) / 1000.0;
- }
-
- public final String getId() {
- return id;
- }
-
- public final Compilation getCompilation() {
- return compilation;
- }
-
- /**
- * Set the compilation for this event. This is not a {@code final} method
- * as it is overridden in {@link UncommonTrapEvent}.
- */
- public void setCompilation(Compilation compilation) {
- this.compilation = compilation;
- }
-
- abstract public void print(PrintStream stream, boolean printID);
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Representation of a compilation scope in a compilation log. This class is a
- * hybrid: its instances can represent original scopes of methods being
- * compiled, but are also used to represent call sites in given methods.
- */
-public class CallSite {
-
- /**
- * The index of the call in the caller. This will be 0 if this instance
- * represents a compilation root.
- */
- private int bci;
-
- /**
- * The method that is called at this call site. This will be {@code null}
- * if this instance represents a compilation root.
- */
- private Method method;
-
- /**
- * The invocation count for this call site.
- */
- private int count;
-
- /**
- * The receiver type of the call represented by this instance, if known.
- */
- private String receiver;
-
- /**
- * In case the {@linkplain receiver receiver type} of the call represented
- * by this instance is known, this is how often the type was encountered.
- */
- private int receiver_count;
-
- /**
- * The reason for a success or failure of an inlining operation at this
- * call site.
- */
- private String reason;
-
- /**
- * A list of all calls in this compilation scope.
- */
- private List calls;
-
- /**
- * Number of nodes in the graph at the end of parsing this compilation
- * scope.
- */
- private int endNodes;
-
- /**
- * Number of live nodes in the graph at the end of parsing this compilation
- * scope.
- */
- private int endLiveNodes;
-
- /**
- * Time in seconds since VM startup at which parsing this compilation scope
- * ended.
- */
- private double timeStamp;
-
- /**
- * The inline ID in case the call represented by this instance is inlined,
- * 0 otherwise.
- */
- private long inlineId;
-
- /**
- * List of uncommon traps in this compilation scope.
- */
- private List traps;
-
- /**
- * Default constructor: used to create an instance that represents the top
- * scope of a compilation.
- */
- CallSite() {}
-
- /**
- * Constructor to create an instance that represents an actual method call.
- */
- CallSite(int bci, Method m) {
- this.bci = bci;
- this.method = m;
- }
-
- /**
- * Add a call site to the compilation scope represented by this instance.
- */
- void add(CallSite site) {
- if (getCalls() == null) {
- calls = new ArrayList<>();
- }
- getCalls().add(site);
- }
-
- /**
- * Return the last of the {@linkplain #getCalls() call sites} in this
- * compilation scope.
- */
- CallSite last() {
- return getCalls().get(getCalls().size() - 1);
- }
-
- /**
- * Return the last-but-one of the {@linkplain #getCalls() call sites} in
- * this compilation scope.
- */
- CallSite lastButOne() {
- return getCalls().get(getCalls().size() - 2);
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- if (getReason() == null) {
- sb.append(" @ " + getBci() + " " + getMethod());
- } else {
- sb.append("- @ " + getBci() + " " + getMethod() + " " + getReason());
- }
- sb.append("\n");
- if (getCalls() != null) {
- for (CallSite site : getCalls()) {
- sb.append(site);
- sb.append("\n");
- }
- }
- return sb.toString();
- }
-
- public void print(PrintStream stream) {
- print(stream, 0, true, false);
- }
-
- void emit(PrintStream stream, int indent) {
- for (int i = 0; i < indent; i++) {
- stream.print(' ');
- }
- }
-
- public void print(PrintStream stream, int indent, boolean printInlining, boolean printUncommonTraps) {
- emit(stream, indent);
- String m = getMethod().getHolder() + "::" + getMethod().getName();
- if (getReason() == null) {
- stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
- } else {
- stream.print(" @ " + getBci() + " " + m + " " + getReason());
- }
- stream.printf(" (end time: %6.4f", getTimeStamp());
- if (getEndNodes() > 0) {
- stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes());
- }
- stream.println(")");
-
- if (getReceiver() != null) {
- emit(stream, indent + 4);
- stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" +
- (getReceiverCount() * 100 / getCount()) + "%)");
- }
- if (printInlining && getCalls() != null) {
- for (CallSite site : getCalls()) {
- site.print(stream, indent + 2, printInlining, printUncommonTraps);
- }
- }
- if (printUncommonTraps && getTraps() != null) {
- for (UncommonTrap site : getTraps()) {
- site.print(stream, indent + 2);
- }
- }
- }
-
- public int getBci() {
- return bci;
- }
-
- public void setBci(int bci) {
- this.bci = bci;
- }
-
- public Method getMethod() {
- return method;
- }
-
- public void setMethod(Method method) {
- this.method = method;
- }
-
- public int getCount() {
- return count;
- }
-
- public void setCount(int count) {
- this.count = count;
- }
-
- public String getReceiver() {
- return receiver;
- }
-
- public void setReceiver(String receiver) {
- this.receiver = receiver;
- }
-
- public int getReceiverCount() {
- return receiver_count;
- }
-
- public void setReceiver_count(int receiver_count) {
- this.receiver_count = receiver_count;
- }
-
- public String getReason() {
- return reason;
- }
-
- public void setReason(String reason) {
- this.reason = reason;
- }
-
- public List getCalls() {
- return calls;
- }
-
- public List getTraps() {
- return traps;
- }
-
- void add(UncommonTrap e) {
- if (traps == null) {
- traps = new ArrayList();
- }
- traps.add(e);
- }
-
- void setEndNodes(int n) {
- endNodes = n;
- }
-
- public int getEndNodes() {
- return endNodes;
- }
-
- void setEndLiveNodes(int n) {
- endLiveNodes = n;
- }
-
- public int getEndLiveNodes() {
- return endLiveNodes;
- }
-
- void setTimeStamp(double time) {
- timeStamp = time;
- }
-
- public double getTimeStamp() {
- return timeStamp;
- }
-
- /**
- * Check whether this call site matches another. Every late inline call
- * site has a unique inline ID. If the call site we're looking for has one,
- * then use it; otherwise rely on method name and byte code index.
- */
- private boolean matches(CallSite other) {
- if (other.inlineId != 0) {
- return inlineId == other.inlineId;
- }
- return method.equals(other.method) && bci == other.bci;
- }
-
- /**
- * Locate a late inline call site: find, in this instance's
- * {@linkplain #calls call sites}, the one furthest down the given call
- * stack.
- *
- * Multiple chains of identical call sites with the same method name / bci
- * combination are possible, so we have to try them all until we find the
- * late inline call site that has a matching inline ID.
- *
- * @return a matching call site, or {@code null} if none was found.
- */
- public CallSite findCallSite(ArrayDeque sites) {
- if (calls == null) {
- return null;
- }
- CallSite site = sites.pop();
- for (CallSite c : calls) {
- if (c.matches(site)) {
- if (!sites.isEmpty()) {
- CallSite res = c.findCallSite(sites);
- if (res != null) {
- sites.push(site);
- return res;
- }
- } else {
- sites.push(site);
- return c;
- }
- }
- }
- sites.push(site);
- return null;
- }
-
- /**
- * Locate a late inline call site in the tree spanned by all this instance's
- * {@linkplain #calls call sites}, and return the sequence of call sites
- * (scopes) leading to that late inline call site.
- */
- public ArrayDeque findCallSite2(CallSite site) {
- if (calls == null) {
- return null;
- }
-
- for (CallSite c : calls) {
- if (c.matches(site)) {
- ArrayDeque stack = new ArrayDeque<>();
- stack.push(c);
- return stack;
- } else {
- ArrayDeque stack = c.findCallSite2(site);
- if (stack != null) {
- stack.push(c);
- return stack;
- }
- }
- }
- return null;
- }
-
- public long getInlineId() {
- return inlineId;
- }
-
- public void setInlineId(long inlineId) {
- this.inlineId = inlineId;
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-import java.util.ArrayList;
-
-/**
- * One particular compilation, represented in the compilation log file as a
- * {@code task} element.
- */
-public class Compilation implements LogEvent {
-
- /**
- * The compilation ID.
- */
- private int id;
-
- /**
- * Whether this is a compilation for on-stack replacement (OSR).
- */
- private boolean osr;
-
- /**
- * The method being compiled.
- */
- private Method method;
-
- /**
- * The {@linkplain CallSite scope} of this compilation. This is created as
- * an empty {@link CallSite} instance, to be filled with data (and
- * meaning) later on.
- */
- private CallSite call = new CallSite();
-
- /**
- * In case a {@code late_inline} event occurs during the compilation, this
- * field holds the information about it.
- */
- private CallSite lateInlineCall = new CallSite();
-
- /**
- * The bytecode instruction index for on-stack replacement compilations; -1
- * if this is not an OSR compilation.
- */
- private int bci;
-
- /**
- * The method under compilation's invocation count.
- */
- private String icount;
-
- /**
- * The method under compilation's backedge count.
- */
- private String bcount;
-
- /**
- * Additional information for special compilations (e.g., adapters).
- */
- private String special;
-
- /**
- * The name of the compiler performing this compilation.
- */
- private String compiler;
-
- /**
- * Start time stamp.
- */
- private double start;
-
- /**
- * End time stamp.
- */
- private double end;
-
- /**
- * Trip count of the register allocator.
- */
- private int attempts;
-
- /**
- * The compilation result (a native method).
- */
- private NMethod nmethod;
-
- /**
- * The phases through which this compilation goes.
- */
- private ArrayList phases = new ArrayList<>(4);
-
- /**
- * In case this compilation fails, the reason for that.
- */
- private String failureReason;
-
- Compilation(int id) {
- this.id = id;
- }
-
- void reset() {
- call = new CallSite();
- lateInlineCall = new CallSite();
- phases = new ArrayList<>(4);
- }
-
- /**
- * Get a compilation phase by name, or {@code null}.
- *
- * @param s the name of the phase to retrieve in this compilation.
- *
- * @return a compilation phase, or {@code null} if no phase with the given
- * name is found.
- */
- Phase getPhase(String s) {
- for (Phase p : getPhases()) {
- if (p.getName().equals(s)) {
- return p;
- }
- }
- return null;
- }
-
- double getRegallocTime() {
- return getPhase("regalloc").getElapsedTime();
- }
-
- public double getStart() {
- return start;
- }
-
- public void setCompiler(String compiler) {
- this.compiler = compiler;
- }
-
- public String getCompiler() {
- return compiler;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(getId());
- sb.append(" ");
- sb.append(getCompiler());
- sb.append(" ");
- sb.append(getMethod());
- sb.append(" ");
- sb.append(getIcount());
- sb.append("+");
- sb.append(getBcount());
- sb.append("\n");
- if (getCall() != null && getCall().getCalls() != null) {
- for (CallSite site : getCall().getCalls()) {
- sb.append(site);
- sb.append("\n");
- }
- }
- if (getLateInlineCall().getCalls() != null) {
- sb.append("late inline:\n");
- for (CallSite site : getLateInlineCall().getCalls()) {
- sb.append(site);
- sb.append("\n");
- }
- }
- return sb.toString();
- }
-
- public void printShort(PrintStream stream) {
- if (getMethod() == null) {
- stream.println(getSpecial());
- } else {
- int bc = isOsr() ? getBCI() : -1;
- stream.print(getId() + getMethod().decodeFlags(bc) + " " + compiler + " " + getMethod().format(bc));
- }
- }
-
- public void print(PrintStream stream, boolean printID) {
- print(stream, 0, printID, true, false);
- }
-
- public void print(PrintStream stream, boolean printID, boolean printInlining) {
- print(stream, 0, printID, printInlining, false);
- }
-
- public void print(PrintStream stream, boolean printID, boolean printInlining, boolean printUncommonTraps) {
- print(stream, 0, printID, printInlining, printUncommonTraps);
- }
-
- public void print(PrintStream stream, int indent, boolean printID, boolean printInlining, boolean printUncommonTraps) {
- if (getMethod() == null) {
- stream.println(getSpecial());
- } else {
- if (printID) {
- stream.print(getId());
- }
- int bc = isOsr() ? getBCI() : -1;
- stream.print(getMethod().decodeFlags(bc) + " " + compiler + " " + getMethod().format(bc));
- stream.println();
- if (getFailureReason() != null) {
- stream.println("COMPILE SKIPPED: " + getFailureReason() + " (not retryable)");
- }
- if (printInlining && call.getCalls() != null) {
- for (CallSite site : call.getCalls()) {
- site.print(stream, indent + 2, printInlining, printUncommonTraps);
- }
- }
- if (printUncommonTraps && call.getTraps() != null) {
- for (UncommonTrap site : call.getTraps()) {
- site.print(stream, indent + 2);
- }
- }
- if (printInlining && lateInlineCall.getCalls() != null) {
- stream.println("late inline:");
- for (CallSite site : lateInlineCall.getCalls()) {
- site.print(stream, indent + 2, printInlining, printUncommonTraps);
- }
- }
- }
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public boolean isOsr() {
- return osr;
- }
-
- public void setOsr(boolean osr) {
- this.osr = osr;
- }
-
- public int getBCI() {
- return bci;
- }
-
- public void setBCI(int osrBci) {
- this.bci = osrBci;
- }
-
- public String getIcount() {
- return icount;
- }
-
- public void setICount(String icount) {
- this.icount = icount;
- }
-
- public String getBcount() {
- return bcount;
- }
-
- public void setBCount(String bcount) {
- this.bcount = bcount;
- }
-
- public String getSpecial() {
- return special;
- }
-
- public void setSpecial(String special) {
- this.special = special;
- }
-
- public void setStart(double start) {
- this.start = start;
- }
-
- public double getEnd() {
- return end;
- }
-
- public void setEnd(double end) {
- this.end = end;
- }
-
- public int getAttempts() {
- return attempts;
- }
-
- public void setAttempts(int attempts) {
- this.attempts = attempts;
- }
-
- public NMethod getNMethod() {
- return nmethod;
- }
-
- public void setNMethod(NMethod NMethod) {
- this.nmethod = NMethod;
- }
-
- public ArrayList getPhases() {
- return phases;
- }
-
- public String getFailureReason() {
- return failureReason;
- }
-
- public void setFailureReason(String failureReason) {
- this.failureReason = failureReason;
- }
-
- public Method getMethod() {
- return method;
- }
-
- /**
- * Set the method under compilation. If it is already set, ignore the
- * argument to avoid changing the method by post-parse inlining info.
- *
- * @param method the method under compilation. May be ignored.
- */
- public void setMethod(Method method) {
- if (getMethod() == null) {
- this.method = method;
- }
- }
-
- public CallSite getCall() {
- return call;
- }
-
- public CallSite getLateInlineCall() {
- return lateInlineCall;
- }
-
- public double getElapsedTime() {
- return end - start;
- }
-
- public Compilation getCompilation() {
- return this;
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Constants.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Constants.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2009, 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.sun.hotspot.tools.compiler;
-
-interface Constants {
- static final int JVM_ACC_PUBLIC = 0x0001; /* visible to everyone */
- static final int JVM_ACC_PRIVATE = 0x0002; /* visible only to the defining class */
- static final int JVM_ACC_PROTECTED = 0x0004; /* visible to subclasses */
- static final int JVM_ACC_STATIC = 0x0008; /* instance variable is static */
- static final int JVM_ACC_FINAL = 0x0010; /* no further subclassing, overriding */
- static final int JVM_ACC_SYNCHRONIZED = 0x0020; /* wrap method call in monitor lock */
- static final int JVM_ACC_SUPER = 0x0020; /* funky handling of invokespecial */
- static final int JVM_ACC_VOLATILE = 0x0040; /* can not cache in registers */
- static final int JVM_ACC_BRIDGE = 0x0040; /* bridge method generated by compiler */
- static final int JVM_ACC_TRANSIENT = 0x0080; /* not persistent */
- static final int JVM_ACC_VARARGS = 0x0080; /* method declared with variable number of args */
- static final int JVM_ACC_NATIVE = 0x0100; /* implemented in C */
- static final int JVM_ACC_INTERFACE = 0x0200; /* class is an interface */
- static final int JVM_ACC_ABSTRACT = 0x0400; /* no definition provided */
- static final int JVM_ACC_STRICT = 0x0800; /* strict floating point */
- static final int JVM_ACC_SYNTHETIC = 0x1000; /* compiler-generated class, method or field */
- static final int JVM_ACC_ANNOTATION = 0x2000; /* annotation type */
- static final int JVM_ACC_ENUM = 0x4000; /* field is declared as element of enum */
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCleanupReader.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.*;
-import java.util.regex.*;
-
-/**
- * This class is a filter class to deal with malformed XML that used
- * to be produced by the JVM when generating LogCompilation. In 1.6
- * and later releases it shouldn't be required.
- */
-class LogCleanupReader extends Reader {
-
- private Reader reader;
-
- private char[] buffer = new char[4096];
-
- private int bufferCount;
-
- private int bufferOffset;
-
- private char[] line = new char[1024];
-
- private int index;
-
- private int length;
-
- private char[] one = new char[1];
-
- LogCleanupReader(Reader r) {
- reader = r;
- }
-
- static final private Matcher duplicateCompileID = Pattern.compile(".+ compile_id='[0-9]+'.*( compile_id='[0-9]+)").matcher("");
- static final private Matcher compilerName = Pattern.compile("' (C[12]) compile_id=").matcher("");
- static final private Matcher destroyVM = Pattern.compile("'(destroy_vm)/").matcher("");
-
- /**
- * The log cleanup takes place in this method. If any of the three patterns
- * ({@link #duplicateCompileID}, {@link #compilerName}, {@link #destroyVM})
- * match, that indicates a problem in the log. The cleanup is performed by
- * correcting the input line and writing it back into the {@link #line}
- * buffer.
- */
- private void fill() throws IOException {
- rawFill();
- if (length != -1) {
- boolean changed = false;
- String s = new String(line, 0, length);
-
- compilerName.reset(s);
- if (compilerName.find()) {
- s = s.substring(0, compilerName.start(1)) + s.substring(compilerName.end(1) + 1);
- changed = true;
- }
-
- duplicateCompileID.reset(s);
- if (duplicateCompileID.lookingAt()) {
- s = s.substring(0, duplicateCompileID.start(1)) + s.substring(duplicateCompileID.end(1) + 1);
- changed = true;
- }
-
- destroyVM.reset(s);
- if (destroyVM.find()) {
- s = s.substring(0, destroyVM.start(1)) + s.substring(destroyVM.end(1));
- changed = true;
- }
-
- if (changed) {
- s.getChars(0, s.length(), line, 0);
- length = s.length();
- }
- }
- }
-
- private void rawFill() throws IOException {
- if (bufferCount == -1) {
- length = -1;
- return;
- }
-
- int i = 0;
- boolean fillNonEOL = true;
- outer:
- while (true) {
- if (fillNonEOL) {
- int p;
- for (p = bufferOffset; p < bufferCount; p++) {
- char c = buffer[p];
- if (c == '\r' || c == '\n') {
- bufferOffset = p;
- fillNonEOL = false;
- continue outer;
- }
- if (i >= line.length) {
- // copy and enlarge the line array
- char[] newLine = new char[line.length * 2];
- System.arraycopy(line, 0, newLine, 0, line.length);
- line = newLine;
- }
- line[i++] = c;
- }
- bufferOffset = p;
- } else {
- int p;
- for (p = bufferOffset; p < bufferCount; p++) {
- char c = buffer[p];
- if (c != '\r' && c != '\n') {
- bufferOffset = p;
- length = i;
- index = 0;
- return;
- }
- line[i++] = c;
- }
- bufferOffset = p;
- }
- if (bufferCount == -1) {
- if (i == 0) {
- length = -1;
- } else {
- length = i;
- }
- index = 0;
- return;
- }
- if (bufferOffset != bufferCount) {
- System.out.println(bufferOffset);
- System.out.println(bufferCount);
- throw new InternalError("how did we get here");
- }
- // load more data and try again.
- bufferCount = reader.read(buffer, 0, buffer.length);
- bufferOffset = 0;
- }
- }
-
- public int read() throws java.io.IOException {
- read(one, 0, 1);
- return one[0];
- }
-
- public int read(char[] buffer) throws java.io.IOException {
- return read(buffer, 0, buffer.length);
- }
-
- public int read(char[] b, int off, int len) throws java.io.IOException {
- if (length == -1) {
- return -1;
- }
-
- if (index == length) {
- fill();
- if (length == -1) {
- return -1;
- }
- }
- int n = Math.min(length - index, Math.min(b.length - off, len));
- // System.out.printf("%d %d %d %d %d\n", index, length, off, len, n);
- System.arraycopy(line, index, b, off, n);
- index += n;
- return n;
- }
-
- public long skip(long n) throws java.io.IOException {
- long result = n;
- while (n-- > 0) read();
- return result;
- }
-
- public boolean ready() throws java.io.IOException {
- return reader.ready() || (line != null && length > 0);
- }
-
- public boolean markSupported() {
- return false;
- }
-
- public void mark(int unused) throws java.io.IOException {
- throw new UnsupportedOperationException("mark not supported");
- }
-
- public void reset() throws java.io.IOException {
- reader.reset();
- line = null;
- index = 0;
- }
-
- public void close() throws java.io.IOException {
- reader.close();
- line = null;
- index = 0;
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,511 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.*;
-
-import org.xml.sax.*;
-import org.xml.sax.helpers.*;
-
-/**
- * The LogCompilation tool parses log files generated by HotSpot using the
- * {@code -XX:+LogCompilation} command line flag, and outputs the data
- * collected therein in a nicely formatted way. There are various sorting
- * options available, as well as options that select specific compilation
- * events (such as inlining decisions) for inclusion in the output.
- *
- * The tool is also capable of fixing broken compilation logs as sometimes
- * generated by Java 1.5 JVMs.
- */
-public class LogCompilation extends DefaultHandler implements ErrorHandler {
-
- /**
- * Print usage information and terminate with a given exit code.
- */
- public static void usage(int exitcode) {
- System.out.println("Usage: LogCompilation [ -v ] [ -c ] [ -s ] [ -e | -n ] file1 ...");
- System.out.println("By default, the tool will print the logged compilations ordered by start time.");
- System.out.println(" -c: clean up malformed 1.5 xml");
- System.out.println(" -i: print inlining decisions");
- System.out.println(" -S: print compilation statistics");
- System.out.println(" -U: print uncommon trap statistics");
- System.out.println(" -t: print with time stamps");
- System.out.println(" -s: sort events by start time (default)");
- System.out.println(" -e: sort events by elapsed time");
- System.out.println(" -n: sort events by name and start");
- System.out.println(" -C: compare logs (give files to compare on command line)");
- System.out.println(" -d: do not print compilation IDs");
- System.exit(exitcode);
- }
-
- /**
- * Process command line arguments, parse log files and trigger desired
- * functionality.
- */
- public static void main(String[] args) throws Exception {
- Comparator sort = LogParser.sortByStart;
- boolean statistics = false;
- boolean printInlining = false;
- boolean cleanup = false;
- boolean trapHistory = false;
- boolean printTimeStamps = false;
- boolean compare = false;
- boolean printID = true;
- int index = 0;
-
- while (args.length > index) {
- String a = args[index];
- if (a.equals("-e")) {
- sort = LogParser.sortByElapsed;
- index++;
- } else if (a.equals("-n")) {
- sort = LogParser.sortByNameAndStart;
- index++;
- } else if (a.equals("-s")) {
- sort = LogParser.sortByStart;
- index++;
- } else if (a.equals("-t")) {
- printTimeStamps = true;
- index++;
- } else if (a.equals("-c")) {
- cleanup = true;
- index++;
- } else if (a.equals("-S")) {
- statistics = true;
- index++;
- } else if (a.equals("-U")) {
- trapHistory = true;
- index++;
- } else if (a.equals("-h")) {
- usage(0);
- } else if (a.equals("-i")) {
- printInlining = true;
- index++;
- } else if (a.equals("-C")) {
- compare = true;
- index++;
- } else if (a.equals("-d")) {
- printID = false;
- index++;
- } else {
- if (a.charAt(0) == '-') {
- System.out.println("Unknown option '" + a + "', assuming file name.");
- }
- break;
- }
- }
-
- if (index >= args.length) {
- usage(1);
- }
-
- if (compare) {
- compareLogs(index, args);
- return;
- }
-
- while (index < args.length) {
- ArrayList events = null;
- try {
- events = LogParser.parse(args[index], cleanup);
- } catch (FileNotFoundException fnfe) {
- System.out.println("File not found: " + args[index]);
- System.exit(1);
- }
-
- Collections.sort(events, sort);
-
- if (statistics) {
- printStatistics(events, System.out);
- } else if (trapHistory) {
- printTrapHistory(events, System.out);
- } else {
- for (LogEvent c : events) {
- if (c instanceof NMethod) {
- // skip these
- continue;
- }
- if (printTimeStamps) {
- System.out.print(c.getStart() + ": ");
- }
- if (c instanceof Compilation) {
- Compilation comp = (Compilation) c;
- comp.print(System.out, printID, printInlining);
- } else {
- c.print(System.out, printID);
- }
- }
- }
- index++;
- }
- }
-
- /**
- * Print extensive statistics from parsed log files.
- */
- public static void printStatistics(ArrayList events, PrintStream out) {
- // track code cache size
- long cacheSize = 0;
- long maxCacheSize = 0;
- // track number of nmethods
- int nmethodsCreated = 0;
- int nmethodsLive = 0;
- // track how many compilations were attempted multiple times
- // (indexed by attempts, mapping to number of compilations)
- int[] attempts = new int[32];
- int maxattempts = 0;
-
- // track time spent in compiler phases
- LinkedHashMap phaseTime = new LinkedHashMap<>(7);
- // track nodes created per phase
- LinkedHashMap phaseNodes = new LinkedHashMap<>(7);
- double elapsed = 0;
-
- for (LogEvent e : events) {
- if (e instanceof Compilation) {
- Compilation c = (Compilation) e;
- c.printShort(out);
- out.printf(" %6.4f\n", c.getElapsedTime());
- attempts[c.getAttempts()]++;
- maxattempts = Math.max(maxattempts,c.getAttempts());
- elapsed += c.getElapsedTime();
- for (Phase phase : c.getPhases()) {
- Double v = phaseTime.get(phase.getName());
- if (v == null) {
- v = Double.valueOf(0.0);
- }
- phaseTime.put(phase.getName(), Double.valueOf(v.doubleValue() + phase.getElapsedTime()));
-
- Integer v2 = phaseNodes.get(phase.getName());
- if (v2 == null) {
- v2 = Integer.valueOf(0);
- }
- phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes()));
- // Print phase name, elapsed time, nodes at the start of
- // the phase, nodes created in the phase, live nodes at the
- // start of the phase, live nodes added in the phase.
- out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getAddedLiveNodes());
- }
- } else if (e instanceof MakeNotEntrantEvent) {
- MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e;
- NMethod nm = mne.getNMethod();
- if (mne.isZombie()) {
- if (nm == null) {
- System.err.println("zombie make not entrant event without nmethod: " + mne.getId());
- }
- cacheSize -= nm.getSize();
- nmethodsLive--;
- }
- } else if (e instanceof NMethod) {
- nmethodsLive++;
- nmethodsCreated++;
- NMethod nm = (NMethod) e;
- cacheSize += nm.getSize();
- maxCacheSize = Math.max(cacheSize, maxCacheSize);
- }
- }
- out.printf("NMethods: %d created %d live %d bytes (%d peak) in the code cache\n", nmethodsCreated, nmethodsLive, cacheSize, maxCacheSize);
- out.println("Phase times:");
- for (String name : phaseTime.keySet()) {
- Double v = phaseTime.get(name);
- Integer v2 = phaseNodes.get(name);
- out.printf("%20s %6.4f %d\n", name, v.doubleValue(), v2.intValue());
- }
- out.printf("%20s %6.4f\n", "total", elapsed);
-
- if (maxattempts > 0) {
- out.println("Distribution of regalloc passes:");
- for (int i = 0; i <= maxattempts; i++) {
- out.printf("%2d %8d\n", i, attempts[i]);
- }
- }
- }
-
- /**
- * Container class for a pair of a method and a bytecode instruction index
- * used by a compiler. This is used in
- * {@linkplain #compareLogs() comparing logs}.
- */
- static class MethodBCIPair {
- public MethodBCIPair(Method m, int b, String c) {
- method = m;
- bci = b;
- compiler = c;
- }
-
- Method method;
- int bci;
- String compiler;
-
- public boolean equals(Object other) {
- if (!(other instanceof MethodBCIPair)) {
- return false;
- }
- MethodBCIPair otherp = (MethodBCIPair)other;
- return (otherp.bci == bci &&
- otherp.method.equals(method) &&
- otherp.compiler.equals(compiler));
- }
-
- public int hashCode() {
- return method.hashCode() + bci;
- }
-
- public String toString() {
- if (bci != -1) {
- return method + "@" + bci + " (" + compiler + ")";
- } else {
- return method + " (" + compiler + ")";
- }
- }
- }
-
- /**
- * Compare a number of compilation log files. Each of the logs is parsed,
- * and all compilations found therein are written to a sorted file (prefix
- * {@code sorted-}. A summary is written to a new file {@code summary.txt}.
- *
- * @param index the index in the command line arguments at which to start
- * looking for files to compare.
- * @param args the command line arguments with which {@link LogCompilation}
- * was originally invoked.
- *
- * @throws Exception in case any exceptions are thrown in the called
- * methods.
- */
- @SuppressWarnings("unchecked")
- static void compareLogs(int index, String[] args) throws Exception {
- HashMap methods = new HashMap<>();
- ArrayList> logs = new ArrayList<>();
- PrintStream[] outs = new PrintStream[args.length - index];
- PrintStream summary = new PrintStream(new FileOutputStream("summary.txt"));
- int o = 0;
- // Process all logs given on the command line: collect compilation
- // data; in particular, method/bci pairs.
- while (index < args.length) {
- String basename = new File(args[index]).getName();
- String outname = "sorted-" + basename;
- System.out.println("Sorting " + basename + " to " + outname);
- outs[o] = new PrintStream(new FileOutputStream(outname));
- o++;
- System.out.println("Parsing " + args[index]);
- ArrayList events = LogParser.parse(args[index], false);
- HashMap compiles = new HashMap<>();
- logs.add(compiles);
- for (LogEvent c : events) {
- if (c instanceof Compilation) {
- Compilation comp = (Compilation) c;
- MethodBCIPair key = new MethodBCIPair(comp.getMethod(), comp.getBCI(),
- comp.getCompiler());
- MethodBCIPair e = methods.get(key);
- if (e == null) {
- methods.put(key, key);
- } else {
- key = e;
- }
- Object other = compiles.get(key);
- if (other == null) {
- compiles.put(key, comp);
- } else {
- if (!(other instanceof List)) {
- List l = new LinkedList<>();
- l.add(other);
- l.add(comp);
- compiles.put(key, l);
- } else {
- List l = (List) other;
- l.add(comp);
- }
- }
- }
- }
- index++;
- }
-
- // Process the collected method/bci pairs and write the output.
- for (MethodBCIPair pair : methods.keySet()) {
- summary.print(pair + " ");
- int base = -1;
- String first = null;
- boolean mismatch = false;
- boolean different = false;
- String[] output = new String[outs.length];
- o = 0;
- for (HashMap set : logs) {
- Object e = set.get(pair);
- String thisone = null;
- Compilation lastc = null;
- int n;
- if (e == null) {
- n = 0;
- } else if (e instanceof Compilation) {
- n = 1;
- lastc = (Compilation) e;
- } else {
- // Compare the last compilation that was done for this method
- n = ((List) e).size();
- lastc = (Compilation) ((List) e).get(n - 1);
- }
- if (lastc != null) {
- n = 1;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(baos);
- lastc.print(ps, false);
- ps.close();
- thisone = new String(baos.toByteArray());
- }
- if (base == -1) {
- base = n;
- } else if (base != n) {
- mismatch = true;
- }
- output[o++] = thisone;
- if (thisone != null) {
- if (first == null) {
- first = thisone;
- } else {
- if (!first.equals(thisone)) {
- different = true;
- }
- }
- }
- if (different) {
- summary.print(n + "d ");
- } else {
- summary.print(n + " ");
- }
- }
- if (mismatch) {
- summary.print("mismatch");
- }
- summary.println();
- if (different) {
- for (int i = 0; i < outs.length; i++) {
- if (output[i] != null) {
- outs[i].println(output[i]);
- }
- }
- }
- }
- for (int i = 0; i < outs.length; i++) {
- outs[i].close();
- }
- if (summary != System.out) {
- summary.close();
- }
- }
-
- /**
- * Print the history of uncommon trap events.
- */
- public static void printTrapHistory(ArrayList events, PrintStream out) {
- // map method names to a list of log events
- LinkedHashMap> traps = new LinkedHashMap<>();
- // map compilation IDs to compilations
- HashMap comps = new HashMap<>();
-
- // First, iterate over all logged events, collecting data about
- // uncommon trap events.
- for (LogEvent e : events) {
- if (e instanceof NMethod) {
- // skip these
- continue;
- }
- if (e instanceof Compilation) {
- Compilation c = (Compilation) e;
- String name = c.getMethod().getFullName();
- ArrayList elist = traps.get(name);
- if (elist != null && comps.get(c.getId()) == null) {
- comps.put(c.getId(), c);
- // If there were previous events for the method
- // then keep track of later compiles too.
- elist.add(c);
- }
- continue;
- }
- if (e instanceof BasicLogEvent) {
- BasicLogEvent ble = (BasicLogEvent) e;
- Compilation c = ble.getCompilation();
- if (c == null) {
- if (!(ble instanceof NMethod)) {
- throw new InternalError("only nmethods should have a null compilation; here's a " + ble.getClass());
- }
- continue;
- }
- String name = c.getMethod().getFullName();
- ArrayList elist = traps.get(name);
- if (elist == null) {
- elist = new ArrayList();
- traps.put(name, elist);
- }
- int bleId = Integer.parseInt(ble.getId());
- if (comps.get(bleId) == null) {
- comps.put(bleId, c);
- // Add the associated compile to the list. It
- // will likely go at the end but we need to search
- // backwards for the proper insertion point.
- double start = c.getStart();
- int ipoint = 0;
- while (ipoint < elist.size() && elist.get(ipoint).getStart() < start) {
- ipoint++;
- }
- if (ipoint == elist.size()) {
- elist.add(c);
- } else {
- elist.add(ipoint, c);
- }
- }
- elist.add(ble);
- }
- }
-
- // Second, iterate over collected traps and output information.
- for (String c: traps.keySet()) {
- ArrayList elist = traps.get(c);
- String name = ((Compilation) elist.get(0)).getMethod().getFullName();
- System.out.println(name);
- double start = 0;
- for (LogEvent e: elist) {
- if (start > e.getStart() && e.getStart() != 0) {
- throw new InternalError("wrong sorting order for traps");
- }
- start = e.getStart();
- out.print(e.getStart() + ": ");
- if (e instanceof Compilation) {
- ((Compilation) e).print(out, true, true, true);
- } else {
- e.print(out, true);
- }
- }
- out.println();
- }
- }
-
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogEvent.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-
-/**
- * The interface of an event from a HotSpot compilation log. Events can have a
- * duration, e.g., a compiler {@link Phase} is an event, and so is an entire
- * {@link Compilation}.
- */
-public interface LogEvent {
-
- /**
- * The event's start time.
- */
- public double getStart();
-
- /**
- * The event's duration in milliseconds.
- */
- public double getElapsedTime();
-
- /**
- * The compilation during which this event was signalled.
- */
- public Compilation getCompilation();
-
- /**
- * Print the event to the given stream.
- */
- public void print(PrintStream stream, boolean printID);
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1302 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.
- *
- */
-
-/**
- * A SAX based parser of LogCompilation output from HotSpot. It takes a complete
- */
-
-package com.sun.hotspot.tools.compiler;
-
-import java.io.FileReader;
-import java.io.PrintStream;
-import java.io.Reader;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.regex.Pattern;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * A SAX parser for HotSpot compilation logs. The bulk of the parsing and event
- * maintenance work is done in the {@link #startElement(String,String,String,Attributes)}
- * and {@link #endElement(String,String,String)} methods.
- */
-public class LogParser extends DefaultHandler implements ErrorHandler {
-
- static final Pattern spacePattern = Pattern.compile(" ");
-
- /**
- * Map internal array type descriptors to Java names.
- */
- static final HashMap type2printableMap;
-
- /**
- * Map Java primitive type names to internal type descriptors.
- */
- static final HashMap type2vmtypeMap;
-
- static {
- type2printableMap = new HashMap<>();
- type2printableMap.put("[I", "int[]");
- type2printableMap.put("[C", "char[]");
- type2printableMap.put("[Z", "boolean[]");
- type2printableMap.put("[L", "Object[]");
- type2printableMap.put("[B", "byte[]");
-
- type2vmtypeMap = new HashMap<>();
- type2vmtypeMap.put("void", "V");
- type2vmtypeMap.put("boolean", "Z");
- type2vmtypeMap.put("byte", "B");
- type2vmtypeMap.put("char", "C");
- type2vmtypeMap.put("short", "S");
- type2vmtypeMap.put("int", "I");
- type2vmtypeMap.put("long", "J");
- type2vmtypeMap.put("float", "F");
- type2vmtypeMap.put("double", "D");
- }
-
- static String[] bytecodes = new String[] {
- "nop",
- "aconst_null",
- "iconst_m1",
- "iconst_0",
- "iconst_1",
- "iconst_2",
- "iconst_3",
- "iconst_4",
- "iconst_5",
- "lconst_0",
- "lconst_1",
- "fconst_0",
- "fconst_1",
- "fconst_2",
- "dconst_0",
- "dconst_1",
- "bipush",
- "sipush",
- "ldc",
- "ldc_w",
- "ldc2_w",
- "iload",
- "lload",
- "fload",
- "dload",
- "aload",
- "iload_0",
- "iload_1",
- "iload_2",
- "iload_3",
- "lload_0",
- "lload_1",
- "lload_2",
- "lload_3",
- "fload_0",
- "fload_1",
- "fload_2",
- "fload_3",
- "dload_0",
- "dload_1",
- "dload_2",
- "dload_3",
- "aload_0",
- "aload_1",
- "aload_2",
- "aload_3",
- "iaload",
- "laload",
- "faload",
- "daload",
- "aaload",
- "baload",
- "caload",
- "saload",
- "istore",
- "lstore",
- "fstore",
- "dstore",
- "astore",
- "istore_0",
- "istore_1",
- "istore_2",
- "istore_3",
- "lstore_0",
- "lstore_1",
- "lstore_2",
- "lstore_3",
- "fstore_0",
- "fstore_1",
- "fstore_2",
- "fstore_3",
- "dstore_0",
- "dstore_1",
- "dstore_2",
- "dstore_3",
- "astore_0",
- "astore_1",
- "astore_2",
- "astore_3",
- "iastore",
- "lastore",
- "fastore",
- "dastore",
- "aastore",
- "bastore",
- "castore",
- "sastore",
- "pop",
- "pop2",
- "dup",
- "dup_x1",
- "dup_x2",
- "dup2",
- "dup2_x1",
- "dup2_x2",
- "swap",
- "iadd",
- "ladd",
- "fadd",
- "dadd",
- "isub",
- "lsub",
- "fsub",
- "dsub",
- "imul",
- "lmul",
- "fmul",
- "dmul",
- "idiv",
- "ldiv",
- "fdiv",
- "ddiv",
- "irem",
- "lrem",
- "frem",
- "drem",
- "ineg",
- "lneg",
- "fneg",
- "dneg",
- "ishl",
- "lshl",
- "ishr",
- "lshr",
- "iushr",
- "lushr",
- "iand",
- "land",
- "ior",
- "lor",
- "ixor",
- "lxor",
- "iinc",
- "i2l",
- "i2f",
- "i2d",
- "l2i",
- "l2f",
- "l2d",
- "f2i",
- "f2l",
- "f2d",
- "d2i",
- "d2l",
- "d2f",
- "i2b",
- "i2c",
- "i2s",
- "lcmp",
- "fcmpl",
- "fcmpg",
- "dcmpl",
- "dcmpg",
- "ifeq",
- "ifne",
- "iflt",
- "ifge",
- "ifgt",
- "ifle",
- "if_icmpeq",
- "if_icmpne",
- "if_icmplt",
- "if_icmpge",
- "if_icmpgt",
- "if_icmple",
- "if_acmpeq",
- "if_acmpne",
- "goto",
- "jsr",
- "ret",
- "tableswitch",
- "lookupswitch",
- "ireturn",
- "lreturn",
- "freturn",
- "dreturn",
- "areturn",
- "return",
- "getstatic",
- "putstatic",
- "getfield",
- "putfield",
- "invokevirtual",
- "invokespecial",
- "invokestatic",
- "invokeinterface",
- "invokedynamic",
- "new",
- "newarray",
- "anewarray",
- "arraylength",
- "athrow",
- "checkcast",
- "instanceof",
- "monitorenter",
- "monitorexit",
- "wide",
- "multianewarray",
- "ifnull",
- "ifnonnull",
- "goto_w",
- "jsr_w",
- "breakpoint"
- };
-
- /**
- * Sort log events by start time.
- */
- static Comparator sortByStart = new Comparator() {
-
- public int compare(LogEvent a, LogEvent b) {
- double difference = (a.getStart() - b.getStart());
- if (difference < 0) {
- return -1;
- }
- if (difference > 0) {
- return 1;
- }
- return 0;
- }
-
- @Override
- public boolean equals(Object other) {
- return false;
- }
-
- @Override
- public int hashCode() {
- return 7;
- }
- };
-
- /**
- * Sort log events first by the name of the compiled method, then by start
- * time. In case one of the events has no associated compilation (or the
- * associated compilation has no method name), the event with a compilation
- * and/or name is considered the larger one.
- */
- static Comparator sortByNameAndStart = new Comparator() {
-
- public int compare(LogEvent a, LogEvent b) {
- Compilation c1 = a.getCompilation();
- Compilation c2 = b.getCompilation();
- if (c1 != null && c1.getMethod() != null && c2 != null && c2.getMethod() != null) {
- int result = c1.getMethod().toString().compareTo(c2.getMethod().toString());
- if (result != 0) {
- return result;
- }
- } else if ((c1 == null || c1.getMethod() == null) && c2 != null && c2.getMethod() != null) {
- return -1;
- } else if ((c2 == null || c2.getMethod() == null) && c1 != null && c1.getMethod() != null) {
- return 1;
- }
- return Double.compare(a.getStart(), b.getStart());
- }
-
- public boolean equals(Object other) {
- return false;
- }
-
- @Override
- public int hashCode() {
- return 7;
- }
- };
-
- /**
- * Sort log events by duration.
- */
- static Comparator sortByElapsed = new Comparator() {
-
- public int compare(LogEvent a, LogEvent b) {
- double difference = (a.getElapsedTime() - b.getElapsedTime());
- if (difference < 0) {
- return -1;
- }
- if (difference > 0) {
- return 1;
- }
- return 0;
- }
-
- @Override
- public boolean equals(Object other) {
- return false;
- }
-
- @Override
- public int hashCode() {
- return 7;
- }
- };
-
- /**
- * Shrink-wrapped representation of a JVMState (tailored to meet this
- * tool's needs). It only records a method and bytecode instruction index.
- */
- class Jvms {
- Jvms(Method method, int bci) {
- this.method = method;
- this.bci = bci;
- }
- final public Method method;
- final public int bci;
- final public String toString() {
- return "@" + bci + " " + method;
- }
- }
-
- /**
- * Representation of a lock elimination. Locks, corresponding to
- * synchronized blocks and method calls, may be eliminated if the object in
- * question is guaranteed to be used thread-locally.
- */
- class LockElimination extends BasicLogEvent {
-
- /**
- * Track all locations from which this lock was eliminated.
- */
- ArrayList jvms = new ArrayList<>(1);
-
- /**
- * The kind of lock (coarsened, nested, non-escaping, unknown).
- */
- final String kind;
-
- /**
- * The lock class (unlock, lock, unknown).
- */
- final String classId;
-
- /**
- * The precise type of lock.
- */
- final String tagName;
-
- LockElimination(String tagName, double start, String id, String kind, String classId) {
- super(start, id);
- this.kind = kind;
- this.classId = classId;
- this.tagName = tagName;
- }
-
- @Override
- public void print(PrintStream stream, boolean printID) {
- if (printID) {
- stream.printf("%s ", getId());
- }
- stream.printf("%s %s %s %.3f ", tagName, kind, classId, getStart());
- stream.print(jvms.toString());
- stream.print("\n");
- }
-
- void addJVMS(Method method, int bci) {
- jvms.add(new Jvms(method, bci));
- }
-
- }
-
- /**
- * A list of log events. This is populated with the events found in the
- * compilation log file during parsing.
- */
- private ArrayList events = new ArrayList<>();
-
- /**
- * Map compilation log IDs to type names.
- */
- private HashMap types = new HashMap<>();
-
- /**
- * Map compilation log IDs to methods.
- */
- private HashMap methods = new HashMap<>();
-
- /**
- * Map compilation IDs ({@see #makeId()}) to newly created nmethods.
- */
- private LinkedHashMap nmethods = new LinkedHashMap<>();
-
- /**
- * Map compilation task IDs {@see #makeId()}) to {@link Compilation}
- * objects.
- */
- private HashMap compiles = new HashMap<>();
-
- /**
- * Track compilation failure reasons.
- */
- private String failureReason;
-
- /**
- * The current bytecode instruction index.
- */
- private int current_bci;
-
- /**
- * The current bytecode instruction.
- */
- private int current_bytecode;
-
- /**
- * A sequence of {@link CallSite}s representing a call stack. A scope
- * typically holds several {@link CallSite}s that represent calls
- * originating from that scope.
- *
- * New scopes are typically pushed when parse log events are encountered
- * ({@see #startElement()}) and popped when parsing of a given Java method
- * is done ({@see #endElement()}). Parsing events can be nested. Several
- * other events add information to scopes ({@see #startElement()}).
- */
- private Deque scopes = new ArrayDeque<>();
-
- /**
- * The current compilation.
- */
- private Compilation compile;
-
- /**
- * The {@linkplain CallSite compilation scope} currently in focus.
- */
- private CallSite site;
-
- /**
- * The {@linkplain CallSite method handle call site} currently under
- * observation.
- */
- private CallSite methodHandleSite;
-
- /**
- * Keep track of potentially nested compiler {@linkplain Phase phases}.
- */
- private Deque phaseStack = new ArrayDeque<>();
-
- /**
- * The {@linkplain LockElimination lock elimination event} currently being
- * processed.
- */
- private LockElimination currentLockElimination;
-
- /**
- * The {@linkplain UncommonTrapEvent uncommon trap event} currently being
- * processed.
- */
- private UncommonTrapEvent currentTrap;
-
- /**
- * During the processing of a late inline event, this stack holds the
- * {@link CallSite}s that represent the inlining event's call stack.
- */
- private Deque lateInlineScope;
-
- /**
- * Denote whether a late inlining event is currently being processed.
- */
- private boolean lateInlining;
-
- /**
- * A document locator to provide better error messages: this allows the
- * tool to display in which line of the log file the problem occurred.
- */
- private Locator locator;
-
- /**
- * Callback for the SAX framework to set the document locator.
- */
- @Override
- public void setDocumentLocator(Locator locator) {
- this.locator = locator;
- }
-
- /**
- * Report an internal error explicitly raised, i.e., not derived from an
- * exception.
- *
- * @param msg The error message to report.
- */
- private void reportInternalError(String msg) {
- reportInternalError(msg, null);
- }
-
- /**
- * Report an internal error derived from an exception.
- *
- * @param msg The beginning of the error message to report. The message
- * from the exception will be appended to this.
- * @param e The exception that led to the internal error.
- */
- private void reportInternalError(String msg, Exception e) {
- if (locator != null) {
- msg += " at " + locator.getLineNumber() + ":" + locator.getColumnNumber();
- if (e != null) {
- msg += " - " + e.getMessage();
- }
- }
- if (e != null) {
- throw new Error(msg, e);
- } else {
- throw new Error(msg);
- }
- }
-
- /**
- * Parse a long hexadecimal address into a {@code long} value. As Java only
- * supports positive {@code long} values, extra error handling and parsing
- * logic is provided.
- */
- long parseLong(String l) {
- try {
- return Long.decode(l).longValue();
- } catch (NumberFormatException nfe) {
- int split = l.length() - 8;
- String s1 = "0x" + l.substring(split);
- String s2 = l.substring(0, split);
- long v1 = Long.decode(s1).longValue() & 0xffffffffL;
- long v2 = (Long.decode(s2).longValue() & 0xffffffffL) << 32;
- if (!l.equals("0x" + Long.toHexString(v1 + v2))) {
- System.out.println(l);
- System.out.println(s1);
- System.out.println(s2);
- System.out.println(v1);
- System.out.println(v2);
- System.out.println(Long.toHexString(v1 + v2));
- reportInternalError("bad conversion");
- }
- return v1 + v2;
- }
- }
-
- /**
- * Entry point for log file parsing with a file name.
- *
- * @param file The name of the log file to parse.
- * @param cleanup Whether to perform bad XML cleanup during parsing (this
- * is relevant for some log files generated by the 1.5 JVM).
- * @return a list of {@link LogEvent} instances describing the events found
- * in the log file.
- */
- public static ArrayList parse(String file, boolean cleanup) throws Exception {
- return parse(new FileReader(file), cleanup);
- }
-
- /**
- * Entry point for log file parsing with a file reader.
- * {@see #parse(String,boolean)}
- */
- public static ArrayList parse(Reader reader, boolean cleanup) throws Exception {
- // Create the XML input factory
- SAXParserFactory factory = SAXParserFactory.newInstance();
-
- // Create the XML LogEvent reader
- SAXParser p = factory.newSAXParser();
-
- if (cleanup) {
- // some versions of the log have slightly malformed XML, so clean it
- // up before passing it to SAX
- reader = new LogCleanupReader(reader);
- }
-
- LogParser log = new LogParser();
- try {
- p.parse(new InputSource(reader), log);
- } catch (Throwable th) {
- th.printStackTrace();
- // Carry on with what we've got...
- }
-
- // Associate compilations with their NMethods and other kinds of events
- for (LogEvent e : log.events) {
- if (e instanceof BasicLogEvent) {
- BasicLogEvent ble = (BasicLogEvent) e;
- Compilation c = log.compiles.get(ble.getId());
- if (c == null) {
- if (!(ble instanceof NMethod)) {
- throw new InternalError("only nmethods should have a null compilation, here's a " + ble.getClass());
- }
- continue;
- }
- ble.setCompilation(c);
- if (ble instanceof NMethod) {
- c.setNMethod((NMethod) ble);
- }
- }
- }
-
- return log.events;
- }
-
- /**
- * Retrieve a given attribute's value from a collection of XML tag
- * attributes. Report an error if the requested attribute is not found.
- *
- * @param attr A collection of XML tag attributes.
- * @param name The name of the attribute the value of which is to be found.
- * @return The value of the requested attribute, or {@code null} if it was
- * not found.
- */
- String search(Attributes attr, String name) {
- String result = attr.getValue(name);
- if (result != null) {
- return result;
- } else {
- reportInternalError("can't find " + name);
- return null;
- }
- }
-
- /**
- * Retrieve a given attribute's value from a collection of XML tag
- * attributes. Return a default value if the requested attribute is not
- * found.
- *
- * @param attr A collection of XML tag attributes.
- * @param name The name of the attribute the value of which is to be found.
- * @param defaultValue The default value to return if the attribute is not
- * found.
- * @return The value of the requested attribute, or the default value if it
- * was not found.
- */
- String search(Attributes attr, String name, String defaultValue) {
- String result = attr.getValue(name);
- if (result != null) {
- return result;
- }
- return defaultValue;
- }
-
- /**
- * Map a type ID from the compilation log to an actual type name. In case
- * the type represents an internal array type descriptor, return a
- * Java-level name. If the type ID cannot be mapped to a name, raise an
- * error.
- */
- String type(String id) {
- String result = types.get(id);
- if (result == null) {
- reportInternalError(id);
- }
- String remapped = type2printableMap.get(result);
- if (remapped != null) {
- return remapped;
- }
- return result;
- }
-
- /**
- * Register a mapping from log file type ID to type name.
- */
- void type(String id, String name) {
- assert type(id) == null;
- types.put(id, name);
- }
-
- /**
- * Map a log file type ID to an internal type declarator.
- */
- String sigtype(String id) {
- String result = types.get(id);
- String remapped = type2vmtypeMap.get(result);
- if (remapped != null) {
- return remapped;
- }
- if (result == null) {
- reportInternalError(id);
- }
- if (result.charAt(0) == '[') {
- return result;
- }
- return "L" + result + ";";
- }
-
- /**
- * Retrieve a method based on the log file ID it was registered under.
- * Raise an error if the ID does not map to a method.
- */
- Method method(String id) {
- Method result = methods.get(id);
- if (result == null) {
- reportInternalError(id);
- }
- return result;
- }
-
- /**
- * From a compilation ID and kind, assemble a compilation ID for inclusion
- * in the output.
- *
- * @param atts A collection of XML attributes from which the required
- * attributes are retrieved.
- */
- public String makeId(Attributes atts) {
- String id = atts.getValue("compile_id");
- String kind = atts.getValue("kind");
- if (kind != null && kind.equals("osr")) {
- id += "%";
- }
- return id;
- }
-
- /**
- * Process the start of a compilation log XML element.
- * phase: record the beginning of a compilation phase, pushing
- * it on the {@linkplain #phaseStack phase stack} and collecting
- * information about the compiler graph.
- * phase_done: record the end of a compilation phase, popping it
- * off the {@linkplain #phaseStack phase stack} and collecting information
- * about the compiler graph (number of nodes and live nodes).
- * task: register the start of a new compilation.
- * type: register a type.
- * bc: note the current bytecode index and instruction name,
- * updating {@link #current_bci} and {@link #current_bytecode}.
- * klass: register a type (class).
- * method: register a Java method.
- * call: process a call, populating {@link #site} with the
- * appropriate data.
- * regalloc: record the register allocator's trip count in the
- * {@linkplain #compile current compilation}.
- * inline_fail: record the reason for a failed inline
- * operation.
- * inline_success: record a successful inlining operation,
- * noting the success reason in the {@linkplain #site call site}.
- * failure: note a compilation failure, storing the reason
- * description in {@link #failureReason}.
- * task_done: register the end of a compilation, recording time
- * stamp and success information.
- * make_not_entrant: deal with making a native method
- * non-callable (e.g., during an OSR compilation, if there are still
- * activations) or a zombie (when the method can be deleted).
- * uncommon_trap: process an uncommon trap, setting the
- * {@link #currentTrap} field.
- * eliminate_lock: record the start of a lock elimination,
- * setting the {@link #currentLockElimination} event.
- * late_inline: start processing a late inline decision:
- * initialize the {@linkplain #lateInlineScope inline scope stack}, create
- * an {@linkplain #site initial scope} with a bogus bytecode index and the
- * right inline ID, and push the scope with the inline ID attached. Note
- * that most of late inlining processing happens in
- * {@link #endElement()}.
- * jvms: record a {@linkplain Jvms JVMState}. Depending on the
- * context in which this event is encountered, this can mean adding
- * information to the currently being processed trap, lock elimination, or
- * inlining operation.
- * inline_id: set the inline ID in the
- * {@linkplain #site current call site}.
- * nmethod: record the creation of a new {@link NMethod} and
- * store it in the {@link #nmethods} map.
- * parse: begin parsing a Java method's bytecode and
- * transforming it into an initial compiler IR graph.
- * parse_done: finish parsing a Java method's bytecode.
- *
- */
- @Override
- public void startElement(String uri, String localName, String qname, Attributes atts) {
- if (qname.equals("phase")) {
- Phase p = new Phase(search(atts, "name"),
- Double.parseDouble(search(atts, "stamp")),
- Integer.parseInt(search(atts, "nodes", "0")),
- Integer.parseInt(search(atts, "live", "0")));
- phaseStack.push(p);
- } else if (qname.equals("phase_done")) {
- Phase p = phaseStack.pop();
- String phaseName = search(atts, "name", null);
- if (phaseName != null && !p.getId().equals(phaseName)) {
- System.out.println("phase: " + p.getId());
- reportInternalError("phase name mismatch");
- }
- p.setEnd(Double.parseDouble(search(atts, "stamp")));
- p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
- p.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
- compile.getPhases().add(p);
- } else if (qname.equals("task")) {
- String id = makeId(atts);
-
- // Create the new Compilation instance and populate it with readily
- // available data.
- compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1")));
- compile.setStart(Double.parseDouble(search(atts, "stamp")));
- compile.setICount(search(atts, "count", "0"));
- compile.setBCount(search(atts, "backedge_count", "0"));
- compile.setBCI(Integer.parseInt(search(atts, "osr_bci", "-1")));
- String compiler = atts.getValue("compiler");
- if (compiler == null) {
- compiler = "";
- }
- compile.setCompiler(compiler);
-
- // Extract the name of the compiled method.
- String[] parts = spacePattern.split(atts.getValue("method"));
- String methodName = parts[0] + "::" + parts[1];
-
- // Continue collecting compilation meta-data.
- String kind = atts.getValue("compile_kind");
- if (kind == null) {
- kind = "normal";
- }
- if (kind.equals("osr")) {
- compile.setOsr(true);
- } else if (kind.equals("c2i")) {
- compile.setSpecial("--- adapter " + methodName);
- } else {
- compile.setSpecial(compile.getId() + " " + methodName + " (0 bytes)");
- }
-
- // Build a dummy method to stuff in the Compilation at the
- // beginning.
- Method m = new Method();
- m.setHolder(parts[0]);
- m.setName(parts[1]);
- m.setSignature(parts[2]);
- m.setFlags("0");
- m.setBytes(search(atts, "bytes", "unknown"));
- compile.setMethod(m);
- events.add(compile);
- compiles.put(id, compile);
- site = compile.getCall();
- } else if (qname.equals("type")) {
- type(search(atts, "id"), search(atts, "name"));
- } else if (qname.equals("bc")) {
- current_bci = Integer.parseInt(search(atts, "bci"));
- current_bytecode = Integer.parseInt(search(atts, "code"));
- } else if (qname.equals("klass")) {
- type(search(atts, "id"), search(atts, "name"));
- } else if (qname.equals("method")) {
- String id = search(atts, "id");
- Method m = new Method();
- m.setHolder(type(search(atts, "holder")));
- m.setName(search(atts, "name"));
- m.setReturnType(type(search(atts, "return")));
- String arguments = atts.getValue("arguments");;
- if (arguments == null) {
- m.setSignature("()" + sigtype(atts.getValue("return")));
- } else {
- String[] args = spacePattern.split(arguments);
- StringBuilder sb = new StringBuilder("(");
- for (int i = 0; i < args.length; i++) {
- sb.append(sigtype(args[i]));
- }
- sb.append(")");
- sb.append(sigtype(atts.getValue("return")));
- m.setSignature(sb.toString());
- }
-
- if (search(atts, "unloaded", "0").equals("0")) {
- m.setBytes(search(atts, "bytes"));
- m.setIICount(search(atts, "iicount"));
- m.setFlags(search(atts, "flags"));
- }
- methods.put(id, m);
- } else if (qname.equals("call")) {
- if (methodHandleSite != null) {
- methodHandleSite = null;
- }
- Method m = method(search(atts, "method"));
- if (lateInlining && scopes.size() == 0) {
- // re-attempting already seen call site (late inlining for MH invokes)
- if (m != site.getMethod()) {
- if (current_bci != site.getBci()) {
- System.err.println(m + " bci: " + current_bci);
- System.err.println(site.getMethod() + " bci: " + site.getBci());
- reportInternalError("bci mismatch after late inlining");
- }
- site.setMethod(m);
- }
- } else {
- // We're dealing with a new call site; the called method is
- // likely to be parsed next.
- site = new CallSite(current_bci, m);
- }
- site.setCount(Integer.parseInt(search(atts, "count", "0")));
- String receiver = atts.getValue("receiver");
- if (receiver != null) {
- site.setReceiver(type(receiver));
- site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count")));
- }
- int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0"));
- if (lateInlining && scopes.size() == 0) {
- // The call was already added before this round of late
- // inlining. Ignore.
- } else if (methodHandle == 0) {
- scopes.peek().add(site);
- } else {
- // method handle call site can be followed by another
- // call (in case it is inlined). If that happens we
- // discard the method handle call site. So we keep
- // track of it but don't add it to the list yet.
- methodHandleSite = site;
- }
- } else if (qname.equals("regalloc")) {
- compile.setAttempts(Integer.parseInt(search(atts, "attempts")));
- } else if (qname.equals("inline_fail")) {
- if (methodHandleSite != null) {
- scopes.peek().add(methodHandleSite);
- methodHandleSite = null;
- }
- if (lateInlining && scopes.size() == 0) {
- site.setReason("fail: " + search(atts, "reason"));
- lateInlining = false;
- } else {
- scopes.peek().last().setReason("fail: " + search(atts, "reason"));
- }
- } else if (qname.equals("inline_success")) {
- if (methodHandleSite != null) {
- reportInternalError("method handle site should have been replaced");
- }
- site.setReason("succeed: " + search(atts, "reason"));
- } else if (qname.equals("failure")) {
- failureReason = search(atts, "reason");
- } else if (qname.equals("task_done")) {
- compile.setEnd(Double.parseDouble(search(atts, "stamp")));
- if (Integer.parseInt(search(atts, "success")) == 0) {
- compile.setFailureReason(failureReason);
- failureReason = null;
- }
- } else if (qname.equals("make_not_entrant")) {
- String id = makeId(atts);
- NMethod nm = nmethods.get(id);
- if (nm == null) reportInternalError("nm == null");
- LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
- atts.getValue("zombie") != null, nm);
- events.add(e);
- } else if (qname.equals("uncommon_trap")) {
- String id = atts.getValue("compile_id");
- if (id != null) {
- id = makeId(atts);
- currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")),
- id,
- atts.getValue("reason"),
- atts.getValue("action"),
- Integer.parseInt(search(atts, "count", "0")));
- events.add(currentTrap);
- } else {
- if (atts.getValue("method") != null) {
- // These are messages from ciTypeFlow that don't
- // actually correspond to generated code.
- return;
- }
- try {
- UncommonTrap unc = new UncommonTrap(Integer.parseInt(search(atts, "bci")),
- search(atts, "reason"),
- search(atts, "action"),
- bytecodes[current_bytecode]);
- if (scopes.size() == 0) {
- // There may be a dangling site not yet in scopes after a late_inline
- if (site != null) {
- site.add(unc);
- } else {
- reportInternalError("scope underflow");
- }
- } else {
- scopes.peek().add(unc);
- }
- } catch (Error e) {
- e.printStackTrace();
- }
- }
- } else if (qname.startsWith("eliminate_lock")) {
- String id = atts.getValue("compile_id");
- if (id != null) {
- id = makeId(atts);
- String kind = atts.getValue("kind");
- String classId = atts.getValue("class_id");
- currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId);
- events.add(currentLockElimination);
- }
- } else if (qname.equals("late_inline")) {
- long inlineId = 0;
- try {
- inlineId = Long.parseLong(search(atts, "inline_id"));
- } catch (InternalError ex) {
- // Log files from older hotspots may lack inline_id,
- // and zero is an acceptable substitute that allows processing to continue.
- }
- lateInlineScope = new ArrayDeque<>();
- Method m = method(search(atts, "method"));
- site = new CallSite(-999, m);
- site.setInlineId(inlineId);
- lateInlineScope.push(site);
- } else if (qname.equals("jvms")) {
- //
- if (currentTrap != null) {
- String[] parts = spacePattern.split(atts.getValue("method"));
- currentTrap.addMethodAndBCI(parts[0].replace('/', '.') + '.' + parts[1] + parts[2], Integer.parseInt(atts.getValue("bci")));
- } else if (currentLockElimination != null) {
- currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
- } else if (lateInlineScope != null) {
- current_bci = Integer.parseInt(search(atts, "bci"));
- Method m = method(search(atts, "method"));
- site = new CallSite(current_bci, m);
- lateInlineScope.push(site);
- } else {
- // Ignore ,
- //
- }
- } else if (qname.equals("inline_id")) {
- if (methodHandleSite != null) {
- reportInternalError("method handle site should have been replaced");
- }
- long id = Long.parseLong(search(atts, "id"));
- site.setInlineId(id);
- } else if (qname.equals("nmethod")) {
- String id = makeId(atts);
- NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
- id,
- parseLong(atts.getValue("address")),
- parseLong(atts.getValue("size")));
- nmethods.put(id, nm);
- events.add(nm);
- } else if (qname.equals("parse")) {
- if (failureReason != null && scopes.size() == 0 && !lateInlining) {
- // A compilation just failed, and we're back at a top
- // compilation scope.
- failureReason = null;
- compile.reset();
- site = compile.getCall();
- }
-
- // Error checking.
- if (methodHandleSite != null) {
- reportInternalError("method handle site should have been replaced");
- }
- Method m = method(search(atts, "method")); // this is the method being parsed
- if (lateInlining && scopes.size() == 0) {
- if (site.getMethod() != m) {
- reportInternalError("Unexpected method mismatch during late inlining (method at call site: " +
- site.getMethod() + ", method being parsed: " + m + ")");
- }
- }
-
- if (scopes.size() == 0 && !lateInlining) {
- // The method being parsed is actually the method being
- // compiled; i.e., we're dealing with a compilation top scope,
- // which we must consequently push to the scopes stack.
- compile.setMethod(m);
- scopes.push(site);
- } else {
- // The method being parsed is *not* the current compilation's
- // top scope; i.e., we're dealing with an actual call site
- // in the top scope or somewhere further down a call stack.
- if (site.getMethod() == m) {
- // We're dealing with monomorphic inlining that didn't have
- // to be narrowed down, because the receiver was known
- // beforehand.
- scopes.push(site);
- } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().lastButOne().getMethod()) {
- // We're dealing with an at least bimorphic call site, and
- // the compiler has now decided to parse the last-but-one
- // method. The last one may already have been parsed for
- // inlining.
- scopes.push(scopes.peek().lastButOne());
- } else {
- // The method has been narrowed down to the one we're now
- // going to parse, which is inlined here. It's monomorphic
- // inlining, but was not immediately clear as such.
- //
- // C1 prints multiple method tags during inlining when it
- // narrows the method being inlined. Example:
- // ...
- //
- //
- //
- //
- //
- // ...
- site.setMethod(m);
- scopes.push(site);
- }
- }
- } else if (qname.equals("parse_done")) {
- // Attach collected information about IR nodes to the current
- // parsing scope before it's popped off the stack in endElement()
- // (see where the parse tag is handled).
- CallSite call = scopes.peek();
- call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
- call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
- call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
- }
- }
-
- /**
- * Process the end of a compilation log XML element.
- * parse: finish transforming a Java method's bytecode
- * instructions to an initial compiler IR graph.
- * uncommon_trap: record the end of processing an uncommon trap,
- * resetting {@link #currentTrap}.
- * eliminate_lock: record the end of a lock elimination,
- * resetting {@link #currentLockElimination}.
- * late_inline: the closing tag for late_inline does not denote
- * the end of a late inlining operation, but the end of the descriptive log
- * data given at its beginning. That is, we're now in the position to
- * assemble details about the inlining chain (bytecode instruction index in
- * caller, called method). The {@link #lateInlining} flag is set to
- * {@code true} here. (It will be reset when parsing the inlined methods is
- * done; this happens for the successful case in this method as well, when
- * {@code parse} elements are processed; and for inlining failures, in
- * {@link #startElement()}, when {@code inline_fail} elements are
- * processed.)
- * task: perform cleanup at the end of a compilation. Note that
- * the explicit {@code task_done} event is handled in
- * {@link #startElement()}.
- *
- */
- @Override
- public void endElement(String uri, String localName, String qname) {
- try {
- if (qname.equals("parse")) {
- // Finish dealing with the current call scope. If no more are
- // left, no late inlining can be going on.
- scopes.pop();
- if (scopes.size() == 0) {
- lateInlining = false;
- }
- } else if (qname.equals("uncommon_trap")) {
- currentTrap = null;
- } else if (qname.startsWith("eliminate_lock")) {
- currentLockElimination = null;
- } else if (qname.equals("late_inline")) {
- // Populate late inlining info.
- if (scopes.size() != 0) {
- reportInternalError("scopes should be empty for late inline");
- }
- // late inline scopes are specified in reverse order:
- // compiled method should be on top of stack.
- CallSite caller = lateInlineScope.pop();
- Method m = compile.getMethod();
- if (!m.equals(caller.getMethod())) {
- reportInternalError(String.format("call site and late_inline info don't match:\n method %s\n caller method %s, bci %d", m, caller.getMethod(), current_bci));
- }
-
- // Walk down the inlining chain and assemble bci+callee info.
- // This needs to be converted from caller+bci info contained in
- // the late_inline data.
- CallSite lateInlineSite = compile.getLateInlineCall();
- ArrayDeque thisCallScopes = new ArrayDeque<>();
- do {
- current_bci = caller.getBci();
- // Next inlined call.
- caller = lateInlineScope.pop();
- CallSite callee = new CallSite(current_bci, caller.getMethod());
- callee.setInlineId(caller.getInlineId());
- thisCallScopes.addLast(callee);
- lateInlineSite.add(callee);
- lateInlineSite = callee;
- } while (!lateInlineScope.isEmpty());
-
- site = compile.getCall().findCallSite(thisCallScopes);
- if (site == null) {
- // Call site could not be found - report the problem in detail.
- System.err.println("call scopes:");
- for (CallSite c : thisCallScopes) {
- System.err.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId());
- }
- CallSite c = thisCallScopes.getLast();
- if (c.getInlineId() != 0) {
- System.err.println("Looking for call site in entire tree:");
- ArrayDeque stack = compile.getCall().findCallSite2(c);
- for (CallSite c2 : stack) {
- System.err.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId());
- }
- }
- System.err.println(caller.getMethod() + " bci: " + current_bci);
- reportInternalError("couldn't find call site");
- }
- lateInlining = true;
-
- if (caller.getBci() != -999) {
- System.out.println(caller.getMethod());
- reportInternalError("broken late_inline info");
- }
- if (site.getMethod() != caller.getMethod()) {
- if (site.getInlineId() == caller.getInlineId()) {
- site.setMethod(caller.getMethod());
- } else {
- System.out.println(site.getMethod());
- System.out.println(caller.getMethod());
- reportInternalError("call site and late_inline info don't match");
- }
- }
- // late_inline is followed by parse with scopes.size() == 0,
- // 'site' will be pushed to scopes.
- lateInlineScope = null;
- } else if (qname.equals("task")) {
- types.clear();
- methods.clear();
- site = null;
- }
- } catch (Exception e) {
- reportInternalError("exception while processing end element", e);
- }
- }
-
- //
- // Handlers for problems that occur in XML parsing itself.
- //
-
- @Override
- public void warning(org.xml.sax.SAXParseException e) {
- System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
- e.printStackTrace();
- }
-
- @Override
- public void error(org.xml.sax.SAXParseException e) {
- System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
- e.printStackTrace();
- }
-
- @Override
- public void fatalError(org.xml.sax.SAXParseException e) {
- System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
- e.printStackTrace();
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-
-/**
- * In a compilation log, represent the event of making a given compiled method
- * not-entrant, e.g., during an OSR compilation.
- */
-class MakeNotEntrantEvent extends BasicLogEvent {
-
- /**
- * Denote whether the method is marked as a zombie, i.e., no further
- * activations exist.
- */
- private final boolean zombie;
-
- /**
- * The method in question.
- */
- private NMethod nmethod;
-
- MakeNotEntrantEvent(double s, String i, boolean z, NMethod nm) {
- super(s, i);
- zombie = z;
- nmethod = nm;
- }
-
- public NMethod getNMethod() {
- return nmethod;
- }
-
- public void print(PrintStream stream, boolean printID) {
- if (isZombie()) {
- stream.printf("%s make_zombie\n", getId());
- } else {
- stream.printf("%s make_not_entrant\n", getId());
- }
- }
-
- public boolean isZombie() {
- return zombie;
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Method.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.util.Arrays;
-
-import static com.sun.hotspot.tools.compiler.Constants.*;
-
-/**
- * Representation of a Java method in a compilation log.
- */
-public class Method {
-
- /**
- * The name of the class holding the method.
- */
- private String holder;
-
- /**
- * The method's name.
- */
- private String name;
-
- /**
- * The return type of the method, as a fully qualified (source-level) class
- * or primitive type name.
- */
- private String returnType;
-
- /**
- * The method's signature, in internal form.
- */
- private String signature;
-
- /**
- * The length of the method's byte code.
- */
- private String bytes;
-
- /**
- * The number of times this method was invoked in the interpreter.
- */
- private String iicount;
-
- /**
- * The method's flags, in the form of a {@code String} representing the
- * {@code int} encoding them.
- */
- private String flags;
-
- /**
- * Decode the {@link flags} numerical string to a format for console
- * output. The result does not honour all possible flags but includes
- * information about OSR compilation.
- *
- * @param osr_bci the byte code index at which an OSR compilation takes
- * place, or -1 if the compilation is not an OSR one.
- */
- String decodeFlags(int osr_bci) {
- int f = Integer.parseInt(getFlags());
- char[] c = new char[4];
- Arrays.fill(c, ' ');
- if (osr_bci >= 0) {
- c[0] = '%';
- }
- if ((f & JVM_ACC_SYNCHRONIZED) != 0) {
- c[1] = 's';
- }
- return new String(c);
- }
-
- /**
- * Format this method for console output.
- *
- * @param osr_bci the byte code index at which OSR takes place, or -1 if no
- * OSR compilation is going on.
- */
- String format(int osr_bci) {
- if (osr_bci >= 0) {
- return getHolder() + "::" + getName() + " @ " + osr_bci + " (" + getBytes() + " bytes)";
- } else {
- return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)";
- }
- }
-
- @Override
- public String toString() {
- return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)";
- }
-
- public String getFullName() {
- return getHolder().replace('/', '.') + "." + getName() + signature;
- }
-
- public String getHolder() {
- return holder;
- }
-
- public void setHolder(String holder) {
- this.holder = holder;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getReturnType() {
- return returnType;
- }
-
- public void setReturnType(String returnType) {
- this.returnType = returnType;
- }
-
- public String getSignature() {
- return signature;
- }
-
- public void setSignature(String signature) {
- this.signature = signature.replace('/', '.');
- }
-
- public String getArguments() {
- return signature.substring(0, signature.indexOf(')') + 1);
- }
-
- public String getBytes() {
- return bytes;
- }
-
- public void setBytes(String bytes) {
- this.bytes = bytes;
- }
-
- public String getIICount() {
- return iicount;
- }
-
- public void setIICount(String iicount) {
- this.iicount = iicount;
- }
-
- public String getFlags() {
- return flags;
- }
-
- public void setFlags(String flags) {
- this.flags = flags;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Method) {
- Method other = (Method) o;
- return holder.equals(other.holder) && name.equals(other.name) && signature.equals(other.signature);
- }
- return false;
- }
-
- public int hashCode() {
- return holder.hashCode() ^ name.hashCode();
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-
-/**
- * A compilation log event that is signalled whenever a new nmethod (a native
- * method, a compilation result) is created.
- */
-public class NMethod extends BasicLogEvent {
-
- /**
- * The nmethod's starting address in memory.
- */
- private long address;
-
- /**
- * The nmethod's size in bytes.
- */
- private long size;
-
- NMethod(double s, String i, long a, long sz) {
- super(s, i);
- address = a;
- size = sz;
- }
-
- public void print(PrintStream out, boolean printID) {
- // XXX Currently we do nothing
- // throw new InternalError();
- }
-
- public long getAddress() {
- return address;
- }
-
- public void setAddress(long address) {
- this.address = address;
- }
-
- public long getSize() {
- return size;
- }
-
- public void setSize(long size) {
- this.size = size;
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-
-/**
- * Representation of a compilation phase as a log event.
- */
-public class Phase extends BasicLogEvent {
-
- /**
- * The number of nodes in the compilation at the beginning of this phase.
- */
- private final int startNodes;
-
- /**
- * The number of nodes in the compilation at the end of this phase.
- */
- private int endNodes;
-
- /**
- * The number of live nodes in the compilation at the beginning of this
- * phase.
- */
- private final int startLiveNodes;
-
- /**
- * The number of live nodes in the compilation at the end of this phase.
- */
- private int endLiveNodes;
-
- Phase(String n, double s, int nodes, int live) {
- super(s, n);
- startNodes = nodes;
- startLiveNodes = live;
- }
-
- int getNodes() {
- return getEndNodes() - getStartNodes();
- }
-
- void setEndNodes(int n) {
- endNodes = n;
- }
-
- public String getName() {
- return getId();
- }
-
- public int getStartNodes() {
- return startNodes;
- }
-
- public int getEndNodes() {
- return endNodes;
- }
-
- /**
- * The number of live nodes added by this phase.
- */
- int getAddedLiveNodes() {
- return getEndLiveNodes() - getStartLiveNodes();
- }
-
- void setEndLiveNodes(int n) {
- endLiveNodes = n;
- }
-
- public int getStartLiveNodes() {
- return startLiveNodes;
- }
-
- public int getEndLiveNodes() {
- return endLiveNodes;
- }
-
- @Override
- public void print(PrintStream stream, boolean printID) {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-
-/**
- * An instance of this class represents an uncommon trap associated with a
- * given bytecode instruction. An uncommon trap is described in terms of its
- * reason and action to be taken. An instance of this class is always relative
- * to a specific method and only contains the relevant bytecode instruction
- * index.
- */
-class UncommonTrap {
-
- private int bci;
- private String reason;
- private String action;
- private String bytecode;
-
- public UncommonTrap(int b, String r, String a, String bc) {
- bci = b;
- reason = r;
- action = a;
- bytecode = bc;
- }
-
- public int getBCI() {
- return bci;
- }
-
- public String getReason() {
- return reason;
- }
-
- public String getAction() {
- return action;
- }
-
- public String getBytecode() {
- return bytecode;
- }
-
- void emit(PrintStream stream, int indent) {
- for (int i = 0; i < indent; i++) {
- stream.print(' ');
- }
- }
-
- public void print(PrintStream stream, int indent) {
- emit(stream, indent);
- stream.println(this);
- }
-
- public String toString() {
- return "@ " + bci + " " + getBytecode() + " uncommon trap " + getReason() + " " + getAction();
- }
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java
--- a/src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Thu Nov 30 20:37:20 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
-
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Represents an uncommon trap encountered during a compilation.
- */
-class UncommonTrapEvent extends BasicLogEvent {
-
- private final String reason;
- private final String action;
-
- /**
- * Denote how many times this trap has been encountered.
- */
- private int count;
-
- /**
- * The name of the bytecode instruction at which the trap occurred.
- */
- private String bytecode;
-
- private List jvmsMethods = new ArrayList<>();
-
- private List jvmsBCIs = new ArrayList<>();
-
- UncommonTrapEvent(double s, String i, String r, String a, int c) {
- super(s, i);
- reason = r;
- action = a;
- count = c;
- }
-
- public void updateCount(UncommonTrapEvent trap) {
- setCount(Math.max(getCount(), trap.getCount()));
- }
-
- public void print(PrintStream stream, boolean printID) {
- if (printID) {
- stream.print(getId() + " ");
- }
- stream.printf("uncommon trap %s %s %s\n", bytecode, getReason(), getAction());
- int indent = 2;
- for (int j = 0; j < jvmsMethods.size(); j++) {
- for (int i = 0; i < indent; i++) {
- stream.print(' ');
- }
- stream.println("@ " + jvmsBCIs.get(j) + " " + jvmsMethods.get(j));
- indent += 2;
- }
- }
-
-
- public String getReason() {
- return reason;
- }
-
- public String getAction() {
- return action;
- }
-
- public int getCount() {
- return count;
- }
-
- public void setCount(int count) {
- this.count = count;
- }
-
- /**
- * Set the compilation for this event. This involves identifying the call
- * site to which this uncommon trap event belongs. In addition to setting
- * the {@link #compilation} link, this method will consequently also set
- * the {@link #bytecode} field.
- */
- public void setCompilation(Compilation compilation) {
- super.setCompilation(compilation);
- // Attempt to associate a bytecode with with this trap
- CallSite site = compilation.getCall();
- int i = 0;
- try {
- List traps = site.getTraps();
- while (i + 1 < jvmsMethods.size()) {
- if (!jvmsMethods.get(i).equals(site.getMethod().getFullName())) {
- throw new InternalError(jvmsMethods.get(i) + " != " + site.getMethod().getFullName());
- }
- CallSite result = null;
- for (CallSite call : site.getCalls()) {
- if (call.getBci() == jvmsBCIs.get(i) &&
- call.getMethod().getFullName().equals(jvmsMethods.get(i + 1)) &&
- call.getReceiver() == null) {
- result = call;
- i++;
- break;
- }
- }
- if (result == null) {
- throw new InternalError("couldn't find call site");
- }
- site = result;
- traps = site.getTraps();
- }
- for (UncommonTrap trap : traps) {
- if (trap.getBCI() == jvmsBCIs.get(i) &&
- trap.getReason().equals(getReason()) &&
- trap.getAction().equals(getAction())) {
- bytecode = trap.getBytecode();
- return;
- }
- }
- throw new InternalError("couldn't find bytecode");
- } catch (Exception e) {
- bytecode = "";
- }
- }
-
- public void addMethodAndBCI(String method, int bci) {
- jvmsMethods.add(0, method);
- jvmsBCIs.add(0, bci);
- }
-
-}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/BasicLogEvent.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/BasicLogEvent.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * Provide basic data structures and behaviour for {@link LogEvent}s.
+ */
+public abstract class BasicLogEvent implements LogEvent {
+
+ /**
+ * The event's ID. This is a number; we represent it as a string for
+ * convenience.
+ */
+ protected final String id;
+
+ /**
+ * The event's start time.
+ */
+ protected final double start;
+
+ /**
+ * The event's end time.
+ */
+ protected double end;
+
+ /**
+ * The compilation during which this event was signalled.
+ */
+ protected Compilation compilation;
+
+ BasicLogEvent(double start, String id) {
+ this.start = start;
+ this.end = start;
+ this.id = id;
+ }
+
+ public final double getStart() {
+ return start;
+ }
+
+ public final double getEnd() {
+ return end;
+ }
+
+ public final void setEnd(double end) {
+ this.end = end;
+ }
+
+ public final double getElapsedTime() {
+ return ((int) ((getEnd() - getStart()) * 1000)) / 1000.0;
+ }
+
+ public final String getId() {
+ return id;
+ }
+
+ public final Compilation getCompilation() {
+ return compilation;
+ }
+
+ /**
+ * Set the compilation for this event. This is not a {@code final} method
+ * as it is overridden in {@link UncommonTrapEvent}.
+ */
+ public void setCompilation(Compilation compilation) {
+ this.compilation = compilation;
+ }
+
+ abstract public void print(PrintStream stream, boolean printID);
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/CallSite.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/CallSite.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Representation of a compilation scope in a compilation log. This class is a
+ * hybrid: its instances can represent original scopes of methods being
+ * compiled, but are also used to represent call sites in given methods.
+ */
+public class CallSite {
+
+ /**
+ * The index of the call in the caller. This will be 0 if this instance
+ * represents a compilation root.
+ */
+ private int bci;
+
+ /**
+ * The method that is called at this call site. This will be {@code null}
+ * if this instance represents a compilation root.
+ */
+ private Method method;
+
+ /**
+ * The invocation count for this call site.
+ */
+ private int count;
+
+ /**
+ * The receiver type of the call represented by this instance, if known.
+ */
+ private String receiver;
+
+ /**
+ * In case the {@linkplain receiver receiver type} of the call represented
+ * by this instance is known, this is how often the type was encountered.
+ */
+ private int receiver_count;
+
+ /**
+ * The reason for a success or failure of an inlining operation at this
+ * call site.
+ */
+ private String reason;
+
+ /**
+ * A list of all calls in this compilation scope.
+ */
+ private List calls;
+
+ /**
+ * Number of nodes in the graph at the end of parsing this compilation
+ * scope.
+ */
+ private int endNodes;
+
+ /**
+ * Number of live nodes in the graph at the end of parsing this compilation
+ * scope.
+ */
+ private int endLiveNodes;
+
+ /**
+ * Time in seconds since VM startup at which parsing this compilation scope
+ * ended.
+ */
+ private double timeStamp;
+
+ /**
+ * The inline ID in case the call represented by this instance is inlined,
+ * 0 otherwise.
+ */
+ private long inlineId;
+
+ /**
+ * List of uncommon traps in this compilation scope.
+ */
+ private List traps;
+
+ /**
+ * Default constructor: used to create an instance that represents the top
+ * scope of a compilation.
+ */
+ CallSite() {}
+
+ /**
+ * Constructor to create an instance that represents an actual method call.
+ */
+ CallSite(int bci, Method m) {
+ this.bci = bci;
+ this.method = m;
+ }
+
+ /**
+ * Add a call site to the compilation scope represented by this instance.
+ */
+ void add(CallSite site) {
+ if (getCalls() == null) {
+ calls = new ArrayList<>();
+ }
+ getCalls().add(site);
+ }
+
+ /**
+ * Return the last of the {@linkplain #getCalls() call sites} in this
+ * compilation scope.
+ */
+ CallSite last() {
+ return getCalls().get(getCalls().size() - 1);
+ }
+
+ /**
+ * Return the last-but-one of the {@linkplain #getCalls() call sites} in
+ * this compilation scope.
+ */
+ CallSite lastButOne() {
+ return getCalls().get(getCalls().size() - 2);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (getReason() == null) {
+ sb.append(" @ " + getBci() + " " + getMethod());
+ } else {
+ sb.append("- @ " + getBci() + " " + getMethod() + " " + getReason());
+ }
+ sb.append("\n");
+ if (getCalls() != null) {
+ for (CallSite site : getCalls()) {
+ sb.append(site);
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ public void print(PrintStream stream) {
+ print(stream, 0, true, false);
+ }
+
+ void emit(PrintStream stream, int indent) {
+ for (int i = 0; i < indent; i++) {
+ stream.print(' ');
+ }
+ }
+
+ public void print(PrintStream stream, int indent, boolean printInlining, boolean printUncommonTraps) {
+ emit(stream, indent);
+ String m = getMethod().getHolder() + "::" + getMethod().getName();
+ if (getReason() == null) {
+ stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
+ } else {
+ stream.print(" @ " + getBci() + " " + m + " " + getReason());
+ }
+ stream.printf(" (end time: %6.4f", getTimeStamp());
+ if (getEndNodes() > 0) {
+ stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes());
+ }
+ stream.println(")");
+
+ if (getReceiver() != null) {
+ emit(stream, indent + 4);
+ stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" +
+ (getReceiverCount() * 100 / getCount()) + "%)");
+ }
+ if (printInlining && getCalls() != null) {
+ for (CallSite site : getCalls()) {
+ site.print(stream, indent + 2, printInlining, printUncommonTraps);
+ }
+ }
+ if (printUncommonTraps && getTraps() != null) {
+ for (UncommonTrap site : getTraps()) {
+ site.print(stream, indent + 2);
+ }
+ }
+ }
+
+ public int getBci() {
+ return bci;
+ }
+
+ public void setBci(int bci) {
+ this.bci = bci;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public void setMethod(Method method) {
+ this.method = method;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public String getReceiver() {
+ return receiver;
+ }
+
+ public void setReceiver(String receiver) {
+ this.receiver = receiver;
+ }
+
+ public int getReceiverCount() {
+ return receiver_count;
+ }
+
+ public void setReceiver_count(int receiver_count) {
+ this.receiver_count = receiver_count;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ public List getCalls() {
+ return calls;
+ }
+
+ public List getTraps() {
+ return traps;
+ }
+
+ void add(UncommonTrap e) {
+ if (traps == null) {
+ traps = new ArrayList();
+ }
+ traps.add(e);
+ }
+
+ void setEndNodes(int n) {
+ endNodes = n;
+ }
+
+ public int getEndNodes() {
+ return endNodes;
+ }
+
+ void setEndLiveNodes(int n) {
+ endLiveNodes = n;
+ }
+
+ public int getEndLiveNodes() {
+ return endLiveNodes;
+ }
+
+ void setTimeStamp(double time) {
+ timeStamp = time;
+ }
+
+ public double getTimeStamp() {
+ return timeStamp;
+ }
+
+ /**
+ * Check whether this call site matches another. Every late inline call
+ * site has a unique inline ID. If the call site we're looking for has one,
+ * then use it; otherwise rely on method name and byte code index.
+ */
+ private boolean matches(CallSite other) {
+ if (other.inlineId != 0) {
+ return inlineId == other.inlineId;
+ }
+ return method.equals(other.method) && bci == other.bci;
+ }
+
+ /**
+ * Locate a late inline call site: find, in this instance's
+ * {@linkplain #calls call sites}, the one furthest down the given call
+ * stack.
+ *
+ * Multiple chains of identical call sites with the same method name / bci
+ * combination are possible, so we have to try them all until we find the
+ * late inline call site that has a matching inline ID.
+ *
+ * @return a matching call site, or {@code null} if none was found.
+ */
+ public CallSite findCallSite(ArrayDeque sites) {
+ if (calls == null) {
+ return null;
+ }
+ CallSite site = sites.pop();
+ for (CallSite c : calls) {
+ if (c.matches(site)) {
+ if (!sites.isEmpty()) {
+ CallSite res = c.findCallSite(sites);
+ if (res != null) {
+ sites.push(site);
+ return res;
+ }
+ } else {
+ sites.push(site);
+ return c;
+ }
+ }
+ }
+ sites.push(site);
+ return null;
+ }
+
+ /**
+ * Locate a late inline call site in the tree spanned by all this instance's
+ * {@linkplain #calls call sites}, and return the sequence of call sites
+ * (scopes) leading to that late inline call site.
+ */
+ public ArrayDeque findCallSite2(CallSite site) {
+ if (calls == null) {
+ return null;
+ }
+
+ for (CallSite c : calls) {
+ if (c.matches(site)) {
+ ArrayDeque stack = new ArrayDeque<>();
+ stack.push(c);
+ return stack;
+ } else {
+ ArrayDeque stack = c.findCallSite2(site);
+ if (stack != null) {
+ stack.push(c);
+ return stack;
+ }
+ }
+ }
+ return null;
+ }
+
+ public long getInlineId() {
+ return inlineId;
+ }
+
+ public void setInlineId(long inlineId) {
+ this.inlineId = inlineId;
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Compilation.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Compilation.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+
+/**
+ * One particular compilation, represented in the compilation log file as a
+ * {@code task} element.
+ */
+public class Compilation implements LogEvent {
+
+ /**
+ * The compilation ID.
+ */
+ private int id;
+
+ /**
+ * Whether this is a compilation for on-stack replacement (OSR).
+ */
+ private boolean osr;
+
+ /**
+ * The method being compiled.
+ */
+ private Method method;
+
+ /**
+ * The {@linkplain CallSite scope} of this compilation. This is created as
+ * an empty {@link CallSite} instance, to be filled with data (and
+ * meaning) later on.
+ */
+ private CallSite call = new CallSite();
+
+ /**
+ * In case a {@code late_inline} event occurs during the compilation, this
+ * field holds the information about it.
+ */
+ private CallSite lateInlineCall = new CallSite();
+
+ /**
+ * The bytecode instruction index for on-stack replacement compilations; -1
+ * if this is not an OSR compilation.
+ */
+ private int bci;
+
+ /**
+ * The method under compilation's invocation count.
+ */
+ private String icount;
+
+ /**
+ * The method under compilation's backedge count.
+ */
+ private String bcount;
+
+ /**
+ * Additional information for special compilations (e.g., adapters).
+ */
+ private String special;
+
+ /**
+ * The name of the compiler performing this compilation.
+ */
+ private String compiler;
+
+ /**
+ * Start time stamp.
+ */
+ private double start;
+
+ /**
+ * End time stamp.
+ */
+ private double end;
+
+ /**
+ * Trip count of the register allocator.
+ */
+ private int attempts;
+
+ /**
+ * The compilation result (a native method).
+ */
+ private NMethod nmethod;
+
+ /**
+ * The phases through which this compilation goes.
+ */
+ private ArrayList phases = new ArrayList<>(4);
+
+ /**
+ * In case this compilation fails, the reason for that.
+ */
+ private String failureReason;
+
+ Compilation(int id) {
+ this.id = id;
+ }
+
+ void reset() {
+ call = new CallSite();
+ lateInlineCall = new CallSite();
+ phases = new ArrayList<>(4);
+ }
+
+ /**
+ * Get a compilation phase by name, or {@code null}.
+ *
+ * @param s the name of the phase to retrieve in this compilation.
+ *
+ * @return a compilation phase, or {@code null} if no phase with the given
+ * name is found.
+ */
+ Phase getPhase(String s) {
+ for (Phase p : getPhases()) {
+ if (p.getName().equals(s)) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ double getRegallocTime() {
+ return getPhase("regalloc").getElapsedTime();
+ }
+
+ public double getStart() {
+ return start;
+ }
+
+ public void setCompiler(String compiler) {
+ this.compiler = compiler;
+ }
+
+ public String getCompiler() {
+ return compiler;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getId());
+ sb.append(" ");
+ sb.append(getCompiler());
+ sb.append(" ");
+ sb.append(getMethod());
+ sb.append(" ");
+ sb.append(getIcount());
+ sb.append("+");
+ sb.append(getBcount());
+ sb.append("\n");
+ if (getCall() != null && getCall().getCalls() != null) {
+ for (CallSite site : getCall().getCalls()) {
+ sb.append(site);
+ sb.append("\n");
+ }
+ }
+ if (getLateInlineCall().getCalls() != null) {
+ sb.append("late inline:\n");
+ for (CallSite site : getLateInlineCall().getCalls()) {
+ sb.append(site);
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ public void printShort(PrintStream stream) {
+ if (getMethod() == null) {
+ stream.println(getSpecial());
+ } else {
+ int bc = isOsr() ? getBCI() : -1;
+ stream.print(getId() + getMethod().decodeFlags(bc) + " " + compiler + " " + getMethod().format(bc));
+ }
+ }
+
+ public void print(PrintStream stream, boolean printID) {
+ print(stream, 0, printID, true, false);
+ }
+
+ public void print(PrintStream stream, boolean printID, boolean printInlining) {
+ print(stream, 0, printID, printInlining, false);
+ }
+
+ public void print(PrintStream stream, boolean printID, boolean printInlining, boolean printUncommonTraps) {
+ print(stream, 0, printID, printInlining, printUncommonTraps);
+ }
+
+ public void print(PrintStream stream, int indent, boolean printID, boolean printInlining, boolean printUncommonTraps) {
+ if (getMethod() == null) {
+ stream.println(getSpecial());
+ } else {
+ if (printID) {
+ stream.print(getId());
+ }
+ int bc = isOsr() ? getBCI() : -1;
+ stream.print(getMethod().decodeFlags(bc) + " " + compiler + " " + getMethod().format(bc));
+ stream.println();
+ if (getFailureReason() != null) {
+ stream.println("COMPILE SKIPPED: " + getFailureReason() + " (not retryable)");
+ }
+ if (printInlining && call.getCalls() != null) {
+ for (CallSite site : call.getCalls()) {
+ site.print(stream, indent + 2, printInlining, printUncommonTraps);
+ }
+ }
+ if (printUncommonTraps && call.getTraps() != null) {
+ for (UncommonTrap site : call.getTraps()) {
+ site.print(stream, indent + 2);
+ }
+ }
+ if (printInlining && lateInlineCall.getCalls() != null) {
+ stream.println("late inline:");
+ for (CallSite site : lateInlineCall.getCalls()) {
+ site.print(stream, indent + 2, printInlining, printUncommonTraps);
+ }
+ }
+ }
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public boolean isOsr() {
+ return osr;
+ }
+
+ public void setOsr(boolean osr) {
+ this.osr = osr;
+ }
+
+ public int getBCI() {
+ return bci;
+ }
+
+ public void setBCI(int osrBci) {
+ this.bci = osrBci;
+ }
+
+ public String getIcount() {
+ return icount;
+ }
+
+ public void setICount(String icount) {
+ this.icount = icount;
+ }
+
+ public String getBcount() {
+ return bcount;
+ }
+
+ public void setBCount(String bcount) {
+ this.bcount = bcount;
+ }
+
+ public String getSpecial() {
+ return special;
+ }
+
+ public void setSpecial(String special) {
+ this.special = special;
+ }
+
+ public void setStart(double start) {
+ this.start = start;
+ }
+
+ public double getEnd() {
+ return end;
+ }
+
+ public void setEnd(double end) {
+ this.end = end;
+ }
+
+ public int getAttempts() {
+ return attempts;
+ }
+
+ public void setAttempts(int attempts) {
+ this.attempts = attempts;
+ }
+
+ public NMethod getNMethod() {
+ return nmethod;
+ }
+
+ public void setNMethod(NMethod NMethod) {
+ this.nmethod = NMethod;
+ }
+
+ public ArrayList getPhases() {
+ return phases;
+ }
+
+ public String getFailureReason() {
+ return failureReason;
+ }
+
+ public void setFailureReason(String failureReason) {
+ this.failureReason = failureReason;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ /**
+ * Set the method under compilation. If it is already set, ignore the
+ * argument to avoid changing the method by post-parse inlining info.
+ *
+ * @param method the method under compilation. May be ignored.
+ */
+ public void setMethod(Method method) {
+ if (getMethod() == null) {
+ this.method = method;
+ }
+ }
+
+ public CallSite getCall() {
+ return call;
+ }
+
+ public CallSite getLateInlineCall() {
+ return lateInlineCall;
+ }
+
+ public double getElapsedTime() {
+ return end - start;
+ }
+
+ public Compilation getCompilation() {
+ return this;
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Constants.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Constants.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009, 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.sun.hotspot.tools.compiler;
+
+interface Constants {
+ static final int JVM_ACC_PUBLIC = 0x0001; /* visible to everyone */
+ static final int JVM_ACC_PRIVATE = 0x0002; /* visible only to the defining class */
+ static final int JVM_ACC_PROTECTED = 0x0004; /* visible to subclasses */
+ static final int JVM_ACC_STATIC = 0x0008; /* instance variable is static */
+ static final int JVM_ACC_FINAL = 0x0010; /* no further subclassing, overriding */
+ static final int JVM_ACC_SYNCHRONIZED = 0x0020; /* wrap method call in monitor lock */
+ static final int JVM_ACC_SUPER = 0x0020; /* funky handling of invokespecial */
+ static final int JVM_ACC_VOLATILE = 0x0040; /* can not cache in registers */
+ static final int JVM_ACC_BRIDGE = 0x0040; /* bridge method generated by compiler */
+ static final int JVM_ACC_TRANSIENT = 0x0080; /* not persistent */
+ static final int JVM_ACC_VARARGS = 0x0080; /* method declared with variable number of args */
+ static final int JVM_ACC_NATIVE = 0x0100; /* implemented in C */
+ static final int JVM_ACC_INTERFACE = 0x0200; /* class is an interface */
+ static final int JVM_ACC_ABSTRACT = 0x0400; /* no definition provided */
+ static final int JVM_ACC_STRICT = 0x0800; /* strict floating point */
+ static final int JVM_ACC_SYNTHETIC = 0x1000; /* compiler-generated class, method or field */
+ static final int JVM_ACC_ANNOTATION = 0x2000; /* annotation type */
+ static final int JVM_ACC_ENUM = 0x4000; /* field is declared as element of enum */
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCleanupReader.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCleanupReader.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.*;
+import java.util.regex.*;
+
+/**
+ * This class is a filter class to deal with malformed XML that used
+ * to be produced by the JVM when generating LogCompilation. In 1.6
+ * and later releases it shouldn't be required.
+ */
+class LogCleanupReader extends Reader {
+
+ private Reader reader;
+
+ private char[] buffer = new char[4096];
+
+ private int bufferCount;
+
+ private int bufferOffset;
+
+ private char[] line = new char[1024];
+
+ private int index;
+
+ private int length;
+
+ private char[] one = new char[1];
+
+ LogCleanupReader(Reader r) {
+ reader = r;
+ }
+
+ static final private Matcher duplicateCompileID = Pattern.compile(".+ compile_id='[0-9]+'.*( compile_id='[0-9]+)").matcher("");
+ static final private Matcher compilerName = Pattern.compile("' (C[12]) compile_id=").matcher("");
+ static final private Matcher destroyVM = Pattern.compile("'(destroy_vm)/").matcher("");
+
+ /**
+ * The log cleanup takes place in this method. If any of the three patterns
+ * ({@link #duplicateCompileID}, {@link #compilerName}, {@link #destroyVM})
+ * match, that indicates a problem in the log. The cleanup is performed by
+ * correcting the input line and writing it back into the {@link #line}
+ * buffer.
+ */
+ private void fill() throws IOException {
+ rawFill();
+ if (length != -1) {
+ boolean changed = false;
+ String s = new String(line, 0, length);
+
+ compilerName.reset(s);
+ if (compilerName.find()) {
+ s = s.substring(0, compilerName.start(1)) + s.substring(compilerName.end(1) + 1);
+ changed = true;
+ }
+
+ duplicateCompileID.reset(s);
+ if (duplicateCompileID.lookingAt()) {
+ s = s.substring(0, duplicateCompileID.start(1)) + s.substring(duplicateCompileID.end(1) + 1);
+ changed = true;
+ }
+
+ destroyVM.reset(s);
+ if (destroyVM.find()) {
+ s = s.substring(0, destroyVM.start(1)) + s.substring(destroyVM.end(1));
+ changed = true;
+ }
+
+ if (changed) {
+ s.getChars(0, s.length(), line, 0);
+ length = s.length();
+ }
+ }
+ }
+
+ private void rawFill() throws IOException {
+ if (bufferCount == -1) {
+ length = -1;
+ return;
+ }
+
+ int i = 0;
+ boolean fillNonEOL = true;
+ outer:
+ while (true) {
+ if (fillNonEOL) {
+ int p;
+ for (p = bufferOffset; p < bufferCount; p++) {
+ char c = buffer[p];
+ if (c == '\r' || c == '\n') {
+ bufferOffset = p;
+ fillNonEOL = false;
+ continue outer;
+ }
+ if (i >= line.length) {
+ // copy and enlarge the line array
+ char[] newLine = new char[line.length * 2];
+ System.arraycopy(line, 0, newLine, 0, line.length);
+ line = newLine;
+ }
+ line[i++] = c;
+ }
+ bufferOffset = p;
+ } else {
+ int p;
+ for (p = bufferOffset; p < bufferCount; p++) {
+ char c = buffer[p];
+ if (c != '\r' && c != '\n') {
+ bufferOffset = p;
+ length = i;
+ index = 0;
+ return;
+ }
+ line[i++] = c;
+ }
+ bufferOffset = p;
+ }
+ if (bufferCount == -1) {
+ if (i == 0) {
+ length = -1;
+ } else {
+ length = i;
+ }
+ index = 0;
+ return;
+ }
+ if (bufferOffset != bufferCount) {
+ System.out.println(bufferOffset);
+ System.out.println(bufferCount);
+ throw new InternalError("how did we get here");
+ }
+ // load more data and try again.
+ bufferCount = reader.read(buffer, 0, buffer.length);
+ bufferOffset = 0;
+ }
+ }
+
+ public int read() throws java.io.IOException {
+ read(one, 0, 1);
+ return one[0];
+ }
+
+ public int read(char[] buffer) throws java.io.IOException {
+ return read(buffer, 0, buffer.length);
+ }
+
+ public int read(char[] b, int off, int len) throws java.io.IOException {
+ if (length == -1) {
+ return -1;
+ }
+
+ if (index == length) {
+ fill();
+ if (length == -1) {
+ return -1;
+ }
+ }
+ int n = Math.min(length - index, Math.min(b.length - off, len));
+ // System.out.printf("%d %d %d %d %d\n", index, length, off, len, n);
+ System.arraycopy(line, index, b, off, n);
+ index += n;
+ return n;
+ }
+
+ public long skip(long n) throws java.io.IOException {
+ long result = n;
+ while (n-- > 0) read();
+ return result;
+ }
+
+ public boolean ready() throws java.io.IOException {
+ return reader.ready() || (line != null && length > 0);
+ }
+
+ public boolean markSupported() {
+ return false;
+ }
+
+ public void mark(int unused) throws java.io.IOException {
+ throw new UnsupportedOperationException("mark not supported");
+ }
+
+ public void reset() throws java.io.IOException {
+ reader.reset();
+ line = null;
+ index = 0;
+ }
+
+ public void close() throws java.io.IOException {
+ reader.close();
+ line = null;
+ index = 0;
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCompilation.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogCompilation.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.*;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+/**
+ * The LogCompilation tool parses log files generated by HotSpot using the
+ * {@code -XX:+LogCompilation} command line flag, and outputs the data
+ * collected therein in a nicely formatted way. There are various sorting
+ * options available, as well as options that select specific compilation
+ * events (such as inlining decisions) for inclusion in the output.
+ *
+ * The tool is also capable of fixing broken compilation logs as sometimes
+ * generated by Java 1.5 JVMs.
+ */
+public class LogCompilation extends DefaultHandler implements ErrorHandler {
+
+ /**
+ * Print usage information and terminate with a given exit code.
+ */
+ public static void usage(int exitcode) {
+ System.out.println("Usage: LogCompilation [ -v ] [ -c ] [ -s ] [ -e | -n ] file1 ...");
+ System.out.println("By default, the tool will print the logged compilations ordered by start time.");
+ System.out.println(" -c: clean up malformed 1.5 xml");
+ System.out.println(" -i: print inlining decisions");
+ System.out.println(" -S: print compilation statistics");
+ System.out.println(" -U: print uncommon trap statistics");
+ System.out.println(" -t: print with time stamps");
+ System.out.println(" -s: sort events by start time (default)");
+ System.out.println(" -e: sort events by elapsed time");
+ System.out.println(" -n: sort events by name and start");
+ System.out.println(" -C: compare logs (give files to compare on command line)");
+ System.out.println(" -d: do not print compilation IDs");
+ System.exit(exitcode);
+ }
+
+ /**
+ * Process command line arguments, parse log files and trigger desired
+ * functionality.
+ */
+ public static void main(String[] args) throws Exception {
+ Comparator sort = LogParser.sortByStart;
+ boolean statistics = false;
+ boolean printInlining = false;
+ boolean cleanup = false;
+ boolean trapHistory = false;
+ boolean printTimeStamps = false;
+ boolean compare = false;
+ boolean printID = true;
+ int index = 0;
+
+ while (args.length > index) {
+ String a = args[index];
+ if (a.equals("-e")) {
+ sort = LogParser.sortByElapsed;
+ index++;
+ } else if (a.equals("-n")) {
+ sort = LogParser.sortByNameAndStart;
+ index++;
+ } else if (a.equals("-s")) {
+ sort = LogParser.sortByStart;
+ index++;
+ } else if (a.equals("-t")) {
+ printTimeStamps = true;
+ index++;
+ } else if (a.equals("-c")) {
+ cleanup = true;
+ index++;
+ } else if (a.equals("-S")) {
+ statistics = true;
+ index++;
+ } else if (a.equals("-U")) {
+ trapHistory = true;
+ index++;
+ } else if (a.equals("-h")) {
+ usage(0);
+ } else if (a.equals("-i")) {
+ printInlining = true;
+ index++;
+ } else if (a.equals("-C")) {
+ compare = true;
+ index++;
+ } else if (a.equals("-d")) {
+ printID = false;
+ index++;
+ } else {
+ if (a.charAt(0) == '-') {
+ System.out.println("Unknown option '" + a + "', assuming file name.");
+ }
+ break;
+ }
+ }
+
+ if (index >= args.length) {
+ usage(1);
+ }
+
+ if (compare) {
+ compareLogs(index, args);
+ return;
+ }
+
+ while (index < args.length) {
+ ArrayList events = null;
+ try {
+ events = LogParser.parse(args[index], cleanup);
+ } catch (FileNotFoundException fnfe) {
+ System.out.println("File not found: " + args[index]);
+ System.exit(1);
+ }
+
+ Collections.sort(events, sort);
+
+ if (statistics) {
+ printStatistics(events, System.out);
+ } else if (trapHistory) {
+ printTrapHistory(events, System.out);
+ } else {
+ for (LogEvent c : events) {
+ if (c instanceof NMethod) {
+ // skip these
+ continue;
+ }
+ if (printTimeStamps) {
+ System.out.print(c.getStart() + ": ");
+ }
+ if (c instanceof Compilation) {
+ Compilation comp = (Compilation) c;
+ comp.print(System.out, printID, printInlining);
+ } else {
+ c.print(System.out, printID);
+ }
+ }
+ }
+ index++;
+ }
+ }
+
+ /**
+ * Print extensive statistics from parsed log files.
+ */
+ public static void printStatistics(ArrayList events, PrintStream out) {
+ // track code cache size
+ long cacheSize = 0;
+ long maxCacheSize = 0;
+ // track number of nmethods
+ int nmethodsCreated = 0;
+ int nmethodsLive = 0;
+ // track how many compilations were attempted multiple times
+ // (indexed by attempts, mapping to number of compilations)
+ int[] attempts = new int[32];
+ int maxattempts = 0;
+
+ // track time spent in compiler phases
+ LinkedHashMap phaseTime = new LinkedHashMap<>(7);
+ // track nodes created per phase
+ LinkedHashMap phaseNodes = new LinkedHashMap<>(7);
+ double elapsed = 0;
+
+ for (LogEvent e : events) {
+ if (e instanceof Compilation) {
+ Compilation c = (Compilation) e;
+ c.printShort(out);
+ out.printf(" %6.4f\n", c.getElapsedTime());
+ attempts[c.getAttempts()]++;
+ maxattempts = Math.max(maxattempts,c.getAttempts());
+ elapsed += c.getElapsedTime();
+ for (Phase phase : c.getPhases()) {
+ Double v = phaseTime.get(phase.getName());
+ if (v == null) {
+ v = Double.valueOf(0.0);
+ }
+ phaseTime.put(phase.getName(), Double.valueOf(v.doubleValue() + phase.getElapsedTime()));
+
+ Integer v2 = phaseNodes.get(phase.getName());
+ if (v2 == null) {
+ v2 = Integer.valueOf(0);
+ }
+ phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes()));
+ // Print phase name, elapsed time, nodes at the start of
+ // the phase, nodes created in the phase, live nodes at the
+ // start of the phase, live nodes added in the phase.
+ out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getAddedLiveNodes());
+ }
+ } else if (e instanceof MakeNotEntrantEvent) {
+ MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e;
+ NMethod nm = mne.getNMethod();
+ if (mne.isZombie()) {
+ if (nm == null) {
+ System.err.println("zombie make not entrant event without nmethod: " + mne.getId());
+ }
+ cacheSize -= nm.getSize();
+ nmethodsLive--;
+ }
+ } else if (e instanceof NMethod) {
+ nmethodsLive++;
+ nmethodsCreated++;
+ NMethod nm = (NMethod) e;
+ cacheSize += nm.getSize();
+ maxCacheSize = Math.max(cacheSize, maxCacheSize);
+ }
+ }
+ out.printf("NMethods: %d created %d live %d bytes (%d peak) in the code cache\n", nmethodsCreated, nmethodsLive, cacheSize, maxCacheSize);
+ out.println("Phase times:");
+ for (String name : phaseTime.keySet()) {
+ Double v = phaseTime.get(name);
+ Integer v2 = phaseNodes.get(name);
+ out.printf("%20s %6.4f %d\n", name, v.doubleValue(), v2.intValue());
+ }
+ out.printf("%20s %6.4f\n", "total", elapsed);
+
+ if (maxattempts > 0) {
+ out.println("Distribution of regalloc passes:");
+ for (int i = 0; i <= maxattempts; i++) {
+ out.printf("%2d %8d\n", i, attempts[i]);
+ }
+ }
+ }
+
+ /**
+ * Container class for a pair of a method and a bytecode instruction index
+ * used by a compiler. This is used in
+ * {@linkplain #compareLogs() comparing logs}.
+ */
+ static class MethodBCIPair {
+ public MethodBCIPair(Method m, int b, String c) {
+ method = m;
+ bci = b;
+ compiler = c;
+ }
+
+ Method method;
+ int bci;
+ String compiler;
+
+ public boolean equals(Object other) {
+ if (!(other instanceof MethodBCIPair)) {
+ return false;
+ }
+ MethodBCIPair otherp = (MethodBCIPair)other;
+ return (otherp.bci == bci &&
+ otherp.method.equals(method) &&
+ otherp.compiler.equals(compiler));
+ }
+
+ public int hashCode() {
+ return method.hashCode() + bci;
+ }
+
+ public String toString() {
+ if (bci != -1) {
+ return method + "@" + bci + " (" + compiler + ")";
+ } else {
+ return method + " (" + compiler + ")";
+ }
+ }
+ }
+
+ /**
+ * Compare a number of compilation log files. Each of the logs is parsed,
+ * and all compilations found therein are written to a sorted file (prefix
+ * {@code sorted-}. A summary is written to a new file {@code summary.txt}.
+ *
+ * @param index the index in the command line arguments at which to start
+ * looking for files to compare.
+ * @param args the command line arguments with which {@link LogCompilation}
+ * was originally invoked.
+ *
+ * @throws Exception in case any exceptions are thrown in the called
+ * methods.
+ */
+ @SuppressWarnings("unchecked")
+ static void compareLogs(int index, String[] args) throws Exception {
+ HashMap methods = new HashMap<>();
+ ArrayList> logs = new ArrayList<>();
+ PrintStream[] outs = new PrintStream[args.length - index];
+ PrintStream summary = new PrintStream(new FileOutputStream("summary.txt"));
+ int o = 0;
+ // Process all logs given on the command line: collect compilation
+ // data; in particular, method/bci pairs.
+ while (index < args.length) {
+ String basename = new File(args[index]).getName();
+ String outname = "sorted-" + basename;
+ System.out.println("Sorting " + basename + " to " + outname);
+ outs[o] = new PrintStream(new FileOutputStream(outname));
+ o++;
+ System.out.println("Parsing " + args[index]);
+ ArrayList events = LogParser.parse(args[index], false);
+ HashMap compiles = new HashMap<>();
+ logs.add(compiles);
+ for (LogEvent c : events) {
+ if (c instanceof Compilation) {
+ Compilation comp = (Compilation) c;
+ MethodBCIPair key = new MethodBCIPair(comp.getMethod(), comp.getBCI(),
+ comp.getCompiler());
+ MethodBCIPair e = methods.get(key);
+ if (e == null) {
+ methods.put(key, key);
+ } else {
+ key = e;
+ }
+ Object other = compiles.get(key);
+ if (other == null) {
+ compiles.put(key, comp);
+ } else {
+ if (!(other instanceof List)) {
+ List l = new LinkedList<>();
+ l.add(other);
+ l.add(comp);
+ compiles.put(key, l);
+ } else {
+ List l = (List) other;
+ l.add(comp);
+ }
+ }
+ }
+ }
+ index++;
+ }
+
+ // Process the collected method/bci pairs and write the output.
+ for (MethodBCIPair pair : methods.keySet()) {
+ summary.print(pair + " ");
+ int base = -1;
+ String first = null;
+ boolean mismatch = false;
+ boolean different = false;
+ String[] output = new String[outs.length];
+ o = 0;
+ for (HashMap set : logs) {
+ Object e = set.get(pair);
+ String thisone = null;
+ Compilation lastc = null;
+ int n;
+ if (e == null) {
+ n = 0;
+ } else if (e instanceof Compilation) {
+ n = 1;
+ lastc = (Compilation) e;
+ } else {
+ // Compare the last compilation that was done for this method
+ n = ((List) e).size();
+ lastc = (Compilation) ((List) e).get(n - 1);
+ }
+ if (lastc != null) {
+ n = 1;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ lastc.print(ps, false);
+ ps.close();
+ thisone = new String(baos.toByteArray());
+ }
+ if (base == -1) {
+ base = n;
+ } else if (base != n) {
+ mismatch = true;
+ }
+ output[o++] = thisone;
+ if (thisone != null) {
+ if (first == null) {
+ first = thisone;
+ } else {
+ if (!first.equals(thisone)) {
+ different = true;
+ }
+ }
+ }
+ if (different) {
+ summary.print(n + "d ");
+ } else {
+ summary.print(n + " ");
+ }
+ }
+ if (mismatch) {
+ summary.print("mismatch");
+ }
+ summary.println();
+ if (different) {
+ for (int i = 0; i < outs.length; i++) {
+ if (output[i] != null) {
+ outs[i].println(output[i]);
+ }
+ }
+ }
+ }
+ for (int i = 0; i < outs.length; i++) {
+ outs[i].close();
+ }
+ if (summary != System.out) {
+ summary.close();
+ }
+ }
+
+ /**
+ * Print the history of uncommon trap events.
+ */
+ public static void printTrapHistory(ArrayList events, PrintStream out) {
+ // map method names to a list of log events
+ LinkedHashMap> traps = new LinkedHashMap<>();
+ // map compilation IDs to compilations
+ HashMap comps = new HashMap<>();
+
+ // First, iterate over all logged events, collecting data about
+ // uncommon trap events.
+ for (LogEvent e : events) {
+ if (e instanceof NMethod) {
+ // skip these
+ continue;
+ }
+ if (e instanceof Compilation) {
+ Compilation c = (Compilation) e;
+ String name = c.getMethod().getFullName();
+ ArrayList elist = traps.get(name);
+ if (elist != null && comps.get(c.getId()) == null) {
+ comps.put(c.getId(), c);
+ // If there were previous events for the method
+ // then keep track of later compiles too.
+ elist.add(c);
+ }
+ continue;
+ }
+ if (e instanceof BasicLogEvent) {
+ BasicLogEvent ble = (BasicLogEvent) e;
+ Compilation c = ble.getCompilation();
+ if (c == null) {
+ if (!(ble instanceof NMethod)) {
+ throw new InternalError("only nmethods should have a null compilation; here's a " + ble.getClass());
+ }
+ continue;
+ }
+ String name = c.getMethod().getFullName();
+ ArrayList elist = traps.get(name);
+ if (elist == null) {
+ elist = new ArrayList();
+ traps.put(name, elist);
+ }
+ int bleId = Integer.parseInt(ble.getId());
+ if (comps.get(bleId) == null) {
+ comps.put(bleId, c);
+ // Add the associated compile to the list. It
+ // will likely go at the end but we need to search
+ // backwards for the proper insertion point.
+ double start = c.getStart();
+ int ipoint = 0;
+ while (ipoint < elist.size() && elist.get(ipoint).getStart() < start) {
+ ipoint++;
+ }
+ if (ipoint == elist.size()) {
+ elist.add(c);
+ } else {
+ elist.add(ipoint, c);
+ }
+ }
+ elist.add(ble);
+ }
+ }
+
+ // Second, iterate over collected traps and output information.
+ for (String c: traps.keySet()) {
+ ArrayList elist = traps.get(c);
+ String name = ((Compilation) elist.get(0)).getMethod().getFullName();
+ System.out.println(name);
+ double start = 0;
+ for (LogEvent e: elist) {
+ if (start > e.getStart() && e.getStart() != 0) {
+ throw new InternalError("wrong sorting order for traps");
+ }
+ start = e.getStart();
+ out.print(e.getStart() + ": ");
+ if (e instanceof Compilation) {
+ ((Compilation) e).print(out, true, true, true);
+ } else {
+ e.print(out, true);
+ }
+ }
+ out.println();
+ }
+ }
+
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogEvent.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogEvent.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * The interface of an event from a HotSpot compilation log. Events can have a
+ * duration, e.g., a compiler {@link Phase} is an event, and so is an entire
+ * {@link Compilation}.
+ */
+public interface LogEvent {
+
+ /**
+ * The event's start time.
+ */
+ public double getStart();
+
+ /**
+ * The event's duration in milliseconds.
+ */
+ public double getElapsedTime();
+
+ /**
+ * The compilation during which this event was signalled.
+ */
+ public Compilation getCompilation();
+
+ /**
+ * Print the event to the given stream.
+ */
+ public void print(PrintStream stream, boolean printID);
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogParser.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/LogParser.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,1302 @@
+/*
+ * Copyright (c) 2009, 2015, 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.
+ *
+ */
+
+/**
+ * A SAX based parser of LogCompilation output from HotSpot. It takes a complete
+ */
+
+package com.sun.hotspot.tools.compiler;
+
+import java.io.FileReader;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A SAX parser for HotSpot compilation logs. The bulk of the parsing and event
+ * maintenance work is done in the {@link #startElement(String,String,String,Attributes)}
+ * and {@link #endElement(String,String,String)} methods.
+ */
+public class LogParser extends DefaultHandler implements ErrorHandler {
+
+ static final Pattern spacePattern = Pattern.compile(" ");
+
+ /**
+ * Map internal array type descriptors to Java names.
+ */
+ static final HashMap type2printableMap;
+
+ /**
+ * Map Java primitive type names to internal type descriptors.
+ */
+ static final HashMap type2vmtypeMap;
+
+ static {
+ type2printableMap = new HashMap<>();
+ type2printableMap.put("[I", "int[]");
+ type2printableMap.put("[C", "char[]");
+ type2printableMap.put("[Z", "boolean[]");
+ type2printableMap.put("[L", "Object[]");
+ type2printableMap.put("[B", "byte[]");
+
+ type2vmtypeMap = new HashMap<>();
+ type2vmtypeMap.put("void", "V");
+ type2vmtypeMap.put("boolean", "Z");
+ type2vmtypeMap.put("byte", "B");
+ type2vmtypeMap.put("char", "C");
+ type2vmtypeMap.put("short", "S");
+ type2vmtypeMap.put("int", "I");
+ type2vmtypeMap.put("long", "J");
+ type2vmtypeMap.put("float", "F");
+ type2vmtypeMap.put("double", "D");
+ }
+
+ static String[] bytecodes = new String[] {
+ "nop",
+ "aconst_null",
+ "iconst_m1",
+ "iconst_0",
+ "iconst_1",
+ "iconst_2",
+ "iconst_3",
+ "iconst_4",
+ "iconst_5",
+ "lconst_0",
+ "lconst_1",
+ "fconst_0",
+ "fconst_1",
+ "fconst_2",
+ "dconst_0",
+ "dconst_1",
+ "bipush",
+ "sipush",
+ "ldc",
+ "ldc_w",
+ "ldc2_w",
+ "iload",
+ "lload",
+ "fload",
+ "dload",
+ "aload",
+ "iload_0",
+ "iload_1",
+ "iload_2",
+ "iload_3",
+ "lload_0",
+ "lload_1",
+ "lload_2",
+ "lload_3",
+ "fload_0",
+ "fload_1",
+ "fload_2",
+ "fload_3",
+ "dload_0",
+ "dload_1",
+ "dload_2",
+ "dload_3",
+ "aload_0",
+ "aload_1",
+ "aload_2",
+ "aload_3",
+ "iaload",
+ "laload",
+ "faload",
+ "daload",
+ "aaload",
+ "baload",
+ "caload",
+ "saload",
+ "istore",
+ "lstore",
+ "fstore",
+ "dstore",
+ "astore",
+ "istore_0",
+ "istore_1",
+ "istore_2",
+ "istore_3",
+ "lstore_0",
+ "lstore_1",
+ "lstore_2",
+ "lstore_3",
+ "fstore_0",
+ "fstore_1",
+ "fstore_2",
+ "fstore_3",
+ "dstore_0",
+ "dstore_1",
+ "dstore_2",
+ "dstore_3",
+ "astore_0",
+ "astore_1",
+ "astore_2",
+ "astore_3",
+ "iastore",
+ "lastore",
+ "fastore",
+ "dastore",
+ "aastore",
+ "bastore",
+ "castore",
+ "sastore",
+ "pop",
+ "pop2",
+ "dup",
+ "dup_x1",
+ "dup_x2",
+ "dup2",
+ "dup2_x1",
+ "dup2_x2",
+ "swap",
+ "iadd",
+ "ladd",
+ "fadd",
+ "dadd",
+ "isub",
+ "lsub",
+ "fsub",
+ "dsub",
+ "imul",
+ "lmul",
+ "fmul",
+ "dmul",
+ "idiv",
+ "ldiv",
+ "fdiv",
+ "ddiv",
+ "irem",
+ "lrem",
+ "frem",
+ "drem",
+ "ineg",
+ "lneg",
+ "fneg",
+ "dneg",
+ "ishl",
+ "lshl",
+ "ishr",
+ "lshr",
+ "iushr",
+ "lushr",
+ "iand",
+ "land",
+ "ior",
+ "lor",
+ "ixor",
+ "lxor",
+ "iinc",
+ "i2l",
+ "i2f",
+ "i2d",
+ "l2i",
+ "l2f",
+ "l2d",
+ "f2i",
+ "f2l",
+ "f2d",
+ "d2i",
+ "d2l",
+ "d2f",
+ "i2b",
+ "i2c",
+ "i2s",
+ "lcmp",
+ "fcmpl",
+ "fcmpg",
+ "dcmpl",
+ "dcmpg",
+ "ifeq",
+ "ifne",
+ "iflt",
+ "ifge",
+ "ifgt",
+ "ifle",
+ "if_icmpeq",
+ "if_icmpne",
+ "if_icmplt",
+ "if_icmpge",
+ "if_icmpgt",
+ "if_icmple",
+ "if_acmpeq",
+ "if_acmpne",
+ "goto",
+ "jsr",
+ "ret",
+ "tableswitch",
+ "lookupswitch",
+ "ireturn",
+ "lreturn",
+ "freturn",
+ "dreturn",
+ "areturn",
+ "return",
+ "getstatic",
+ "putstatic",
+ "getfield",
+ "putfield",
+ "invokevirtual",
+ "invokespecial",
+ "invokestatic",
+ "invokeinterface",
+ "invokedynamic",
+ "new",
+ "newarray",
+ "anewarray",
+ "arraylength",
+ "athrow",
+ "checkcast",
+ "instanceof",
+ "monitorenter",
+ "monitorexit",
+ "wide",
+ "multianewarray",
+ "ifnull",
+ "ifnonnull",
+ "goto_w",
+ "jsr_w",
+ "breakpoint"
+ };
+
+ /**
+ * Sort log events by start time.
+ */
+ static Comparator sortByStart = new Comparator() {
+
+ public int compare(LogEvent a, LogEvent b) {
+ double difference = (a.getStart() - b.getStart());
+ if (difference < 0) {
+ return -1;
+ }
+ if (difference > 0) {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 7;
+ }
+ };
+
+ /**
+ * Sort log events first by the name of the compiled method, then by start
+ * time. In case one of the events has no associated compilation (or the
+ * associated compilation has no method name), the event with a compilation
+ * and/or name is considered the larger one.
+ */
+ static Comparator sortByNameAndStart = new Comparator() {
+
+ public int compare(LogEvent a, LogEvent b) {
+ Compilation c1 = a.getCompilation();
+ Compilation c2 = b.getCompilation();
+ if (c1 != null && c1.getMethod() != null && c2 != null && c2.getMethod() != null) {
+ int result = c1.getMethod().toString().compareTo(c2.getMethod().toString());
+ if (result != 0) {
+ return result;
+ }
+ } else if ((c1 == null || c1.getMethod() == null) && c2 != null && c2.getMethod() != null) {
+ return -1;
+ } else if ((c2 == null || c2.getMethod() == null) && c1 != null && c1.getMethod() != null) {
+ return 1;
+ }
+ return Double.compare(a.getStart(), b.getStart());
+ }
+
+ public boolean equals(Object other) {
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 7;
+ }
+ };
+
+ /**
+ * Sort log events by duration.
+ */
+ static Comparator sortByElapsed = new Comparator() {
+
+ public int compare(LogEvent a, LogEvent b) {
+ double difference = (a.getElapsedTime() - b.getElapsedTime());
+ if (difference < 0) {
+ return -1;
+ }
+ if (difference > 0) {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 7;
+ }
+ };
+
+ /**
+ * Shrink-wrapped representation of a JVMState (tailored to meet this
+ * tool's needs). It only records a method and bytecode instruction index.
+ */
+ class Jvms {
+ Jvms(Method method, int bci) {
+ this.method = method;
+ this.bci = bci;
+ }
+ final public Method method;
+ final public int bci;
+ final public String toString() {
+ return "@" + bci + " " + method;
+ }
+ }
+
+ /**
+ * Representation of a lock elimination. Locks, corresponding to
+ * synchronized blocks and method calls, may be eliminated if the object in
+ * question is guaranteed to be used thread-locally.
+ */
+ class LockElimination extends BasicLogEvent {
+
+ /**
+ * Track all locations from which this lock was eliminated.
+ */
+ ArrayList jvms = new ArrayList<>(1);
+
+ /**
+ * The kind of lock (coarsened, nested, non-escaping, unknown).
+ */
+ final String kind;
+
+ /**
+ * The lock class (unlock, lock, unknown).
+ */
+ final String classId;
+
+ /**
+ * The precise type of lock.
+ */
+ final String tagName;
+
+ LockElimination(String tagName, double start, String id, String kind, String classId) {
+ super(start, id);
+ this.kind = kind;
+ this.classId = classId;
+ this.tagName = tagName;
+ }
+
+ @Override
+ public void print(PrintStream stream, boolean printID) {
+ if (printID) {
+ stream.printf("%s ", getId());
+ }
+ stream.printf("%s %s %s %.3f ", tagName, kind, classId, getStart());
+ stream.print(jvms.toString());
+ stream.print("\n");
+ }
+
+ void addJVMS(Method method, int bci) {
+ jvms.add(new Jvms(method, bci));
+ }
+
+ }
+
+ /**
+ * A list of log events. This is populated with the events found in the
+ * compilation log file during parsing.
+ */
+ private ArrayList events = new ArrayList<>();
+
+ /**
+ * Map compilation log IDs to type names.
+ */
+ private HashMap types = new HashMap<>();
+
+ /**
+ * Map compilation log IDs to methods.
+ */
+ private HashMap methods = new HashMap<>();
+
+ /**
+ * Map compilation IDs ({@see #makeId()}) to newly created nmethods.
+ */
+ private LinkedHashMap nmethods = new LinkedHashMap<>();
+
+ /**
+ * Map compilation task IDs {@see #makeId()}) to {@link Compilation}
+ * objects.
+ */
+ private HashMap compiles = new HashMap<>();
+
+ /**
+ * Track compilation failure reasons.
+ */
+ private String failureReason;
+
+ /**
+ * The current bytecode instruction index.
+ */
+ private int current_bci;
+
+ /**
+ * The current bytecode instruction.
+ */
+ private int current_bytecode;
+
+ /**
+ * A sequence of {@link CallSite}s representing a call stack. A scope
+ * typically holds several {@link CallSite}s that represent calls
+ * originating from that scope.
+ *
+ * New scopes are typically pushed when parse log events are encountered
+ * ({@see #startElement()}) and popped when parsing of a given Java method
+ * is done ({@see #endElement()}). Parsing events can be nested. Several
+ * other events add information to scopes ({@see #startElement()}).
+ */
+ private Deque scopes = new ArrayDeque<>();
+
+ /**
+ * The current compilation.
+ */
+ private Compilation compile;
+
+ /**
+ * The {@linkplain CallSite compilation scope} currently in focus.
+ */
+ private CallSite site;
+
+ /**
+ * The {@linkplain CallSite method handle call site} currently under
+ * observation.
+ */
+ private CallSite methodHandleSite;
+
+ /**
+ * Keep track of potentially nested compiler {@linkplain Phase phases}.
+ */
+ private Deque phaseStack = new ArrayDeque<>();
+
+ /**
+ * The {@linkplain LockElimination lock elimination event} currently being
+ * processed.
+ */
+ private LockElimination currentLockElimination;
+
+ /**
+ * The {@linkplain UncommonTrapEvent uncommon trap event} currently being
+ * processed.
+ */
+ private UncommonTrapEvent currentTrap;
+
+ /**
+ * During the processing of a late inline event, this stack holds the
+ * {@link CallSite}s that represent the inlining event's call stack.
+ */
+ private Deque lateInlineScope;
+
+ /**
+ * Denote whether a late inlining event is currently being processed.
+ */
+ private boolean lateInlining;
+
+ /**
+ * A document locator to provide better error messages: this allows the
+ * tool to display in which line of the log file the problem occurred.
+ */
+ private Locator locator;
+
+ /**
+ * Callback for the SAX framework to set the document locator.
+ */
+ @Override
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+
+ /**
+ * Report an internal error explicitly raised, i.e., not derived from an
+ * exception.
+ *
+ * @param msg The error message to report.
+ */
+ private void reportInternalError(String msg) {
+ reportInternalError(msg, null);
+ }
+
+ /**
+ * Report an internal error derived from an exception.
+ *
+ * @param msg The beginning of the error message to report. The message
+ * from the exception will be appended to this.
+ * @param e The exception that led to the internal error.
+ */
+ private void reportInternalError(String msg, Exception e) {
+ if (locator != null) {
+ msg += " at " + locator.getLineNumber() + ":" + locator.getColumnNumber();
+ if (e != null) {
+ msg += " - " + e.getMessage();
+ }
+ }
+ if (e != null) {
+ throw new Error(msg, e);
+ } else {
+ throw new Error(msg);
+ }
+ }
+
+ /**
+ * Parse a long hexadecimal address into a {@code long} value. As Java only
+ * supports positive {@code long} values, extra error handling and parsing
+ * logic is provided.
+ */
+ long parseLong(String l) {
+ try {
+ return Long.decode(l).longValue();
+ } catch (NumberFormatException nfe) {
+ int split = l.length() - 8;
+ String s1 = "0x" + l.substring(split);
+ String s2 = l.substring(0, split);
+ long v1 = Long.decode(s1).longValue() & 0xffffffffL;
+ long v2 = (Long.decode(s2).longValue() & 0xffffffffL) << 32;
+ if (!l.equals("0x" + Long.toHexString(v1 + v2))) {
+ System.out.println(l);
+ System.out.println(s1);
+ System.out.println(s2);
+ System.out.println(v1);
+ System.out.println(v2);
+ System.out.println(Long.toHexString(v1 + v2));
+ reportInternalError("bad conversion");
+ }
+ return v1 + v2;
+ }
+ }
+
+ /**
+ * Entry point for log file parsing with a file name.
+ *
+ * @param file The name of the log file to parse.
+ * @param cleanup Whether to perform bad XML cleanup during parsing (this
+ * is relevant for some log files generated by the 1.5 JVM).
+ * @return a list of {@link LogEvent} instances describing the events found
+ * in the log file.
+ */
+ public static ArrayList parse(String file, boolean cleanup) throws Exception {
+ return parse(new FileReader(file), cleanup);
+ }
+
+ /**
+ * Entry point for log file parsing with a file reader.
+ * {@link #parse(String,boolean)}
+ */
+ public static ArrayList parse(Reader reader, boolean cleanup) throws Exception {
+ // Create the XML input factory
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+
+ // Create the XML LogEvent reader
+ SAXParser p = factory.newSAXParser();
+
+ if (cleanup) {
+ // some versions of the log have slightly malformed XML, so clean it
+ // up before passing it to SAX
+ reader = new LogCleanupReader(reader);
+ }
+
+ LogParser log = new LogParser();
+ try {
+ p.parse(new InputSource(reader), log);
+ } catch (Throwable th) {
+ th.printStackTrace();
+ // Carry on with what we've got...
+ }
+
+ // Associate compilations with their NMethods and other kinds of events
+ for (LogEvent e : log.events) {
+ if (e instanceof BasicLogEvent) {
+ BasicLogEvent ble = (BasicLogEvent) e;
+ Compilation c = log.compiles.get(ble.getId());
+ if (c == null) {
+ if (!(ble instanceof NMethod)) {
+ throw new InternalError("only nmethods should have a null compilation, here's a " + ble.getClass());
+ }
+ continue;
+ }
+ ble.setCompilation(c);
+ if (ble instanceof NMethod) {
+ c.setNMethod((NMethod) ble);
+ }
+ }
+ }
+
+ return log.events;
+ }
+
+ /**
+ * Retrieve a given attribute's value from a collection of XML tag
+ * attributes. Report an error if the requested attribute is not found.
+ *
+ * @param attr A collection of XML tag attributes.
+ * @param name The name of the attribute the value of which is to be found.
+ * @return The value of the requested attribute, or {@code null} if it was
+ * not found.
+ */
+ String search(Attributes attr, String name) {
+ String result = attr.getValue(name);
+ if (result != null) {
+ return result;
+ } else {
+ reportInternalError("can't find " + name);
+ return null;
+ }
+ }
+
+ /**
+ * Retrieve a given attribute's value from a collection of XML tag
+ * attributes. Return a default value if the requested attribute is not
+ * found.
+ *
+ * @param attr A collection of XML tag attributes.
+ * @param name The name of the attribute the value of which is to be found.
+ * @param defaultValue The default value to return if the attribute is not
+ * found.
+ * @return The value of the requested attribute, or the default value if it
+ * was not found.
+ */
+ String search(Attributes attr, String name, String defaultValue) {
+ String result = attr.getValue(name);
+ if (result != null) {
+ return result;
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Map a type ID from the compilation log to an actual type name. In case
+ * the type represents an internal array type descriptor, return a
+ * Java-level name. If the type ID cannot be mapped to a name, raise an
+ * error.
+ */
+ String type(String id) {
+ String result = types.get(id);
+ if (result == null) {
+ reportInternalError(id);
+ }
+ String remapped = type2printableMap.get(result);
+ if (remapped != null) {
+ return remapped;
+ }
+ return result;
+ }
+
+ /**
+ * Register a mapping from log file type ID to type name.
+ */
+ void type(String id, String name) {
+ assert type(id) == null;
+ types.put(id, name);
+ }
+
+ /**
+ * Map a log file type ID to an internal type declarator.
+ */
+ String sigtype(String id) {
+ String result = types.get(id);
+ String remapped = type2vmtypeMap.get(result);
+ if (remapped != null) {
+ return remapped;
+ }
+ if (result == null) {
+ reportInternalError(id);
+ }
+ if (result.charAt(0) == '[') {
+ return result;
+ }
+ return "L" + result + ";";
+ }
+
+ /**
+ * Retrieve a method based on the log file ID it was registered under.
+ * Raise an error if the ID does not map to a method.
+ */
+ Method method(String id) {
+ Method result = methods.get(id);
+ if (result == null) {
+ reportInternalError(id);
+ }
+ return result;
+ }
+
+ /**
+ * From a compilation ID and kind, assemble a compilation ID for inclusion
+ * in the output.
+ *
+ * @param atts A collection of XML attributes from which the required
+ * attributes are retrieved.
+ */
+ public String makeId(Attributes atts) {
+ String id = atts.getValue("compile_id");
+ String kind = atts.getValue("kind");
+ if (kind != null && kind.equals("osr")) {
+ id += "%";
+ }
+ return id;
+ }
+
+ /**
+ * Process the start of a compilation log XML element.
+ * phase: record the beginning of a compilation phase, pushing
+ * it on the {@linkplain #phaseStack phase stack} and collecting
+ * information about the compiler graph.
+ * phase_done: record the end of a compilation phase, popping it
+ * off the {@linkplain #phaseStack phase stack} and collecting information
+ * about the compiler graph (number of nodes and live nodes).
+ * task: register the start of a new compilation.
+ * type: register a type.
+ * bc: note the current bytecode index and instruction name,
+ * updating {@link #current_bci} and {@link #current_bytecode}.
+ * klass: register a type (class).
+ * method: register a Java method.
+ * call: process a call, populating {@link #site} with the
+ * appropriate data.
+ * regalloc: record the register allocator's trip count in the
+ * {@linkplain #compile current compilation}.
+ * inline_fail: record the reason for a failed inline
+ * operation.
+ * inline_success: record a successful inlining operation,
+ * noting the success reason in the {@linkplain #site call site}.
+ * failure: note a compilation failure, storing the reason
+ * description in {@link #failureReason}.
+ * task_done: register the end of a compilation, recording time
+ * stamp and success information.
+ * make_not_entrant: deal with making a native method
+ * non-callable (e.g., during an OSR compilation, if there are still
+ * activations) or a zombie (when the method can be deleted).
+ * uncommon_trap: process an uncommon trap, setting the
+ * {@link #currentTrap} field.
+ * eliminate_lock: record the start of a lock elimination,
+ * setting the {@link #currentLockElimination} event.
+ * late_inline: start processing a late inline decision:
+ * initialize the {@linkplain #lateInlineScope inline scope stack}, create
+ * an {@linkplain #site initial scope} with a bogus bytecode index and the
+ * right inline ID, and push the scope with the inline ID attached. Note
+ * that most of late inlining processing happens in
+ * {@link #endElement(String,String,String)}.
+ * jvms: record a {@linkplain Jvms JVMState}. Depending on the
+ * context in which this event is encountered, this can mean adding
+ * information to the currently being processed trap, lock elimination, or
+ * inlining operation.
+ * inline_id: set the inline ID in the
+ * {@linkplain #site current call site}.
+ * nmethod: record the creation of a new {@link NMethod} and
+ * store it in the {@link #nmethods} map.
+ * parse: begin parsing a Java method's bytecode and
+ * transforming it into an initial compiler IR graph.
+ * parse_done: finish parsing a Java method's bytecode.
+ *
+ */
+ @Override
+ public void startElement(String uri, String localName, String qname, Attributes atts) {
+ if (qname.equals("phase")) {
+ Phase p = new Phase(search(atts, "name"),
+ Double.parseDouble(search(atts, "stamp")),
+ Integer.parseInt(search(atts, "nodes", "0")),
+ Integer.parseInt(search(atts, "live", "0")));
+ phaseStack.push(p);
+ } else if (qname.equals("phase_done")) {
+ Phase p = phaseStack.pop();
+ String phaseName = search(atts, "name", null);
+ if (phaseName != null && !p.getId().equals(phaseName)) {
+ System.out.println("phase: " + p.getId());
+ reportInternalError("phase name mismatch");
+ }
+ p.setEnd(Double.parseDouble(search(atts, "stamp")));
+ p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
+ p.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
+ compile.getPhases().add(p);
+ } else if (qname.equals("task")) {
+ String id = makeId(atts);
+
+ // Create the new Compilation instance and populate it with readily
+ // available data.
+ compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1")));
+ compile.setStart(Double.parseDouble(search(atts, "stamp")));
+ compile.setICount(search(atts, "count", "0"));
+ compile.setBCount(search(atts, "backedge_count", "0"));
+ compile.setBCI(Integer.parseInt(search(atts, "osr_bci", "-1")));
+ String compiler = atts.getValue("compiler");
+ if (compiler == null) {
+ compiler = "";
+ }
+ compile.setCompiler(compiler);
+
+ // Extract the name of the compiled method.
+ String[] parts = spacePattern.split(atts.getValue("method"));
+ String methodName = parts[0] + "::" + parts[1];
+
+ // Continue collecting compilation meta-data.
+ String kind = atts.getValue("compile_kind");
+ if (kind == null) {
+ kind = "normal";
+ }
+ if (kind.equals("osr")) {
+ compile.setOsr(true);
+ } else if (kind.equals("c2i")) {
+ compile.setSpecial("--- adapter " + methodName);
+ } else {
+ compile.setSpecial(compile.getId() + " " + methodName + " (0 bytes)");
+ }
+
+ // Build a dummy method to stuff in the Compilation at the
+ // beginning.
+ Method m = new Method();
+ m.setHolder(parts[0]);
+ m.setName(parts[1]);
+ m.setSignature(parts[2]);
+ m.setFlags("0");
+ m.setBytes(search(atts, "bytes", "unknown"));
+ compile.setMethod(m);
+ events.add(compile);
+ compiles.put(id, compile);
+ site = compile.getCall();
+ } else if (qname.equals("type")) {
+ type(search(atts, "id"), search(atts, "name"));
+ } else if (qname.equals("bc")) {
+ current_bci = Integer.parseInt(search(atts, "bci"));
+ current_bytecode = Integer.parseInt(search(atts, "code"));
+ } else if (qname.equals("klass")) {
+ type(search(atts, "id"), search(atts, "name"));
+ } else if (qname.equals("method")) {
+ String id = search(atts, "id");
+ Method m = new Method();
+ m.setHolder(type(search(atts, "holder")));
+ m.setName(search(atts, "name"));
+ m.setReturnType(type(search(atts, "return")));
+ String arguments = atts.getValue("arguments");;
+ if (arguments == null) {
+ m.setSignature("()" + sigtype(atts.getValue("return")));
+ } else {
+ String[] args = spacePattern.split(arguments);
+ StringBuilder sb = new StringBuilder("(");
+ for (int i = 0; i < args.length; i++) {
+ sb.append(sigtype(args[i]));
+ }
+ sb.append(")");
+ sb.append(sigtype(atts.getValue("return")));
+ m.setSignature(sb.toString());
+ }
+
+ if (search(atts, "unloaded", "0").equals("0")) {
+ m.setBytes(search(atts, "bytes"));
+ m.setIICount(search(atts, "iicount"));
+ m.setFlags(search(atts, "flags"));
+ }
+ methods.put(id, m);
+ } else if (qname.equals("call")) {
+ if (methodHandleSite != null) {
+ methodHandleSite = null;
+ }
+ Method m = method(search(atts, "method"));
+ if (lateInlining && scopes.size() == 0) {
+ // re-attempting already seen call site (late inlining for MH invokes)
+ if (m != site.getMethod()) {
+ if (current_bci != site.getBci()) {
+ System.err.println(m + " bci: " + current_bci);
+ System.err.println(site.getMethod() + " bci: " + site.getBci());
+ reportInternalError("bci mismatch after late inlining");
+ }
+ site.setMethod(m);
+ }
+ } else {
+ // We're dealing with a new call site; the called method is
+ // likely to be parsed next.
+ site = new CallSite(current_bci, m);
+ }
+ site.setCount(Integer.parseInt(search(atts, "count", "0")));
+ String receiver = atts.getValue("receiver");
+ if (receiver != null) {
+ site.setReceiver(type(receiver));
+ site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count")));
+ }
+ int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0"));
+ if (lateInlining && scopes.size() == 0) {
+ // The call was already added before this round of late
+ // inlining. Ignore.
+ } else if (methodHandle == 0) {
+ scopes.peek().add(site);
+ } else {
+ // method handle call site can be followed by another
+ // call (in case it is inlined). If that happens we
+ // discard the method handle call site. So we keep
+ // track of it but don't add it to the list yet.
+ methodHandleSite = site;
+ }
+ } else if (qname.equals("regalloc")) {
+ compile.setAttempts(Integer.parseInt(search(atts, "attempts")));
+ } else if (qname.equals("inline_fail")) {
+ if (methodHandleSite != null) {
+ scopes.peek().add(methodHandleSite);
+ methodHandleSite = null;
+ }
+ if (lateInlining && scopes.size() == 0) {
+ site.setReason("fail: " + search(atts, "reason"));
+ lateInlining = false;
+ } else {
+ scopes.peek().last().setReason("fail: " + search(atts, "reason"));
+ }
+ } else if (qname.equals("inline_success")) {
+ if (methodHandleSite != null) {
+ reportInternalError("method handle site should have been replaced");
+ }
+ site.setReason("succeed: " + search(atts, "reason"));
+ } else if (qname.equals("failure")) {
+ failureReason = search(atts, "reason");
+ } else if (qname.equals("task_done")) {
+ compile.setEnd(Double.parseDouble(search(atts, "stamp")));
+ if (Integer.parseInt(search(atts, "success")) == 0) {
+ compile.setFailureReason(failureReason);
+ failureReason = null;
+ }
+ } else if (qname.equals("make_not_entrant")) {
+ String id = makeId(atts);
+ NMethod nm = nmethods.get(id);
+ if (nm == null) reportInternalError("nm == null");
+ LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
+ atts.getValue("zombie") != null, nm);
+ events.add(e);
+ } else if (qname.equals("uncommon_trap")) {
+ String id = atts.getValue("compile_id");
+ if (id != null) {
+ id = makeId(atts);
+ currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")),
+ id,
+ atts.getValue("reason"),
+ atts.getValue("action"),
+ Integer.parseInt(search(atts, "count", "0")));
+ events.add(currentTrap);
+ } else {
+ if (atts.getValue("method") != null) {
+ // These are messages from ciTypeFlow that don't
+ // actually correspond to generated code.
+ return;
+ }
+ try {
+ UncommonTrap unc = new UncommonTrap(Integer.parseInt(search(atts, "bci")),
+ search(atts, "reason"),
+ search(atts, "action"),
+ bytecodes[current_bytecode]);
+ if (scopes.size() == 0) {
+ // There may be a dangling site not yet in scopes after a late_inline
+ if (site != null) {
+ site.add(unc);
+ } else {
+ reportInternalError("scope underflow");
+ }
+ } else {
+ scopes.peek().add(unc);
+ }
+ } catch (Error e) {
+ e.printStackTrace();
+ }
+ }
+ } else if (qname.startsWith("eliminate_lock")) {
+ String id = atts.getValue("compile_id");
+ if (id != null) {
+ id = makeId(atts);
+ String kind = atts.getValue("kind");
+ String classId = atts.getValue("class_id");
+ currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId);
+ events.add(currentLockElimination);
+ }
+ } else if (qname.equals("late_inline")) {
+ long inlineId = 0;
+ try {
+ inlineId = Long.parseLong(search(atts, "inline_id"));
+ } catch (InternalError ex) {
+ // Log files from older hotspots may lack inline_id,
+ // and zero is an acceptable substitute that allows processing to continue.
+ }
+ lateInlineScope = new ArrayDeque<>();
+ Method m = method(search(atts, "method"));
+ site = new CallSite(-999, m);
+ site.setInlineId(inlineId);
+ lateInlineScope.push(site);
+ } else if (qname.equals("jvms")) {
+ //
+ if (currentTrap != null) {
+ String[] parts = spacePattern.split(atts.getValue("method"));
+ currentTrap.addMethodAndBCI(parts[0].replace('/', '.') + '.' + parts[1] + parts[2], Integer.parseInt(atts.getValue("bci")));
+ } else if (currentLockElimination != null) {
+ currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
+ } else if (lateInlineScope != null) {
+ current_bci = Integer.parseInt(search(atts, "bci"));
+ Method m = method(search(atts, "method"));
+ site = new CallSite(current_bci, m);
+ lateInlineScope.push(site);
+ } else {
+ // Ignore ,
+ //
+ }
+ } else if (qname.equals("inline_id")) {
+ if (methodHandleSite != null) {
+ reportInternalError("method handle site should have been replaced");
+ }
+ long id = Long.parseLong(search(atts, "id"));
+ site.setInlineId(id);
+ } else if (qname.equals("nmethod")) {
+ String id = makeId(atts);
+ NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
+ id,
+ parseLong(atts.getValue("address")),
+ parseLong(atts.getValue("size")));
+ nmethods.put(id, nm);
+ events.add(nm);
+ } else if (qname.equals("parse")) {
+ if (failureReason != null && scopes.size() == 0 && !lateInlining) {
+ // A compilation just failed, and we're back at a top
+ // compilation scope.
+ failureReason = null;
+ compile.reset();
+ site = compile.getCall();
+ }
+
+ // Error checking.
+ if (methodHandleSite != null) {
+ reportInternalError("method handle site should have been replaced");
+ }
+ Method m = method(search(atts, "method")); // this is the method being parsed
+ if (lateInlining && scopes.size() == 0) {
+ if (site.getMethod() != m) {
+ reportInternalError("Unexpected method mismatch during late inlining (method at call site: " +
+ site.getMethod() + ", method being parsed: " + m + ")");
+ }
+ }
+
+ if (scopes.size() == 0 && !lateInlining) {
+ // The method being parsed is actually the method being
+ // compiled; i.e., we're dealing with a compilation top scope,
+ // which we must consequently push to the scopes stack.
+ compile.setMethod(m);
+ scopes.push(site);
+ } else {
+ // The method being parsed is *not* the current compilation's
+ // top scope; i.e., we're dealing with an actual call site
+ // in the top scope or somewhere further down a call stack.
+ if (site.getMethod() == m) {
+ // We're dealing with monomorphic inlining that didn't have
+ // to be narrowed down, because the receiver was known
+ // beforehand.
+ scopes.push(site);
+ } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().lastButOne().getMethod()) {
+ // We're dealing with an at least bimorphic call site, and
+ // the compiler has now decided to parse the last-but-one
+ // method. The last one may already have been parsed for
+ // inlining.
+ scopes.push(scopes.peek().lastButOne());
+ } else {
+ // The method has been narrowed down to the one we're now
+ // going to parse, which is inlined here. It's monomorphic
+ // inlining, but was not immediately clear as such.
+ //
+ // C1 prints multiple method tags during inlining when it
+ // narrows the method being inlined. Example:
+ // ...
+ //
+ //
+ //
+ //
+ //
+ // ...
+ site.setMethod(m);
+ scopes.push(site);
+ }
+ }
+ } else if (qname.equals("parse_done")) {
+ // Attach collected information about IR nodes to the current
+ // parsing scope before it's popped off the stack in endElement()
+ // (see where the parse tag is handled).
+ CallSite call = scopes.peek();
+ call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
+ call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
+ call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
+ }
+ }
+
+ /**
+ * Process the end of a compilation log XML element.
+ * parse: finish transforming a Java method's bytecode
+ * instructions to an initial compiler IR graph.
+ * uncommon_trap: record the end of processing an uncommon trap,
+ * resetting {@link #currentTrap}.
+ * eliminate_lock: record the end of a lock elimination,
+ * resetting {@link #currentLockElimination}.
+ * late_inline: the closing tag for late_inline does not denote
+ * the end of a late inlining operation, but the end of the descriptive log
+ * data given at its beginning. That is, we're now in the position to
+ * assemble details about the inlining chain (bytecode instruction index in
+ * caller, called method). The {@link #lateInlining} flag is set to
+ * {@code true} here. (It will be reset when parsing the inlined methods is
+ * done; this happens for the successful case in this method as well, when
+ * {@code parse} elements are processed; and for inlining failures, in
+ * {@link #startElement(String,String,String,Attributes)}, when {@code inline_fail} elements are
+ * processed.)
+ * task: perform cleanup at the end of a compilation. Note that
+ * the explicit {@code task_done} event is handled in
+ * {@link #startElement(String,String,String,Attributes)}.
+ *
+ */
+ @Override
+ public void endElement(String uri, String localName, String qname) {
+ try {
+ if (qname.equals("parse")) {
+ // Finish dealing with the current call scope. If no more are
+ // left, no late inlining can be going on.
+ scopes.pop();
+ if (scopes.size() == 0) {
+ lateInlining = false;
+ }
+ } else if (qname.equals("uncommon_trap")) {
+ currentTrap = null;
+ } else if (qname.startsWith("eliminate_lock")) {
+ currentLockElimination = null;
+ } else if (qname.equals("late_inline")) {
+ // Populate late inlining info.
+ if (scopes.size() != 0) {
+ reportInternalError("scopes should be empty for late inline");
+ }
+ // late inline scopes are specified in reverse order:
+ // compiled method should be on top of stack.
+ CallSite caller = lateInlineScope.pop();
+ Method m = compile.getMethod();
+ if (!m.equals(caller.getMethod())) {
+ reportInternalError(String.format("call site and late_inline info don't match:\n method %s\n caller method %s, bci %d", m, caller.getMethod(), current_bci));
+ }
+
+ // Walk down the inlining chain and assemble bci+callee info.
+ // This needs to be converted from caller+bci info contained in
+ // the late_inline data.
+ CallSite lateInlineSite = compile.getLateInlineCall();
+ ArrayDeque thisCallScopes = new ArrayDeque<>();
+ do {
+ current_bci = caller.getBci();
+ // Next inlined call.
+ caller = lateInlineScope.pop();
+ CallSite callee = new CallSite(current_bci, caller.getMethod());
+ callee.setInlineId(caller.getInlineId());
+ thisCallScopes.addLast(callee);
+ lateInlineSite.add(callee);
+ lateInlineSite = callee;
+ } while (!lateInlineScope.isEmpty());
+
+ site = compile.getCall().findCallSite(thisCallScopes);
+ if (site == null) {
+ // Call site could not be found - report the problem in detail.
+ System.err.println("call scopes:");
+ for (CallSite c : thisCallScopes) {
+ System.err.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId());
+ }
+ CallSite c = thisCallScopes.getLast();
+ if (c.getInlineId() != 0) {
+ System.err.println("Looking for call site in entire tree:");
+ ArrayDeque stack = compile.getCall().findCallSite2(c);
+ for (CallSite c2 : stack) {
+ System.err.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId());
+ }
+ }
+ System.err.println(caller.getMethod() + " bci: " + current_bci);
+ reportInternalError("couldn't find call site");
+ }
+ lateInlining = true;
+
+ if (caller.getBci() != -999) {
+ System.out.println(caller.getMethod());
+ reportInternalError("broken late_inline info");
+ }
+ if (site.getMethod() != caller.getMethod()) {
+ if (site.getInlineId() == caller.getInlineId()) {
+ site.setMethod(caller.getMethod());
+ } else {
+ System.out.println(site.getMethod());
+ System.out.println(caller.getMethod());
+ reportInternalError("call site and late_inline info don't match");
+ }
+ }
+ // late_inline is followed by parse with scopes.size() == 0,
+ // 'site' will be pushed to scopes.
+ lateInlineScope = null;
+ } else if (qname.equals("task")) {
+ types.clear();
+ methods.clear();
+ site = null;
+ }
+ } catch (Exception e) {
+ reportInternalError("exception while processing end element", e);
+ }
+ }
+
+ //
+ // Handlers for problems that occur in XML parsing itself.
+ //
+
+ @Override
+ public void warning(org.xml.sax.SAXParseException e) {
+ System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
+ e.printStackTrace();
+ }
+
+ @Override
+ public void error(org.xml.sax.SAXParseException e) {
+ System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
+ e.printStackTrace();
+ }
+
+ @Override
+ public void fatalError(org.xml.sax.SAXParseException e) {
+ System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
+ e.printStackTrace();
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * In a compilation log, represent the event of making a given compiled method
+ * not-entrant, e.g., during an OSR compilation.
+ */
+class MakeNotEntrantEvent extends BasicLogEvent {
+
+ /**
+ * Denote whether the method is marked as a zombie, i.e., no further
+ * activations exist.
+ */
+ private final boolean zombie;
+
+ /**
+ * The method in question.
+ */
+ private NMethod nmethod;
+
+ MakeNotEntrantEvent(double s, String i, boolean z, NMethod nm) {
+ super(s, i);
+ zombie = z;
+ nmethod = nm;
+ }
+
+ public NMethod getNMethod() {
+ return nmethod;
+ }
+
+ public void print(PrintStream stream, boolean printID) {
+ if (isZombie()) {
+ stream.printf("%s make_zombie\n", getId());
+ } else {
+ stream.printf("%s make_not_entrant\n", getId());
+ }
+ }
+
+ public boolean isZombie() {
+ return zombie;
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Method.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Method.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.util.Arrays;
+
+import static com.sun.hotspot.tools.compiler.Constants.*;
+
+/**
+ * Representation of a Java method in a compilation log.
+ */
+public class Method {
+
+ /**
+ * The name of the class holding the method.
+ */
+ private String holder;
+
+ /**
+ * The method's name.
+ */
+ private String name;
+
+ /**
+ * The return type of the method, as a fully qualified (source-level) class
+ * or primitive type name.
+ */
+ private String returnType;
+
+ /**
+ * The method's signature, in internal form.
+ */
+ private String signature;
+
+ /**
+ * The length of the method's byte code.
+ */
+ private String bytes;
+
+ /**
+ * The number of times this method was invoked in the interpreter.
+ */
+ private String iicount;
+
+ /**
+ * The method's flags, in the form of a {@code String} representing the
+ * {@code int} encoding them.
+ */
+ private String flags;
+
+ /**
+ * Decode the {@link flags} numerical string to a format for console
+ * output. The result does not honour all possible flags but includes
+ * information about OSR compilation.
+ *
+ * @param osr_bci the byte code index at which an OSR compilation takes
+ * place, or -1 if the compilation is not an OSR one.
+ */
+ String decodeFlags(int osr_bci) {
+ int f = Integer.parseInt(getFlags());
+ char[] c = new char[4];
+ Arrays.fill(c, ' ');
+ if (osr_bci >= 0) {
+ c[0] = '%';
+ }
+ if ((f & JVM_ACC_SYNCHRONIZED) != 0) {
+ c[1] = 's';
+ }
+ return new String(c);
+ }
+
+ /**
+ * Format this method for console output.
+ *
+ * @param osr_bci the byte code index at which OSR takes place, or -1 if no
+ * OSR compilation is going on.
+ */
+ String format(int osr_bci) {
+ if (osr_bci >= 0) {
+ return getHolder() + "::" + getName() + " @ " + osr_bci + " (" + getBytes() + " bytes)";
+ } else {
+ return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)";
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getHolder() + "::" + getName() + " (" + getBytes() + " bytes)";
+ }
+
+ public String getFullName() {
+ return getHolder().replace('/', '.') + "." + getName() + signature;
+ }
+
+ public String getHolder() {
+ return holder;
+ }
+
+ public void setHolder(String holder) {
+ this.holder = holder;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getReturnType() {
+ return returnType;
+ }
+
+ public void setReturnType(String returnType) {
+ this.returnType = returnType;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public void setSignature(String signature) {
+ this.signature = signature.replace('/', '.');
+ }
+
+ public String getArguments() {
+ return signature.substring(0, signature.indexOf(')') + 1);
+ }
+
+ public String getBytes() {
+ return bytes;
+ }
+
+ public void setBytes(String bytes) {
+ this.bytes = bytes;
+ }
+
+ public String getIICount() {
+ return iicount;
+ }
+
+ public void setIICount(String iicount) {
+ this.iicount = iicount;
+ }
+
+ public String getFlags() {
+ return flags;
+ }
+
+ public void setFlags(String flags) {
+ this.flags = flags;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Method) {
+ Method other = (Method) o;
+ return holder.equals(other.holder) && name.equals(other.name) && signature.equals(other.signature);
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return holder.hashCode() ^ name.hashCode();
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/NMethod.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/NMethod.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * A compilation log event that is signalled whenever a new nmethod (a native
+ * method, a compilation result) is created.
+ */
+public class NMethod extends BasicLogEvent {
+
+ /**
+ * The nmethod's starting address in memory.
+ */
+ private long address;
+
+ /**
+ * The nmethod's size in bytes.
+ */
+ private long size;
+
+ NMethod(double s, String i, long a, long sz) {
+ super(s, i);
+ address = a;
+ size = sz;
+ }
+
+ public void print(PrintStream out, boolean printID) {
+ // XXX Currently we do nothing
+ // throw new InternalError();
+ }
+
+ public long getAddress() {
+ return address;
+ }
+
+ public void setAddress(long address) {
+ this.address = address;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Phase.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/Phase.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * Representation of a compilation phase as a log event.
+ */
+public class Phase extends BasicLogEvent {
+
+ /**
+ * The number of nodes in the compilation at the beginning of this phase.
+ */
+ private final int startNodes;
+
+ /**
+ * The number of nodes in the compilation at the end of this phase.
+ */
+ private int endNodes;
+
+ /**
+ * The number of live nodes in the compilation at the beginning of this
+ * phase.
+ */
+ private final int startLiveNodes;
+
+ /**
+ * The number of live nodes in the compilation at the end of this phase.
+ */
+ private int endLiveNodes;
+
+ Phase(String n, double s, int nodes, int live) {
+ super(s, n);
+ startNodes = nodes;
+ startLiveNodes = live;
+ }
+
+ int getNodes() {
+ return getEndNodes() - getStartNodes();
+ }
+
+ void setEndNodes(int n) {
+ endNodes = n;
+ }
+
+ public String getName() {
+ return getId();
+ }
+
+ public int getStartNodes() {
+ return startNodes;
+ }
+
+ public int getEndNodes() {
+ return endNodes;
+ }
+
+ /**
+ * The number of live nodes added by this phase.
+ */
+ int getAddedLiveNodes() {
+ return getEndLiveNodes() - getStartLiveNodes();
+ }
+
+ void setEndLiveNodes(int n) {
+ endLiveNodes = n;
+ }
+
+ public int getStartLiveNodes() {
+ return startLiveNodes;
+ }
+
+ public int getEndLiveNodes() {
+ return endLiveNodes;
+ }
+
+ @Override
+ public void print(PrintStream stream, boolean printID) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrap.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrap.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+
+/**
+ * An instance of this class represents an uncommon trap associated with a
+ * given bytecode instruction. An uncommon trap is described in terms of its
+ * reason and action to be taken. An instance of this class is always relative
+ * to a specific method and only contains the relevant bytecode instruction
+ * index.
+ */
+class UncommonTrap {
+
+ private int bci;
+ private String reason;
+ private String action;
+ private String bytecode;
+
+ public UncommonTrap(int b, String r, String a, String bc) {
+ bci = b;
+ reason = r;
+ action = a;
+ bytecode = bc;
+ }
+
+ public int getBCI() {
+ return bci;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getBytecode() {
+ return bytecode;
+ }
+
+ void emit(PrintStream stream, int indent) {
+ for (int i = 0; i < indent; i++) {
+ stream.print(' ');
+ }
+ }
+
+ public void print(PrintStream stream, int indent) {
+ emit(stream, indent);
+ stream.println(this);
+ }
+
+ public String toString() {
+ return "@ " + bci + " " + getBytecode() + " uncommon trap " + getReason() + " " + getAction();
+ }
+}
diff -r 9289fcb41aae -r 3af0ab7d1d90 src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils/LogCompilation/src/main/java/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Thu Nov 30 16:00:34 2017 -0500
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sun.hotspot.tools.compiler;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents an uncommon trap encountered during a compilation.
+ */
+class UncommonTrapEvent extends BasicLogEvent {
+
+ private final String reason;
+ private final String action;
+
+ /**
+ * Denote how many times this trap has been encountered.
+ */
+ private int count;
+
+ /**
+ * The name of the bytecode instruction at which the trap occurred.
+ */
+ private String bytecode;
+
+ private List jvmsMethods = new ArrayList<>();
+
+ private List jvmsBCIs = new ArrayList<>();
+
+ UncommonTrapEvent(double s, String i, String r, String a, int c) {
+ super(s, i);
+ reason = r;
+ action = a;
+ count = c;
+ }
+
+ public void updateCount(UncommonTrapEvent trap) {
+ setCount(Math.max(getCount(), trap.getCount()));
+ }
+
+ public void print(PrintStream stream, boolean printID) {
+ if (printID) {
+ stream.print(getId() + " ");
+ }
+ stream.printf("uncommon trap %s %s %s\n", bytecode, getReason(), getAction());
+ int indent = 2;
+ for (int j = 0; j < jvmsMethods.size(); j++) {
+ for (int i = 0; i < indent; i++) {
+ stream.print(' ');
+ }
+ stream.println("@ " + jvmsBCIs.get(j) + " " + jvmsMethods.get(j));
+ indent += 2;
+ }
+ }
+
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ /**
+ * Set the compilation for this event. This involves identifying the call
+ * site to which this uncommon trap event belongs. In addition to setting
+ * the {@link #compilation} link, this method will consequently also set
+ * the {@link #bytecode} field.
+ */
+ public void setCompilation(Compilation compilation) {
+ super.setCompilation(compilation);
+ // Attempt to associate a bytecode with with this trap
+ CallSite site = compilation.getCall();
+ int i = 0;
+ try {
+ List traps = site.getTraps();
+ while (i + 1 < jvmsMethods.size()) {
+ if (!jvmsMethods.get(i).equals(site.getMethod().getFullName())) {
+ throw new InternalError(jvmsMethods.get(i) + " != " + site.getMethod().getFullName());
+ }
+ CallSite result = null;
+ for (CallSite call : site.getCalls()) {
+ if (call.getBci() == jvmsBCIs.get(i) &&
+ call.getMethod().getFullName().equals(jvmsMethods.get(i + 1)) &&
+ call.getReceiver() == null) {
+ result = call;
+ i++;
+ break;
+ }
+ }
+ if (result == null) {
+ throw new InternalError("couldn't find call site");
+ }
+ site = result;
+ traps = site.getTraps();
+ }
+ for (UncommonTrap trap : traps) {
+ if (trap.getBCI() == jvmsBCIs.get(i) &&
+ trap.getReason().equals(getReason()) &&
+ trap.getAction().equals(getAction())) {
+ bytecode = trap.getBytecode();
+ return;
+ }
+ }
+ throw new InternalError("couldn't find bytecode");
+ } catch (Exception e) {
+ bytecode = "";
+ }
+ }
+
+ public void addMethodAndBCI(String method, int bci) {
+ jvmsMethods.add(0, method);
+ jvmsBCIs.add(0, bci);
+ }
+
+}