1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   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 package jdk.vm.ci.hotspot;
  24 
  25 import java.nio.ByteBuffer;
  26 import java.nio.ByteOrder;
  27 import java.util.Arrays;
  28 import java.util.Comparator;
  29 import java.util.List;
  30 import java.util.stream.Stream;
  31 import java.util.stream.Stream.Builder;
  32 
  33 import jdk.vm.ci.code.BytecodeFrame;
  34 import jdk.vm.ci.code.CompilationResult;
  35 import jdk.vm.ci.code.CompilationResult.CodeAnnotation;
  36 import jdk.vm.ci.code.CompilationResult.CodeComment;
  37 import jdk.vm.ci.code.CompilationResult.DataPatch;
  38 import jdk.vm.ci.code.CompilationResult.ExceptionHandler;
  39 import jdk.vm.ci.code.CompilationResult.Infopoint;
  40 import jdk.vm.ci.code.CompilationResult.JumpTable;
  41 import jdk.vm.ci.code.CompilationResult.Mark;
  42 import jdk.vm.ci.code.CompilationResult.Site;
  43 import jdk.vm.ci.code.DataSection;
  44 import jdk.vm.ci.meta.Assumptions.Assumption;
  45 import jdk.vm.ci.meta.ResolvedJavaMethod;
  46 
  47 /**
  48  * A {@link CompilationResult} with additional HotSpot-specific information required for installing
  49  * the code in HotSpot's code cache.
  50  */
  51 public class HotSpotCompiledCode {
  52 
  53     public final String name;
  54     public final Site[] sites;
  55     public final ExceptionHandler[] exceptionHandlers;
  56     public final Comment[] comments;
  57     public final Assumption[] assumptions;
  58 
  59     public final byte[] targetCode;
  60     public final int targetCodeSize;
  61 
  62     public final byte[] dataSection;
  63     public final int dataSectionAlignment;
  64     public final DataPatch[] dataSectionPatches;
  65     public final boolean isImmutablePIC;
  66 
  67     public final int totalFrameSize;
  68     public final int customStackAreaOffset;
  69 
  70     /**
  71      * The list of the methods whose bytecodes were used as input to the compilation. If
  72      * {@code null}, then the compilation did not record method dependencies. Otherwise, the first
  73      * element of this array is the root method of the compilation.
  74      */
  75     public final ResolvedJavaMethod[] methods;
  76 
  77     public static class Comment {
  78 
  79         public final String text;
  80         public final int pcOffset;
  81 
  82         public Comment(int pcOffset, String text) {
  83             this.text = text;
  84             this.pcOffset = pcOffset;
  85         }
  86     }
  87 
  88     public HotSpotCompiledCode(CompilationResult compResult) {
  89         name = compResult.getName();
  90         sites = getSortedSites(compResult);
  91         if (compResult.getExceptionHandlers().isEmpty()) {
  92             exceptionHandlers = null;
  93         } else {
  94             exceptionHandlers = compResult.getExceptionHandlers().toArray(new ExceptionHandler[compResult.getExceptionHandlers().size()]);
  95         }
  96         List<CodeAnnotation> annotations = compResult.getAnnotations();
  97         comments = new Comment[annotations.size()];
  98         if (!annotations.isEmpty()) {
  99             for (int i = 0; i < comments.length; i++) {
 100                 CodeAnnotation annotation = annotations.get(i);
 101                 String text;
 102                 if (annotation instanceof CodeComment) {
 103                     CodeComment codeComment = (CodeComment) annotation;
 104                     text = codeComment.value;
 105                 } else if (annotation instanceof JumpTable) {
 106                     JumpTable jumpTable = (JumpTable) annotation;
 107                     text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]";
 108                 } else {
 109                     text = annotation.toString();
 110                 }
 111                 comments[i] = new Comment(annotation.position, text);
 112             }
 113         }
 114         assumptions = compResult.getAssumptions();
 115         assert validateFrames();
 116 
 117         targetCode = compResult.getTargetCode();
 118         targetCodeSize = compResult.getTargetCodeSize();
 119 
 120         DataSection data = compResult.getDataSection();
 121         data.finalizeLayout();
 122         dataSection = new byte[data.getSectionSize()];
 123 
 124         ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());
 125         Builder<DataPatch> patchBuilder = Stream.builder();
 126         data.buildDataSection(buffer, patchBuilder);
 127 
 128         dataSectionAlignment = data.getSectionAlignment();
 129         dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]);
 130 
 131         isImmutablePIC = compResult.isImmutablePIC();
 132 
 133         totalFrameSize = compResult.getTotalFrameSize();
 134         customStackAreaOffset = compResult.getCustomStackAreaOffset();
 135 
 136         methods = compResult.getMethods();
 137     }
 138 
 139     /**
 140      * Ensure that all the frames passed into HotSpot are properly formatted with an empty or
 141      * illegal slot following double word slots.
 142      */
 143     private boolean validateFrames() {
 144         for (Site site : sites) {
 145             if (site instanceof Infopoint) {
 146                 Infopoint info = (Infopoint) site;
 147                 if (info.debugInfo != null) {
 148                     BytecodeFrame frame = info.debugInfo.frame();
 149                     assert frame == null || frame.validateFormat();
 150                 }
 151             }
 152         }
 153         return true;
 154     }
 155 
 156     static class SiteComparator implements Comparator<Site> {
 157 
 158         public int compare(Site s1, Site s2) {
 159             if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) {
 160                 return s1 instanceof Mark ? -1 : 1;
 161             }
 162             return s1.pcOffset - s2.pcOffset;
 163         }
 164     }
 165 
 166     private static Site[] getSortedSites(CompilationResult target) {
 167         List<?>[] lists = new List<?>[]{target.getInfopoints(), target.getDataPatches(), target.getMarks()};
 168         int count = 0;
 169         for (List<?> list : lists) {
 170             count += list.size();
 171         }
 172         Site[] result = new Site[count];
 173         int pos = 0;
 174         for (List<?> list : lists) {
 175             for (Object elem : list) {
 176                 result[pos++] = (Site) elem;
 177             }
 178         }
 179         Arrays.sort(result, new SiteComparator());
 180         return result;
 181     }
 182 
 183     @Override
 184     public String toString() {
 185         return name;
 186     }
 187 }