src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -22,19 +22,72 @@
*/
package jdk.vm.ci.meta;
+import java.util.Map;
+import java.util.function.Supplier;
+
/**
- * Manages unique deoptimization reasons. Reasons are embedded in compiled code and can be
- * invalidated at run time. Subsequent compilations then should not speculate again on such
- * invalidated reasons to avoid repeated deoptimization.
- *
- * All methods of this interface are called by the compiler. There is no need for API to register
- * failed speculations during deoptimization, since every VM has different needs there.
+ * Manages unique {@link SpeculationReason} objects that denote why a deoptimization occurred.
+ * Reasons are embedded in compiled code for a method. If the compiled code deoptimizes at a
+ * position associated with a {@link SpeculationReason}, the reason is added to a set of failed
+ * speculations associated with the method. A subsequent compilation of the method can query the
+ * failed speculations via a {@link SpeculationLog} to avoid making a speculation based on
+ * invalidated reasons. This avoids repeated deoptimizations.
*/
public interface SpeculationLog {
/**
- * Marker interface for speculation objects that can be added to the speculation log.
+ * The specific attributes of a speculation that a compiler uses to denote a speculation in a
+ * compiled method. Typical attributes of a speculation are a bytecode position, type
+ * information about a variable being speculated on and an enum denoting the type of operation
+ * to which the speculation applies. A {@link SpeculationReason} is used as a key in a
+ * {@link Map} and so it must implement {@link Object#equals(Object)} and
+ * {@link Object#hashCode()} in terms of its attributes.
+ *
+ * A JVMCI implementation may serialize speculations for storage off heap (e.g. in native memory
+ * associated with an nmethod). For this reason, the attributes of a {@link SpeculationReason}
+ * are restricted to those supported by the {@code add...} methods of
+ * {@link SpeculationReasonEncoding}.
*/
public interface SpeculationReason {
+
+ /**
+ * Encodes the attributes of this reason using a {@link SpeculationReasonEncoding}. For
+ * efficiency, a {@link SpeculationReason} implementation should cache the returned value
+ * and return it for all subsequent calls to this method. This also underlines the
+ * requirement that the encoding for a specific reason instance should be stable.
+ *
+ * @param encodingSupplier source of a {@link SpeculationReasonEncoding}
+ * @return a {@link SpeculationReasonEncoding} that encodes all the attributes that uniquely
+ * identify this reason
+ */
+ default SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+ return null;
+ }
+ }
+
+ /**
+ * Provides a facility for encoding the attributes of a {@link SpeculationReason}. The encoding
+ * format is determined by the implementation of this interface.
+ */
+ public interface SpeculationReasonEncoding {
+ void addByte(int value);
+
+ void addShort(int value);
+
+ void addInt(int value);
+
+ void addLong(long value);
+
+ void addMethod(ResolvedJavaMethod method);
+
+ void addType(ResolvedJavaType type);
+
+ void addString(String value);
+
+ default void addField(ResolvedJavaField field) {
+ addType(field.getDeclaringClass());
+ addInt(field.getModifiers());
+ addInt(field.getOffset());
+ }
}
/**
@@ -44,7 +97,7 @@
}
class Speculation {
- private SpeculationReason reason;
+ private final SpeculationReason reason;
public Speculation(SpeculationReason reason) {
this.reason = reason;
@@ -77,7 +130,8 @@
Speculation NO_SPECULATION = new Speculation(new NoSpeculationReason());
/**
- * Must be called before compilation, i.e., before a compiler calls {@link #maySpeculate}.
+ * Updates the set of failed speculations recorded in this log. This must be called before
+ * compilation.
*/
void collectFailedSpeculations();