src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java
changeset 54669 ad45b3802d4e
parent 54601 c40b2a190173
child 54914 9feb4852536f
equal deleted inserted replaced
54668:0bda2308eded 54669:ad45b3802d4e
     1 /*
     1 /*
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    27 import static java.lang.Thread.currentThread;
    27 import static java.lang.Thread.currentThread;
    28 
    28 
    29 import java.io.IOException;
    29 import java.io.IOException;
    30 import java.io.InputStream;
    30 import java.io.InputStream;
    31 import java.util.Arrays;
    31 import java.util.Arrays;
       
    32 import java.util.ArrayList;
       
    33 import java.util.HashMap;
    32 import java.util.Iterator;
    34 import java.util.Iterator;
    33 import java.util.List;
    35 import java.util.List;
       
    36 import java.util.Map;
    34 import java.util.ServiceConfigurationError;
    37 import java.util.ServiceConfigurationError;
    35 import java.util.ServiceLoader;
    38 import java.util.ServiceLoader;
    36 import java.util.concurrent.atomic.AtomicLong;
    39 import java.util.concurrent.atomic.AtomicLong;
    37 
    40 import java.util.function.Supplier;
       
    41 
       
    42 import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject;
       
    43 
       
    44 import jdk.vm.ci.code.BytecodePosition;
       
    45 import jdk.vm.ci.meta.ResolvedJavaField;
       
    46 import jdk.vm.ci.meta.ResolvedJavaMethod;
       
    47 import jdk.vm.ci.meta.ResolvedJavaType;
    38 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
    48 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
       
    49 import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
    39 import jdk.vm.ci.runtime.JVMCI;
    50 import jdk.vm.ci.runtime.JVMCI;
    40 import jdk.vm.ci.services.JVMCIPermission;
    51 import jdk.vm.ci.services.JVMCIPermission;
    41 import jdk.vm.ci.services.Services;
    52 import jdk.vm.ci.services.Services;
    42 
    53 
       
    54 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
       
    55 import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
       
    56 
    43 /**
    57 /**
    44  * JDK 9+ version of {@link GraalServices}.
    58  * JDK 13+ version of {@link GraalServices}.
    45  */
    59  */
    46 public final class GraalServices {
    60 public final class GraalServices {
    47 
    61 
       
    62     private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
       
    63 
    48     private GraalServices() {
    64     private GraalServices() {
    49     }
    65     }
    50 
    66 
    51     /**
    67     /**
    52      * Gets an {@link Iterable} of the providers available for a given service.
    68      * Gets an {@link Iterable} of the providers available for a given service.
    53      *
    69      *
    54      * @throws SecurityException if on JDK8 and a security manager is present and it denies
    70      * @throws SecurityException if on JDK8 and a security manager is present and it denies
    55      *             {@link JVMCIPermission}
    71      *             {@link JVMCIPermission}
    56      */
    72      */
       
    73     @SuppressWarnings("unchecked")
    57     public static <S> Iterable<S> load(Class<S> service) {
    74     public static <S> Iterable<S> load(Class<S> service) {
    58         Iterable<S> iterable = ServiceLoader.load(service);
    75         if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
       
    76             List<?> list = servicesCache.get(service);
       
    77             if (list != null) {
       
    78                 return (Iterable<S>) list;
       
    79             }
       
    80             if (IS_IN_NATIVE_IMAGE) {
       
    81                 throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
       
    82             }
       
    83         }
       
    84 
       
    85         Iterable<S> providers = load0(service);
       
    86 
       
    87         if (IS_BUILDING_NATIVE_IMAGE) {
       
    88             synchronized (servicesCache) {
       
    89                 ArrayList<S> providersList = new ArrayList<>();
       
    90                 for (S provider : providers) {
       
    91                     providersList.add(provider);
       
    92                 }
       
    93                 providers = providersList;
       
    94                 servicesCache.put(service, providersList);
       
    95                 return providers;
       
    96             }
       
    97         }
       
    98 
       
    99         return providers;
       
   100     }
       
   101 
       
   102     protected static <S> Iterable<S> load0(Class<S> service) {
       
   103         Iterable<S> iterable = ServiceLoader.load(service, GraalServices.class.getClassLoader());
    59         return new Iterable<>() {
   104         return new Iterable<>() {
    60             @Override
   105             @Override
    61             public Iterator<S> iterator() {
   106             public Iterator<S> iterator() {
    62                 Iterator<S> iterator = iterable.iterator();
   107                 Iterator<S> iterator = iterable.iterator();
    63                 return new Iterator<>() {
   108                 return new Iterator<>() {
    88      * opened all its packages to the module defining {@link GraalServices}.
   133      * opened all its packages to the module defining {@link GraalServices}.
    89      *
   134      *
    90      * @param other all JVMCI packages will be opened to the module defining this class
   135      * @param other all JVMCI packages will be opened to the module defining this class
    91      */
   136      */
    92     static void openJVMCITo(Class<?> other) {
   137     static void openJVMCITo(Class<?> other) {
       
   138         if (IS_IN_NATIVE_IMAGE) return;
       
   139 
    93         Module jvmciModule = JVMCI_MODULE;
   140         Module jvmciModule = JVMCI_MODULE;
    94         Module otherModule = other.getModule();
   141         Module otherModule = other.getModule();
    95         if (jvmciModule != otherModule) {
   142         if (jvmciModule != otherModule) {
    96             for (String pkg : jvmciModule.getPackages()) {
   143             for (String pkg : jvmciModule.getPackages()) {
    97                 if (!jvmciModule.isOpen(pkg, otherModule)) {
   144                 if (!jvmciModule.isOpen(pkg, otherModule)) {
    98                     // JVMCI initialization opens all JVMCI packages
   145                     // JVMCI initialization opens all JVMCI packages
    99                     // to Graal which is a prerequisite for Graal to
   146                     // to Graal which is a prerequisite for Graal to
   100                     // open JVMCI packages to other modules.
   147                     // open JVMCI packages to other modules.
   101                     JVMCI.initialize();
   148                     JVMCI.getRuntime();
   102 
   149 
   103                     jvmciModule.addOpens(pkg, otherModule);
   150                     jvmciModule.addOpens(pkg, otherModule);
   104                 }
   151                 }
   105             }
   152             }
   106         }
   153         }
   177      */
   224      */
   178     static final class DirectSpeculationReason implements SpeculationReason {
   225     static final class DirectSpeculationReason implements SpeculationReason {
   179         final int groupId;
   226         final int groupId;
   180         final String groupName;
   227         final String groupName;
   181         final Object[] context;
   228         final Object[] context;
       
   229         private SpeculationReasonEncoding encoding;
   182 
   230 
   183         DirectSpeculationReason(int groupId, String groupName, Object[] context) {
   231         DirectSpeculationReason(int groupId, String groupName, Object[] context) {
   184             this.groupId = groupId;
   232             this.groupId = groupId;
   185             this.groupName = groupName;
   233             this.groupName = groupName;
   186             this.context = context;
   234             this.context = context;
   201         }
   249         }
   202 
   250 
   203         @Override
   251         @Override
   204         public String toString() {
   252         public String toString() {
   205             return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context));
   253             return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context));
       
   254         }
       
   255 
       
   256         @Override
       
   257         public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
       
   258             if (encoding == null) {
       
   259                 encoding = encodingSupplier.get();
       
   260                 encoding.addInt(groupId);
       
   261                 for (Object o : context) {
       
   262                     if (o == null) {
       
   263                         encoding.addInt(0);
       
   264                     } else {
       
   265                         addNonNullObject(encoding, o);
       
   266                     }
       
   267                 }
       
   268             }
       
   269             return encoding;
       
   270         }
       
   271 
       
   272         static void addNonNullObject(SpeculationReasonEncoding encoding, Object o) {
       
   273             Class<? extends Object> c = o.getClass();
       
   274             if (c == String.class) {
       
   275                 encoding.addString((String) o);
       
   276             } else if (c == Byte.class) {
       
   277                 encoding.addByte((Byte) o);
       
   278             } else if (c == Short.class) {
       
   279                 encoding.addShort((Short) o);
       
   280             } else if (c == Character.class) {
       
   281                 encoding.addShort((Character) o);
       
   282             } else if (c == Integer.class) {
       
   283                 encoding.addInt((Integer) o);
       
   284             } else if (c == Long.class) {
       
   285                 encoding.addLong((Long) o);
       
   286             } else if (c == Float.class) {
       
   287                 encoding.addInt(Float.floatToRawIntBits((Float) o));
       
   288             } else if (c == Double.class) {
       
   289                 encoding.addLong(Double.doubleToRawLongBits((Double) o));
       
   290             } else if (o instanceof Enum) {
       
   291                 encoding.addInt(((Enum<?>) o).ordinal());
       
   292             } else if (o instanceof ResolvedJavaMethod) {
       
   293                 encoding.addMethod((ResolvedJavaMethod) o);
       
   294             } else if (o instanceof ResolvedJavaType) {
       
   295                 encoding.addType((ResolvedJavaType) o);
       
   296             } else if (o instanceof ResolvedJavaField) {
       
   297                 encoding.addField((ResolvedJavaField) o);
       
   298             } else if (o instanceof SpeculationContextObject) {
       
   299                 SpeculationContextObject sco = (SpeculationContextObject) o;
       
   300                 // These are compiler objects which all have the same class
       
   301                 // loader so the class name uniquely identifies the class.
       
   302                 encoding.addString(o.getClass().getName());
       
   303                 sco.accept(new EncodingAdapter(encoding));
       
   304             } else if (o.getClass() == BytecodePosition.class) {
       
   305                 BytecodePosition p = (BytecodePosition) o;
       
   306                 while (p != null) {
       
   307                     encoding.addInt(p.getBCI());
       
   308                     encoding.addMethod(p.getMethod());
       
   309                     p = p.getCaller();
       
   310                 }
       
   311             } else {
       
   312                 throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName());
       
   313             }
       
   314         }
       
   315     }
       
   316 
       
   317     static class EncodingAdapter implements SpeculationContextObject.Visitor {
       
   318         private final SpeculationReasonEncoding encoding;
       
   319 
       
   320         EncodingAdapter(SpeculationReasonEncoding encoding) {
       
   321             this.encoding = encoding;
       
   322         }
       
   323 
       
   324         @Override
       
   325         public void visitBoolean(boolean v) {
       
   326             encoding.addByte(v ? 1 : 0);
       
   327         }
       
   328 
       
   329         @Override
       
   330         public void visitByte(byte v) {
       
   331             encoding.addByte(v);
       
   332         }
       
   333 
       
   334         @Override
       
   335         public void visitChar(char v) {
       
   336             encoding.addShort(v);
       
   337         }
       
   338 
       
   339         @Override
       
   340         public void visitShort(short v) {
       
   341             encoding.addInt(v);
       
   342         }
       
   343 
       
   344         @Override
       
   345         public void visitInt(int v) {
       
   346             encoding.addInt(v);
       
   347         }
       
   348 
       
   349         @Override
       
   350         public void visitLong(long v) {
       
   351             encoding.addLong(v);
       
   352         }
       
   353 
       
   354         @Override
       
   355         public void visitFloat(float v) {
       
   356             encoding.addInt(Float.floatToRawIntBits(v));
       
   357         }
       
   358 
       
   359         @Override
       
   360         public void visitDouble(double v) {
       
   361             encoding.addLong(Double.doubleToRawLongBits(v));
       
   362         }
       
   363 
       
   364         @Override
       
   365         public void visitObject(Object v) {
       
   366             if (v == null) {
       
   367                 encoding.addInt(0);
       
   368             } else {
       
   369                 DirectSpeculationReason.addNonNullObject(encoding, v);
       
   370             }
   206         }
   371         }
   207     }
   372     }
   208 
   373 
   209     static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) {
   374     static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) {
   210         return new DirectSpeculationReason(groupId, groupName, context);
   375         return new DirectSpeculationReason(groupId, groupName, context);