< prev index next >

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

Print this page
rev 52509 : [mq]: graal

@@ -22,31 +22,38 @@
  */
 
 
 package org.graalvm.compiler.hotspot;
 
+import static org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder.Options.ShowSubstitutionSourceInfo;
 import static org.graalvm.util.CollectionsUtil.anyMatch;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumMap;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.stream.Stream;
 import java.util.stream.Stream.Builder;
 
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
 import org.graalvm.compiler.code.CompilationResult.CodeComment;
 import org.graalvm.compiler.code.CompilationResult.JumpTable;
 import org.graalvm.compiler.code.DataSection;
 import org.graalvm.compiler.code.SourceMapping;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.code.DebugInfo;
 import jdk.vm.ci.code.StackSlot;
 import jdk.vm.ci.code.site.ConstantReference;

@@ -62,18 +69,24 @@
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.meta.Assumptions.Assumption;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class HotSpotCompiledCodeBuilder {
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Controls whether the source position information of snippets and method substitutions" +
+                " are exposed to HotSpot.  Can be useful when profiling to get more precise position information.")
+        public static final OptionKey<Boolean> ShowSubstitutionSourceInfo = new OptionKey<>(false);
+    }
 
-    public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) {
+    public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult, OptionValues options) {
         String name = compResult.getName();
 
         byte[] targetCode = compResult.getTargetCode();
         int targetCodeSize = compResult.getTargetCodeSize();
 
-        Site[] sites = getSortedSites(codeCache, compResult);
+        Site[] sites = getSortedSites(compResult, options, codeCache.shouldDebugNonSafepoints() && method != null);
 
         Assumption[] assumptions = compResult.getAssumptions();
 
         ResolvedJavaMethod[] methods = compResult.getMethods();
 

@@ -203,51 +216,101 @@
     /**
      * HotSpot expects sites to be presented in ascending order of PC (see
      * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects
      * {@link Infopoint} PCs to be unique.
      */
-    private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) {
+    private static Site[] getSortedSites(CompilationResult target, OptionValues options, boolean includeSourceInfo) {
         List<Site> sites = new ArrayList<>(
                         target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size());
         sites.addAll(target.getExceptionHandlers());
         sites.addAll(target.getInfopoints());
         sites.addAll(target.getDataPatches());
         sites.addAll(target.getMarks());
 
-        if (codeCache.shouldDebugNonSafepoints()) {
+        if (includeSourceInfo) {
             /*
              * Translate the source mapping into appropriate info points. In HotSpot only one
              * position can really be represented and recording the end PC seems to give the best
              * results and corresponds with what C1 and C2 do. HotSpot doesn't like to see these
              * unless -XX:+DebugNonSafepoints is enabled, so don't emit them in that case.
              */
-            List<Site> sourcePositionSites = new ArrayList<>();
-            for (SourceMapping source : target.getSourceMappings()) {
-                NodeSourcePosition sourcePosition = source.getSourcePosition();
-                if (sourcePosition.isPlaceholder() || sourcePosition.isSubstitution()) {
-                    // HotSpot doesn't understand any of the special positions so just drop them.
-                    continue;
+
+            List<SourceMapping> sourceMappings = new ArrayList<>();
+            ListIterator<SourceMapping> sourceMappingListIterator = target.getSourceMappings().listIterator();
+            if (sourceMappingListIterator.hasNext()) {
+                SourceMapping currentSource = sourceMappingListIterator.next();
+                NodeSourcePosition sourcePosition = currentSource.getSourcePosition();
+                if (!sourcePosition.isPlaceholder() && !sourcePosition.isSubstitution()) {
+                    sourceMappings.add(currentSource);
+                }
+                while (sourceMappingListIterator.hasNext()) {
+                    SourceMapping nextSource = sourceMappingListIterator.next();
+                    assert currentSource.getStartOffset() <= nextSource.getStartOffset() : "Must be presorted";
+                    currentSource = nextSource;
+                    sourcePosition = currentSource.getSourcePosition();
+                    if (!sourcePosition.isPlaceholder() && !sourcePosition.isSubstitution()) {
+                        sourceMappings.add(currentSource);
                 }
-                assert sourcePosition.verify();
-                sourcePosition = sourcePosition.trim();
+                }
+            }
+
                 /*
                  * Don't add BYTECODE_POSITION info points that would potentially create conflicts.
-                 * Under certain conditions the site's pc is not the pc that gets recorded by
-                 * HotSpot (see @code {CodeInstaller::site_Call}). So, avoid adding any source
-                 * positions that can potentially map to the same pc. To do that make sure that the
+             * Under certain conditions the site's pc is not the pc that gets recorded by HotSpot
+             * (see @code {CodeInstaller::site_Call}). So, avoid adding any source positions that
+             * can potentially map to the same pc. To do that the following code makes sure that the
                  * source mapping doesn't contain a pc of any important Site.
                  */
-                if (sourcePosition != null && !anyMatch(sites, s -> source.contains(s.pcOffset))) {
-                    sourcePositionSites.add(new Infopoint(source.getEndOffset(), new DebugInfo(sourcePosition), InfopointReason.BYTECODE_POSITION));
+            sites.sort(new SiteComparator());
+
+            ListIterator<Site> siteListIterator = sites.listIterator();
+            sourceMappingListIterator = sourceMappings.listIterator();
 
+            List<Site> sourcePositionSites = new ArrayList<>();
+            Site site = null;
+
+            // Iterate over sourceMappings and sites in parallel. Create source position infopoints
+            // only for source mappings that don't have any sites inside their intervals.
+            while (sourceMappingListIterator.hasNext()) {
+                SourceMapping source = sourceMappingListIterator.next();
+
+                // Skip sites before the current source mapping
+                if (site == null || site.pcOffset < source.getStartOffset()) {
+                    while (siteListIterator.hasNext()) {
+                        site = siteListIterator.next();
+                        if (site.pcOffset >= source.getStartOffset()) {
+                            break;
+                        }
                 }
             }
+                assert !siteListIterator.hasNext() || site.pcOffset >= source.getStartOffset();
+                if (site != null && source.getStartOffset() <= site.pcOffset && site.pcOffset <= source.getEndOffset()) {
+                    // Conflicting source mapping, skip it.
+                    continue;
+                } else {
+                    // Since the sites are sorted there can not be any more sites in this interval.
+                }
+                assert !siteListIterator.hasNext() || site.pcOffset > source.getEndOffset();
+                // Good source mapping. Create an infopoint and add it to the list.
+                NodeSourcePosition sourcePosition = source.getSourcePosition();
+                assert sourcePosition.verify();
+                if (!ShowSubstitutionSourceInfo.getValue(options)) {
+                    sourcePosition = sourcePosition.trim();
+                    assert verifyTrim(sourcePosition);
+                }
+                if (sourcePosition != null) {
+                    assert !anyMatch(sites, s -> source.getStartOffset() <= s.pcOffset && s.pcOffset <= source.getEndOffset());
+                    sourcePositionSites.add(new Infopoint(source.getEndOffset(), new DebugInfo(sourcePosition), InfopointReason.BYTECODE_POSITION));
+                }
+            }
+
             sites.addAll(sourcePositionSites);
         }
 
         SiteComparator c = new SiteComparator();
         Collections.sort(sites, c);
+
         if (c.sawCollidingInfopoints) {
             Infopoint lastInfopoint = null;
             List<Site> copy = new ArrayList<>(sites.size());
             for (Site site : sites) {
                 if (site instanceof Infopoint) {

@@ -263,8 +326,16 @@
                     copy.add(site);
                 }
             }
             sites = copy;
         }
+
         return sites.toArray(new Site[sites.size()]);
     }
+
+    private static boolean verifyTrim(NodeSourcePosition sourcePosition) {
+        for (NodeSourcePosition sp = sourcePosition; sp != null; sp = sp.getCaller()) {
+            assert (sp.getMethod().getAnnotation(Snippet.class) == null && sp.getMethod().getAnnotation(MethodSubstitution.class) == null);
+        }
+        return true;
+    }
 }
< prev index next >