< 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


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

  27 import static org.graalvm.util.CollectionsUtil.anyMatch;
  28 
  29 import java.nio.ByteBuffer;
  30 import java.nio.ByteOrder;
  31 import java.util.ArrayList;
  32 import java.util.Collections;
  33 import java.util.Comparator;
  34 import java.util.EnumMap;
  35 import java.util.List;

  36 import java.util.Map;
  37 import java.util.stream.Stream;
  38 import java.util.stream.Stream.Builder;
  39 


  40 import org.graalvm.compiler.code.CompilationResult;
  41 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
  42 import org.graalvm.compiler.code.CompilationResult.CodeComment;
  43 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  44 import org.graalvm.compiler.code.DataSection;
  45 import org.graalvm.compiler.code.SourceMapping;
  46 import org.graalvm.compiler.debug.GraalError;
  47 import org.graalvm.compiler.graph.NodeSourcePosition;



  48 
  49 import jdk.vm.ci.code.CodeCacheProvider;
  50 import jdk.vm.ci.code.DebugInfo;
  51 import jdk.vm.ci.code.StackSlot;
  52 import jdk.vm.ci.code.site.ConstantReference;
  53 import jdk.vm.ci.code.site.DataPatch;
  54 import jdk.vm.ci.code.site.Infopoint;
  55 import jdk.vm.ci.code.site.InfopointReason;
  56 import jdk.vm.ci.code.site.Mark;
  57 import jdk.vm.ci.code.site.Site;
  58 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
  59 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
  60 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
  61 import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
  62 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
  63 import jdk.vm.ci.meta.Assumptions.Assumption;
  64 import jdk.vm.ci.meta.ResolvedJavaMethod;
  65 
  66 public class HotSpotCompiledCodeBuilder {






  67 
  68     public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) {
  69         String name = compResult.getName();
  70 
  71         byte[] targetCode = compResult.getTargetCode();
  72         int targetCodeSize = compResult.getTargetCodeSize();
  73 
  74         Site[] sites = getSortedSites(codeCache, compResult);
  75 
  76         Assumption[] assumptions = compResult.getAssumptions();
  77 
  78         ResolvedJavaMethod[] methods = compResult.getMethods();
  79 
  80         List<CodeAnnotation> annotations = compResult.getAnnotations();
  81         Comment[] comments = new Comment[annotations.size()];
  82         if (!annotations.isEmpty()) {
  83             for (int i = 0; i < comments.length; i++) {
  84                 CodeAnnotation annotation = annotations.get(i);
  85                 String text;
  86                 if (annotation instanceof CodeComment) {
  87                     CodeComment codeComment = (CodeComment) annotation;
  88                     text = codeComment.value;
  89                 } else if (annotation instanceof JumpTable) {
  90                     JumpTable jumpTable = (JumpTable) annotation;
  91                     text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]";
  92                 } else {
  93                     text = annotation.toString();
  94                 }


 188                 boolean s1IsInfopoint = s1 instanceof Infopoint;
 189                 boolean s2IsInfopoint = s2 instanceof Infopoint;
 190                 if (s1IsInfopoint != s2IsInfopoint) {
 191                     return s1IsInfopoint ? 1 : -1;
 192                 }
 193 
 194                 if (s1IsInfopoint) {
 195                     sawCollidingInfopoints = true;
 196                     return checkCollision((Infopoint) s1, (Infopoint) s2);
 197                 }
 198             }
 199             return s1.pcOffset - s2.pcOffset;
 200         }
 201     }
 202 
 203     /**
 204      * HotSpot expects sites to be presented in ascending order of PC (see
 205      * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects
 206      * {@link Infopoint} PCs to be unique.
 207      */
 208     private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) {
 209         List<Site> sites = new ArrayList<>(
 210                         target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size());
 211         sites.addAll(target.getExceptionHandlers());
 212         sites.addAll(target.getInfopoints());
 213         sites.addAll(target.getDataPatches());
 214         sites.addAll(target.getMarks());
 215 
 216         if (codeCache.shouldDebugNonSafepoints()) {
 217             /*
 218              * Translate the source mapping into appropriate info points. In HotSpot only one
 219              * position can really be represented and recording the end PC seems to give the best
 220              * results and corresponds with what C1 and C2 do. HotSpot doesn't like to see these
 221              * unless -XX:+DebugNonSafepoints is enabled, so don't emit them in that case.
 222              */
 223             List<Site> sourcePositionSites = new ArrayList<>();
 224             for (SourceMapping source : target.getSourceMappings()) {
 225                 NodeSourcePosition sourcePosition = source.getSourcePosition();
 226                 if (sourcePosition.isPlaceholder() || sourcePosition.isSubstitution()) {
 227                     // HotSpot doesn't understand any of the special positions so just drop them.
 228                     continue;










 229                 }
 230                 assert sourcePosition.verify();
 231                 sourcePosition = sourcePosition.trim();

 232                 /*
 233                  * Don't add BYTECODE_POSITION info points that would potentially create conflicts.
 234                  * Under certain conditions the site's pc is not the pc that gets recorded by
 235                  * HotSpot (see @code {CodeInstaller::site_Call}). So, avoid adding any source
 236                  * positions that can potentially map to the same pc. To do that make sure that the
 237                  * source mapping doesn't contain a pc of any important Site.
 238                  */
 239                 if (sourcePosition != null && !anyMatch(sites, s -> source.contains(s.pcOffset))) {
 240                     sourcePositionSites.add(new Infopoint(source.getEndOffset(), new DebugInfo(sourcePosition), InfopointReason.BYTECODE_POSITION));


 241 















 242                 }
 243             }





















 244             sites.addAll(sourcePositionSites);
 245         }
 246 
 247         SiteComparator c = new SiteComparator();
 248         Collections.sort(sites, c);

 249         if (c.sawCollidingInfopoints) {
 250             Infopoint lastInfopoint = null;
 251             List<Site> copy = new ArrayList<>(sites.size());
 252             for (Site site : sites) {
 253                 if (site instanceof Infopoint) {
 254                     Infopoint info = (Infopoint) site;
 255                     if (lastInfopoint == null || lastInfopoint.pcOffset != info.pcOffset) {
 256                         lastInfopoint = info;
 257                         copy.add(info);
 258                     } else {
 259                         // Omit this colliding infopoint
 260                         assert lastInfopoint.reason.compareTo(info.reason) <= 0;
 261                     }
 262                 } else {
 263                     copy.add(site);
 264                 }
 265             }
 266             sites = copy;
 267         }

 268         return sites.toArray(new Site[sites.size()]);







 269     }
 270 }


   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;
  26 
  27 import static org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder.Options.ShowSubstitutionSourceInfo;
  28 import static org.graalvm.util.CollectionsUtil.anyMatch;
  29 
  30 import java.nio.ByteBuffer;
  31 import java.nio.ByteOrder;
  32 import java.util.ArrayList;
  33 import java.util.Collections;
  34 import java.util.Comparator;
  35 import java.util.EnumMap;
  36 import java.util.List;
  37 import java.util.ListIterator;
  38 import java.util.Map;
  39 import java.util.stream.Stream;
  40 import java.util.stream.Stream.Builder;
  41 
  42 import org.graalvm.compiler.api.replacements.MethodSubstitution;
  43 import org.graalvm.compiler.api.replacements.Snippet;
  44 import org.graalvm.compiler.code.CompilationResult;
  45 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
  46 import org.graalvm.compiler.code.CompilationResult.CodeComment;
  47 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  48 import org.graalvm.compiler.code.DataSection;
  49 import org.graalvm.compiler.code.SourceMapping;
  50 import org.graalvm.compiler.debug.GraalError;
  51 import org.graalvm.compiler.graph.NodeSourcePosition;
  52 import org.graalvm.compiler.options.Option;
  53 import org.graalvm.compiler.options.OptionKey;
  54 import org.graalvm.compiler.options.OptionValues;
  55 
  56 import jdk.vm.ci.code.CodeCacheProvider;
  57 import jdk.vm.ci.code.DebugInfo;
  58 import jdk.vm.ci.code.StackSlot;
  59 import jdk.vm.ci.code.site.ConstantReference;
  60 import jdk.vm.ci.code.site.DataPatch;
  61 import jdk.vm.ci.code.site.Infopoint;
  62 import jdk.vm.ci.code.site.InfopointReason;
  63 import jdk.vm.ci.code.site.Mark;
  64 import jdk.vm.ci.code.site.Site;
  65 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
  66 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
  67 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
  68 import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
  69 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
  70 import jdk.vm.ci.meta.Assumptions.Assumption;
  71 import jdk.vm.ci.meta.ResolvedJavaMethod;
  72 
  73 public class HotSpotCompiledCodeBuilder {
  74     public static class Options {
  75         // @formatter:off
  76         @Option(help = "Controls whether the source position information of snippets and method substitutions" +
  77                 " are exposed to HotSpot.  Can be useful when profiling to get more precise position information.")
  78         public static final OptionKey<Boolean> ShowSubstitutionSourceInfo = new OptionKey<>(false);
  79     }
  80 
  81     public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult, OptionValues options) {
  82         String name = compResult.getName();
  83 
  84         byte[] targetCode = compResult.getTargetCode();
  85         int targetCodeSize = compResult.getTargetCodeSize();
  86 
  87         Site[] sites = getSortedSites(compResult, options, codeCache.shouldDebugNonSafepoints() && method != null);
  88 
  89         Assumption[] assumptions = compResult.getAssumptions();
  90 
  91         ResolvedJavaMethod[] methods = compResult.getMethods();
  92 
  93         List<CodeAnnotation> annotations = compResult.getAnnotations();
  94         Comment[] comments = new Comment[annotations.size()];
  95         if (!annotations.isEmpty()) {
  96             for (int i = 0; i < comments.length; i++) {
  97                 CodeAnnotation annotation = annotations.get(i);
  98                 String text;
  99                 if (annotation instanceof CodeComment) {
 100                     CodeComment codeComment = (CodeComment) annotation;
 101                     text = codeComment.value;
 102                 } else if (annotation instanceof JumpTable) {
 103                     JumpTable jumpTable = (JumpTable) annotation;
 104                     text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]";
 105                 } else {
 106                     text = annotation.toString();
 107                 }


 201                 boolean s1IsInfopoint = s1 instanceof Infopoint;
 202                 boolean s2IsInfopoint = s2 instanceof Infopoint;
 203                 if (s1IsInfopoint != s2IsInfopoint) {
 204                     return s1IsInfopoint ? 1 : -1;
 205                 }
 206 
 207                 if (s1IsInfopoint) {
 208                     sawCollidingInfopoints = true;
 209                     return checkCollision((Infopoint) s1, (Infopoint) s2);
 210                 }
 211             }
 212             return s1.pcOffset - s2.pcOffset;
 213         }
 214     }
 215 
 216     /**
 217      * HotSpot expects sites to be presented in ascending order of PC (see
 218      * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects
 219      * {@link Infopoint} PCs to be unique.
 220      */
 221     private static Site[] getSortedSites(CompilationResult target, OptionValues options, boolean includeSourceInfo) {
 222         List<Site> sites = new ArrayList<>(
 223                         target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size());
 224         sites.addAll(target.getExceptionHandlers());
 225         sites.addAll(target.getInfopoints());
 226         sites.addAll(target.getDataPatches());
 227         sites.addAll(target.getMarks());
 228 
 229         if (includeSourceInfo) {
 230             /*
 231              * Translate the source mapping into appropriate info points. In HotSpot only one
 232              * position can really be represented and recording the end PC seems to give the best
 233              * results and corresponds with what C1 and C2 do. HotSpot doesn't like to see these
 234              * unless -XX:+DebugNonSafepoints is enabled, so don't emit them in that case.
 235              */
 236 
 237             List<SourceMapping> sourceMappings = new ArrayList<>();
 238             ListIterator<SourceMapping> sourceMappingListIterator = target.getSourceMappings().listIterator();
 239             if (sourceMappingListIterator.hasNext()) {
 240                 SourceMapping currentSource = sourceMappingListIterator.next();
 241                 NodeSourcePosition sourcePosition = currentSource.getSourcePosition();
 242                 if (!sourcePosition.isPlaceholder() && !sourcePosition.isSubstitution()) {
 243                     sourceMappings.add(currentSource);
 244                 }
 245                 while (sourceMappingListIterator.hasNext()) {
 246                     SourceMapping nextSource = sourceMappingListIterator.next();
 247                     assert currentSource.getStartOffset() <= nextSource.getStartOffset() : "Must be presorted";
 248                     currentSource = nextSource;
 249                     sourcePosition = currentSource.getSourcePosition();
 250                     if (!sourcePosition.isPlaceholder() && !sourcePosition.isSubstitution()) {
 251                         sourceMappings.add(currentSource);
 252                     }
 253                 }
 254             }
 255 
 256             /*
 257              * Don't add BYTECODE_POSITION info points that would potentially create conflicts.
 258              * Under certain conditions the site's pc is not the pc that gets recorded by HotSpot
 259              * (see @code {CodeInstaller::site_Call}). So, avoid adding any source positions that
 260              * can potentially map to the same pc. To do that the following code makes sure that the
 261              * source mapping doesn't contain a pc of any important Site.
 262              */
 263             sites.sort(new SiteComparator());
 264 
 265             ListIterator<Site> siteListIterator = sites.listIterator();
 266             sourceMappingListIterator = sourceMappings.listIterator();
 267 
 268             List<Site> sourcePositionSites = new ArrayList<>();
 269             Site site = null;
 270 
 271             // Iterate over sourceMappings and sites in parallel. Create source position infopoints
 272             // only for source mappings that don't have any sites inside their intervals.
 273             while (sourceMappingListIterator.hasNext()) {
 274                 SourceMapping source = sourceMappingListIterator.next();
 275 
 276                 // Skip sites before the current source mapping
 277                 if (site == null || site.pcOffset < source.getStartOffset()) {
 278                     while (siteListIterator.hasNext()) {
 279                         site = siteListIterator.next();
 280                         if (site.pcOffset >= source.getStartOffset()) {
 281                             break;
 282                         }
 283                     }
 284                 }
 285                 assert !siteListIterator.hasNext() || site.pcOffset >= source.getStartOffset();
 286                 if (site != null && source.getStartOffset() <= site.pcOffset && site.pcOffset <= source.getEndOffset()) {
 287                     // Conflicting source mapping, skip it.
 288                     continue;
 289                 } else {
 290                     // Since the sites are sorted there can not be any more sites in this interval.
 291                 }
 292                 assert !siteListIterator.hasNext() || site.pcOffset > source.getEndOffset();
 293                 // Good source mapping. Create an infopoint and add it to the list.
 294                 NodeSourcePosition sourcePosition = source.getSourcePosition();
 295                 assert sourcePosition.verify();
 296                 if (!ShowSubstitutionSourceInfo.getValue(options)) {
 297                     sourcePosition = sourcePosition.trim();
 298                     assert verifyTrim(sourcePosition);
 299                 }
 300                 if (sourcePosition != null) {
 301                     assert !anyMatch(sites, s -> source.getStartOffset() <= s.pcOffset && s.pcOffset <= source.getEndOffset());
 302                     sourcePositionSites.add(new Infopoint(source.getEndOffset(), new DebugInfo(sourcePosition), InfopointReason.BYTECODE_POSITION));
 303                 }
 304             }
 305 
 306             sites.addAll(sourcePositionSites);
 307         }
 308 
 309         SiteComparator c = new SiteComparator();
 310         Collections.sort(sites, c);
 311 
 312         if (c.sawCollidingInfopoints) {
 313             Infopoint lastInfopoint = null;
 314             List<Site> copy = new ArrayList<>(sites.size());
 315             for (Site site : sites) {
 316                 if (site instanceof Infopoint) {
 317                     Infopoint info = (Infopoint) site;
 318                     if (lastInfopoint == null || lastInfopoint.pcOffset != info.pcOffset) {
 319                         lastInfopoint = info;
 320                         copy.add(info);
 321                     } else {
 322                         // Omit this colliding infopoint
 323                         assert lastInfopoint.reason.compareTo(info.reason) <= 0;
 324                     }
 325                 } else {
 326                     copy.add(site);
 327                 }
 328             }
 329             sites = copy;
 330         }
 331 
 332         return sites.toArray(new Site[sites.size()]);
 333     }
 334 
 335     private static boolean verifyTrim(NodeSourcePosition sourcePosition) {
 336         for (NodeSourcePosition sp = sourcePosition; sp != null; sp = sp.getCaller()) {
 337             assert (sp.getMethod().getAnnotation(Snippet.class) == null && sp.getMethod().getAnnotation(MethodSubstitution.class) == null);
 338         }
 339         return true;
 340     }
 341 }
< prev index next >