< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java

Print this page




   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 
  24 
  25 package org.graalvm.compiler.hotspot.stubs;
  26 
  27 import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
  28 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
  29 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
  30 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getPendingException;
  31 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
  32 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic;
  33 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
  34 import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
  35 
  36 import java.lang.reflect.Method;
  37 import java.lang.reflect.Modifier;
  38 import java.util.Arrays;
  39 import java.util.List;
  40 
  41 import org.graalvm.compiler.api.replacements.Fold;
  42 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
  43 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
  44 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
  45 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
  46 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  47 import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode;
  48 import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
  49 import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
  50 import org.graalvm.compiler.hotspot.word.KlassPointer;
  51 import org.graalvm.compiler.nodes.PiNode;
  52 import org.graalvm.compiler.nodes.SnippetAnchorNode;
  53 import org.graalvm.compiler.nodes.extended.GuardingNode;
  54 import org.graalvm.compiler.replacements.Log;
  55 import org.graalvm.compiler.word.Word;
  56 import jdk.internal.vm.compiler.word.Pointer;
  57 import jdk.internal.vm.compiler.word.WordFactory;
  58 
  59 import jdk.vm.ci.meta.DeoptimizationAction;
  60 
  61 //JaCoCo Exclude
  62 
  63 /**
  64  * A collection of methods used in {@link Stub}s.
  65  */
  66 public class StubUtil {
  67 
  68     public static final ForeignCallDescriptor VM_MESSAGE_C = newDescriptor(StubUtil.class, "vmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class);
  69 
  70     public static ForeignCallDescriptor newDescriptor(Class<?> stubClass, String name, Class<?> resultType, Class<?>... argumentTypes) {
  71         ForeignCallDescriptor d = new ForeignCallDescriptor(name, resultType, argumentTypes);
  72         assert descriptorFor(stubClass, name).equals(d) : descriptorFor(stubClass, name) + " != " + d;
  73         return d;
  74     }
  75 
  76     /**
  77      * Looks for a {@link StubForeignCallNode} node intrinsic named {@code name} in
  78      * {@code stubClass} and returns a {@link ForeignCallDescriptor} based on its signature and the
  79      * value of {@code hasSideEffect}.
  80      */
  81     private static ForeignCallDescriptor descriptorFor(Class<?> stubClass, String name) {
  82         Method found = null;
  83         for (Method method : stubClass.getDeclaredMethods()) {
  84             if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
  85                 if (method.getAnnotation(NodeIntrinsic.class).value().equals(StubForeignCallNode.class)) {
  86                     assert found == null : "found more than one foreign call named " + name + " in " + stubClass;
  87                     assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == ForeignCallDescriptor.class : "first parameter of foreign call '" + name + "' in " + stubClass +
  88                                     " must be of type " + ForeignCallDescriptor.class.getSimpleName();
  89                     found = method;
  90                 }
  91             }
  92         }
  93         assert found != null : "could not find foreign call named " + name + " in " + stubClass;
  94         List<Class<?>> paramList = Arrays.asList(found.getParameterTypes());
  95         Class<?>[] cCallTypes = paramList.subList(1, paramList.size()).toArray(new Class<?>[paramList.size() - 1]);
  96         return new ForeignCallDescriptor(name, found.getReturnType(), cCallTypes);
  97     }
  98 
  99     public static void handlePendingException(Word thread, boolean shouldClearException, boolean isObjectResult) {
 100         if ((shouldClearException && clearPendingException(thread) != null) || (!shouldClearException && getPendingException(thread) != null)) {
 101             if (isObjectResult) {
 102                 getAndClearObjectResult(thread);
 103             }
 104             DeoptimizeCallerNode.deopt(DeoptimizationAction.None, RuntimeConstraint);
 105         }
 106     }
 107 
 108     /**
 109      * Determines if this is a HotSpot build where the ASSERT mechanism is enabled.
 110      */
 111     @Fold
 112     public static boolean cAssertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) {
 113         return config.cAssertions;
 114     }
 115 
 116     @NodeIntrinsic(StubForeignCallNode.class)
 117     private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
 118 
 119     /**
 120      * Prints a message to the log stream.
 121      * <p>
 122      * <b>Stubs must use this instead of {@link Log#printf(String, long)} to avoid an object
 123      * constant in a RuntimeStub.</b>
 124      *
 125      * @param message a message string
 126      */
 127     public static void printf(String message) {


 215     public static void fatal(String format, long v1, long v2) {
 216         vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, 0L);
 217     }
 218 
 219     /**
 220      * Exits the VM with a given error message.
 221      * <p>
 222      * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
 223      * object constant in a RuntimeStub.</b>
 224      *
 225      * @param format a C style printf format value
 226      * @param v1 the value associated with the first conversion specifier in {@code format}
 227      * @param v2 the value associated with the second conversion specifier in {@code format}
 228      * @param v3 the value associated with the third conversion specifier in {@code format}
 229      */
 230     public static void fatal(String format, long v1, long v2, long v3) {
 231         vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, v3);
 232     }
 233 
 234     /**
 235      * Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
 236      */
 237     public static Object verifyObject(Object object) {
 238         if (verifyOops(INJECTED_VMCONFIG)) {
 239             Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG));
 240             verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
 241 
 242             Pointer oop = Word.objectToTrackedPointer(object);
 243             if (object != null) {
 244                 GuardingNode anchorNode = SnippetAnchorNode.anchor();
 245                 // make sure object is 'reasonable'
 246                 if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) {
 247                     fatal("oop not in heap: %p", oop.rawValue());
 248                 }
 249 
 250                 KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
 251                 if (klass.isNull()) {
 252                     fatal("klass for oop %p is null", oop.rawValue());
 253                 }
 254             }
 255         }
 256         return object;
 257     }
 258 
 259     @Fold
 260     static long verifyOopCounterAddress(@InjectedParameter GraalHotSpotVMConfig config) {
 261         return config.verifyOopCounterAddress;
 262     }
 263 
 264     @Fold
 265     static long verifyOopMask(@InjectedParameter GraalHotSpotVMConfig config) {
 266         return config.verifyOopMask;
 267     }
 268 
 269     @Fold
 270     static long verifyOopBits(@InjectedParameter GraalHotSpotVMConfig config) {
 271         return config.verifyOopBits;
 272     }
 273 
 274     /**
 275      * Print {@code number} as decimal string to {@code buffer}.
 276      *
 277      * @param buffer
 278      * @param number
 279      * @return A pointer pointing one byte right after the last printed digit in {@code buffer}.
 280      */
 281     public static Word printNumber(Word buffer, long number) {
 282         long tmpNumber = number;
 283         int offset;
 284         if (tmpNumber <= 0) {
 285             tmpNumber = -tmpNumber;
 286             offset = 1;
 287         } else {
 288             offset = 0;
 289         }
 290         while (tmpNumber > 0) {
 291             tmpNumber /= 10;
 292             offset++;
 293         }
 294         tmpNumber = number < 0 ? -number : number;




   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 
  24 
  25 package org.graalvm.compiler.hotspot.stubs;
  26 







  27 import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
  28 
  29 import java.lang.reflect.Method;
  30 import java.lang.reflect.Modifier;
  31 import java.util.Arrays;
  32 import java.util.List;
  33 
  34 import org.graalvm.compiler.api.replacements.Fold;
  35 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
  36 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
  37 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
  38 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
  39 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;

  40 import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
  41 import org.graalvm.compiler.hotspot.nodes.VMErrorNode;




  42 import org.graalvm.compiler.replacements.Log;
  43 import org.graalvm.compiler.word.Word;

  44 import jdk.internal.vm.compiler.word.WordFactory;
  45 


  46 //JaCoCo Exclude
  47 
  48 /**
  49  * A collection of methods used in {@link Stub}s.
  50  */
  51 public class StubUtil {
  52 
  53     public static final ForeignCallDescriptor VM_MESSAGE_C = newDescriptor(StubUtil.class, "vmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class);
  54 
  55     public static ForeignCallDescriptor newDescriptor(Class<?> stubClass, String name, Class<?> resultType, Class<?>... argumentTypes) {
  56         ForeignCallDescriptor d = new ForeignCallDescriptor(name, resultType, argumentTypes);
  57         assert descriptorFor(stubClass, name).equals(d) : descriptorFor(stubClass, name) + " != " + d;
  58         return d;
  59     }
  60 
  61     /**
  62      * Looks for a {@link StubForeignCallNode} node intrinsic named {@code name} in
  63      * {@code stubClass} and returns a {@link ForeignCallDescriptor} based on its signature and the
  64      * value of {@code hasSideEffect}.
  65      */
  66     private static ForeignCallDescriptor descriptorFor(Class<?> stubClass, String name) {
  67         Method found = null;
  68         for (Method method : stubClass.getDeclaredMethods()) {
  69             if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) {
  70                 if (method.getAnnotation(NodeIntrinsic.class).value().equals(StubForeignCallNode.class)) {
  71                     assert found == null : "found more than one foreign call named " + name + " in " + stubClass;
  72                     assert method.getParameterTypes().length != 0 && method.getParameterTypes()[0] == ForeignCallDescriptor.class : "first parameter of foreign call '" + name + "' in " + stubClass +
  73                                     " must be of type " + ForeignCallDescriptor.class.getSimpleName();
  74                     found = method;
  75                 }
  76             }
  77         }
  78         assert found != null : "could not find foreign call named " + name + " in " + stubClass;
  79         List<Class<?>> paramList = Arrays.asList(found.getParameterTypes());
  80         Class<?>[] cCallTypes = paramList.subList(1, paramList.size()).toArray(new Class<?>[paramList.size() - 1]);
  81         return new ForeignCallDescriptor(name, found.getReturnType(), cCallTypes);
  82     }
  83 









  84     /**
  85      * Determines if this is a HotSpot build where the ASSERT mechanism is enabled.
  86      */
  87     @Fold
  88     public static boolean cAssertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) {
  89         return config.cAssertions;
  90     }
  91 
  92     @NodeIntrinsic(StubForeignCallNode.class)
  93     private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3);
  94 
  95     /**
  96      * Prints a message to the log stream.
  97      * <p>
  98      * <b>Stubs must use this instead of {@link Log#printf(String, long)} to avoid an object
  99      * constant in a RuntimeStub.</b>
 100      *
 101      * @param message a message string
 102      */
 103     public static void printf(String message) {


 191     public static void fatal(String format, long v1, long v2) {
 192         vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, 0L);
 193     }
 194 
 195     /**
 196      * Exits the VM with a given error message.
 197      * <p>
 198      * <b>Stubs must use this instead of {@link Log#printf(String, long, long, long)} to avoid an
 199      * object constant in a RuntimeStub.</b>
 200      *
 201      * @param format a C style printf format value
 202      * @param v1 the value associated with the first conversion specifier in {@code format}
 203      * @param v2 the value associated with the second conversion specifier in {@code format}
 204      * @param v3 the value associated with the third conversion specifier in {@code format}
 205      */
 206     public static void fatal(String format, long v1, long v2, long v3) {
 207         vmMessageC(VM_MESSAGE_C, true, cstring(format), v1, v2, v3);
 208     }
 209 
 210     /**








































 211      * Print {@code number} as decimal string to {@code buffer}.
 212      *
 213      * @param buffer
 214      * @param number
 215      * @return A pointer pointing one byte right after the last printed digit in {@code buffer}.
 216      */
 217     public static Word printNumber(Word buffer, long number) {
 218         long tmpNumber = number;
 219         int offset;
 220         if (tmpNumber <= 0) {
 221             tmpNumber = -tmpNumber;
 222             offset = 1;
 223         } else {
 224             offset = 0;
 225         }
 226         while (tmpNumber > 0) {
 227             tmpNumber /= 10;
 228             offset++;
 229         }
 230         tmpNumber = number < 0 ? -number : number;


< prev index next >