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