1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.vm.ci.meta; 24 25 import java.util.Map; 26 import java.util.function.Supplier; 27 28 /** 29 * Manages unique {@link SpeculationReason} objects that denote why a deoptimization occurred. 30 * Reasons are embedded in compiled code for a method. If the compiled code deoptimizes at a 31 * position associated with a {@link SpeculationReason}, the reason is added to a set of failed 32 * speculations associated with the method. A subsequent compilation of the method can query the 33 * failed speculations via a {@link SpeculationLog} to avoid making a speculation based on 34 * invalidated reasons. This avoids repeated deoptimizations. 35 */ 36 public interface SpeculationLog { 37 /** 38 * The specific attributes of a speculation that a compiler uses to denote a speculation in a 39 * compiled method. Typical attributes of a speculation are a bytecode position, type 40 * information about a variable being speculated on and an enum denoting the type of operation 41 * to which the speculation applies. A {@link SpeculationReason} is used as a key in a 42 * {@link Map} and so it must implement {@link Object#equals(Object)} and 43 * {@link Object#hashCode()} in terms of its attributes. 44 * 45 * A JVMCI implementation may serialize speculations for storage off heap (e.g. in native memory 46 * associated with an nmethod). For this reason, the attributes of a {@link SpeculationReason} 47 * are restricted to those supported by the {@code add...} methods of 48 * {@link SpeculationReasonEncoding}. 49 */ 50 public interface SpeculationReason { 51 52 /** 53 * Encodes the attributes of this reason using a {@link SpeculationReasonEncoding}. For 54 * efficiency, a {@link SpeculationReason} implementation should cache the returned value 55 * and return it for all subsequent calls to this method. This also underlines the 56 * requirement that the encoding for a specific reason instance should be stable. 57 * 58 * @param encodingSupplier source of a {@link SpeculationReasonEncoding} 59 * @return a {@link SpeculationReasonEncoding} that encodes all the attributes that uniquely 60 * identify this reason 61 */ encode(Supplier<SpeculationReasonEncoding> encodingSupplier)62 default SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) { 63 return null; 64 } 65 } 66 67 /** 68 * Provides a facility for encoding the attributes of a {@link SpeculationReason}. The encoding 69 * format is determined by the implementation of this interface. 70 */ 71 public interface SpeculationReasonEncoding { addByte(int value)72 void addByte(int value); 73 addShort(int value)74 void addShort(int value); 75 addInt(int value)76 void addInt(int value); 77 addLong(long value)78 void addLong(long value); 79 addMethod(ResolvedJavaMethod method)80 void addMethod(ResolvedJavaMethod method); 81 addType(ResolvedJavaType type)82 void addType(ResolvedJavaType type); 83 addString(String value)84 void addString(String value); 85 addField(ResolvedJavaField field)86 default void addField(ResolvedJavaField field) { 87 addType(field.getDeclaringClass()); 88 addInt(field.getModifiers()); 89 addInt(field.getOffset()); 90 } 91 } 92 93 /** 94 * Marker class that indicates that a speculation has no reason. 95 */ 96 final class NoSpeculationReason implements SpeculationReason { 97 } 98 99 class Speculation { 100 private final SpeculationReason reason; 101 Speculation(SpeculationReason reason)102 public Speculation(SpeculationReason reason) { 103 this.reason = reason; 104 } 105 getReason()106 public SpeculationReason getReason() { 107 return reason; 108 } 109 110 @Override toString()111 public String toString() { 112 return reason.toString(); 113 } 114 115 @Override equals(Object obj)116 public boolean equals(Object obj) { 117 if (obj instanceof Speculation) { 118 Speculation other = (Speculation) obj; 119 return reason.equals(other.reason); 120 } 121 return false; 122 } 123 124 @Override hashCode()125 public int hashCode() { 126 return getReason().hashCode(); 127 } 128 } 129 130 Speculation NO_SPECULATION = new Speculation(new NoSpeculationReason()); 131 132 /** 133 * Updates the set of failed speculations recorded in this log. This must be called before 134 * compilation. 135 */ collectFailedSpeculations()136 void collectFailedSpeculations(); 137 138 /** 139 * If this method returns true, the compiler is allowed to {@link #speculate} with the given 140 * reason. 141 */ maySpeculate(SpeculationReason reason)142 boolean maySpeculate(SpeculationReason reason); 143 144 /** 145 * Registers a speculation performed by the compiler. The compiler must guard every call to this 146 * method for a specific reason with a call to {@link #maySpeculate(SpeculationReason)}. 147 * 148 * This API is subject to a benign race where a during the course of a compilation another 149 * thread might fail a speculation such that {@link #maySpeculate(SpeculationReason)} will 150 * return false but an earlier call returned true. This method will still return a working 151 * {@link Speculation} in that case but the compile will eventually be invalidated and the 152 * compile attempted again without the now invalid speculation. 153 * 154 * @param reason an object representing the reason for the speculation 155 * @return a compiler constant encapsulating the provided reason. It is usually passed as an 156 * argument to the deoptimization function. 157 */ speculate(SpeculationReason reason)158 Speculation speculate(SpeculationReason reason); 159 160 /** 161 * Returns if this log has speculations. 162 * 163 * @return true if there are speculations, false otherwise 164 */ hasSpeculations()165 boolean hasSpeculations(); 166 167 /** 168 * Given a {@link JavaConstant} previously returned from 169 * {@link MetaAccessProvider#encodeSpeculation(Speculation)} return the original 170 * {@link Speculation} object. 171 */ lookupSpeculation(JavaConstant constant)172 Speculation lookupSpeculation(JavaConstant constant); 173 } 174