001/* 002 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package jdk.internal.jvmci.hotspot; 024 025import java.nio.*; 026import java.util.*; 027import java.util.stream.*; 028import java.util.stream.Stream.Builder; 029 030import jdk.internal.jvmci.code.*; 031import jdk.internal.jvmci.code.CompilationResult.CodeAnnotation; 032import jdk.internal.jvmci.code.CompilationResult.CodeComment; 033import jdk.internal.jvmci.code.CompilationResult.DataPatch; 034import jdk.internal.jvmci.code.CompilationResult.ExceptionHandler; 035import jdk.internal.jvmci.code.CompilationResult.Infopoint; 036import jdk.internal.jvmci.code.CompilationResult.JumpTable; 037import jdk.internal.jvmci.code.CompilationResult.Mark; 038import jdk.internal.jvmci.code.CompilationResult.Site; 039import jdk.internal.jvmci.meta.Assumptions.Assumption; 040import jdk.internal.jvmci.meta.*; 041 042/** 043 * A {@link CompilationResult} with additional HotSpot-specific information required for installing 044 * the code in HotSpot's code cache. 045 */ 046public abstract class HotSpotCompiledCode { 047 048 public final String name; 049 public final Site[] sites; 050 public final ExceptionHandler[] exceptionHandlers; 051 public final Comment[] comments; 052 public final Assumption[] assumptions; 053 054 public final byte[] targetCode; 055 public final int targetCodeSize; 056 057 public final byte[] dataSection; 058 public final int dataSectionAlignment; 059 public final DataPatch[] dataSectionPatches; 060 061 public final int totalFrameSize; 062 public final int customStackAreaOffset; 063 064 /** 065 * The list of the methods whose bytecodes were used as input to the compilation. If 066 * {@code null}, then the compilation did not record method dependencies. Otherwise, the first 067 * element of this array is the root method of the compilation. 068 */ 069 public final ResolvedJavaMethod[] methods; 070 071 public static class Comment { 072 073 public final String text; 074 public final int pcOffset; 075 076 public Comment(int pcOffset, String text) { 077 this.text = text; 078 this.pcOffset = pcOffset; 079 } 080 } 081 082 public HotSpotCompiledCode(CompilationResult compResult) { 083 name = compResult.getName(); 084 sites = getSortedSites(compResult); 085 if (compResult.getExceptionHandlers().isEmpty()) { 086 exceptionHandlers = null; 087 } else { 088 exceptionHandlers = compResult.getExceptionHandlers().toArray(new ExceptionHandler[compResult.getExceptionHandlers().size()]); 089 } 090 List<CodeAnnotation> annotations = compResult.getAnnotations(); 091 comments = new Comment[annotations.size()]; 092 if (!annotations.isEmpty()) { 093 for (int i = 0; i < comments.length; i++) { 094 CodeAnnotation annotation = annotations.get(i); 095 String text; 096 if (annotation instanceof CodeComment) { 097 CodeComment codeComment = (CodeComment) annotation; 098 text = codeComment.value; 099 } else if (annotation instanceof JumpTable) { 100 JumpTable jumpTable = (JumpTable) annotation; 101 text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]"; 102 } else { 103 text = annotation.toString(); 104 } 105 comments[i] = new Comment(annotation.position, text); 106 } 107 } 108 assumptions = compResult.getAssumptions(); 109 assert validateFrames(); 110 111 targetCode = compResult.getTargetCode(); 112 targetCodeSize = compResult.getTargetCodeSize(); 113 114 DataSection data = compResult.getDataSection(); 115 data.finalizeLayout(); 116 dataSection = new byte[data.getSectionSize()]; 117 118 ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder()); 119 Builder<DataPatch> patchBuilder = Stream.builder(); 120 data.buildDataSection(buffer, patchBuilder); 121 122 dataSectionAlignment = data.getSectionAlignment(); 123 dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]); 124 125 totalFrameSize = compResult.getTotalFrameSize(); 126 customStackAreaOffset = compResult.getCustomStackAreaOffset(); 127 128 methods = compResult.getMethods(); 129 } 130 131 /** 132 * Ensure that all the frames passed into HotSpot are properly formatted with an empty or 133 * illegal slot following double word slots. 134 */ 135 private boolean validateFrames() { 136 for (Site site : sites) { 137 if (site instanceof Infopoint) { 138 Infopoint info = (Infopoint) site; 139 if (info.debugInfo != null) { 140 BytecodeFrame frame = info.debugInfo.frame(); 141 assert frame == null || frame.validateFormat(false); 142 } 143 } 144 } 145 return true; 146 } 147 148 static class SiteComparator implements Comparator<Site> { 149 150 public int compare(Site s1, Site s2) { 151 if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { 152 return s1 instanceof Mark ? -1 : 1; 153 } 154 return s1.pcOffset - s2.pcOffset; 155 } 156 } 157 158 private static Site[] getSortedSites(CompilationResult target) { 159 List<?>[] lists = new List<?>[]{target.getInfopoints(), target.getDataPatches(), target.getMarks()}; 160 int count = 0; 161 for (List<?> list : lists) { 162 count += list.size(); 163 } 164 Site[] result = new Site[count]; 165 int pos = 0; 166 for (List<?> list : lists) { 167 for (Object elem : list) { 168 result[pos++] = (Site) elem; 169 } 170 } 171 Arrays.sort(result, new SiteComparator()); 172 return result; 173 } 174}