< 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 >