1 /* 2 * Copyright (c) 2013, 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 static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.*; 26 27 import java.lang.reflect.*; 28 29 import jdk.vm.ci.code.*; 30 import jdk.vm.ci.code.CompilationResult.*; 31 import jdk.vm.ci.code.DataSection.*; 32 import jdk.vm.ci.common.*; 33 import jdk.vm.ci.meta.*; 34 35 /** 36 * HotSpot implementation of {@link CodeCacheProvider}. 37 */ 38 public class HotSpotCodeCacheProvider implements CodeCacheProvider { 39 40 protected final HotSpotJVMCIRuntimeProvider runtime; 41 public final HotSpotVMConfig config; 42 protected final TargetDescription target; 43 protected final RegisterConfig regConfig; 44 45 public HotSpotCodeCacheProvider(HotSpotJVMCIRuntimeProvider runtime, HotSpotVMConfig config, TargetDescription target, RegisterConfig regConfig) { 46 this.runtime = runtime; 47 this.config = config; 48 this.target = target; 49 this.regConfig = regConfig; 50 } 51 52 @Override 53 public String getMarkName(Mark mark) { 54 int markId = (int) mark.id; 55 Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); 56 for (Field f : fields) { 57 if (f.getName().startsWith("MARKID_")) { 58 f.setAccessible(true); 59 try { 60 if (f.getInt(runtime.getConfig()) == markId) { 61 return f.getName(); 62 } 63 } catch (Exception e) { 64 } 65 } 66 } 67 return CodeCacheProvider.super.getMarkName(mark); 68 } 69 70 /** 71 * Decodes a call target to a mnemonic if possible. 72 */ 73 @Override 74 public String getTargetName(Call call) { 75 Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); 76 for (Field f : fields) { 77 if (f.getName().endsWith("Stub")) { 78 f.setAccessible(true); 79 try { 80 Object address = f.get(runtime.getConfig()); 81 if (address.equals(call.target)) { 82 return f.getName() + ":0x" + Long.toHexString((Long) address); 83 } 84 } catch (Exception e) { 85 } 86 } 87 } 88 return CodeCacheProvider.super.getTargetName(call); 89 } 90 91 @Override 92 public RegisterConfig getRegisterConfig() { 93 return regConfig; 94 } 95 96 @Override 97 public int getMinimumOutgoingSize() { 98 return runtime.getConfig().runtimeCallStackSize; 99 } 100 101 public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) { 102 HotSpotJVMCIRuntime.runtime().notifyInstall(this, installedCode, compResult); 103 return installedCode; 104 } 105 106 private InstalledCode installCode(CompilationResult compResult, HotSpotCompiledNmethod compiledCode, InstalledCode installedCode, SpeculationLog log) { 107 int result = runtime.getCompilerToVM().installCode(target, compiledCode, installedCode, log); 108 if (result != config.codeInstallResultOk) { 109 String msg = compiledCode.getInstallationFailureMessage(); 110 String resultDesc = config.getCodeInstallResultDescription(result); 111 if (msg != null) { 112 msg = String.format("Code installation failed: %s%n%s", resultDesc, msg); 113 } else { 114 msg = String.format("Code installation failed: %s", resultDesc); 115 } 116 if (result == config.codeInstallResultDependenciesInvalid) { 117 throw new AssertionError(resultDesc + " " + msg); 118 } 119 throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg); 120 } 121 return logOrDump(installedCode, compResult); 122 } 123 124 public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv, boolean isDefault) { 125 if (compResult.getId() == -1) { 126 compResult.setId(method.allocateCompileId(compResult.getEntryBCI())); 127 } 128 HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault); 129 HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(method, compResult, jvmciEnv); 130 return installCode(compResult, compiledCode, installedCode, method.getSpeculationLog()); 131 } 132 133 @Override 134 public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) { 135 HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; 136 if (compResult.getId() == -1) { 137 compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI())); 138 } 139 InstalledCode installedCode = predefinedInstalledCode; 140 if (installedCode == null) { 141 HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false); 142 installedCode = code; 143 } 144 HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult); 145 return installCode(compResult, compiledCode, installedCode, log); 146 } 147 148 @Override 149 public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) { 150 HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; 151 return installMethod(hotspotMethod, compResult, 0L, true); 152 } 153 154 public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) { 155 HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method; 156 if (compResult.getId() == -1) { 157 compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI())); 158 } 159 HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true); 160 HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult); 161 CompilerToVM vm = runtime.getCompilerToVM(); 162 int result = vm.installCode(target, compiled, code, null); 163 if (result != runtime.getConfig().codeInstallResultOk) { 164 return null; 165 } 166 return code; 167 } 168 169 public boolean needsDataPatch(JavaConstant constant) { 170 return constant instanceof HotSpotMetaspaceConstant; 171 } 172 173 private Data createSingleDataItem(Constant constant) { 174 int size; 175 DataBuilder builder; 176 if (constant instanceof VMConstant) { 177 VMConstant vmConstant = (VMConstant) constant; 178 boolean compressed; 179 long raw; 180 if (constant instanceof HotSpotObjectConstant) { 181 HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant; 182 compressed = c.isCompressed(); 183 raw = 0xDEADDEADDEADDEADL; 184 } else if (constant instanceof HotSpotMetaspaceConstant) { 185 HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant; 186 compressed = meta.isCompressed(); 187 raw = meta.rawValue(); 188 } else { 189 throw new JVMCIError(String.valueOf(constant)); 190 } 191 192 size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind); 193 if (size == 4) { 194 builder = (buffer, patch) -> { 195 patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); 196 buffer.putInt((int) raw); 197 }; 198 } else { 199 assert size == 8; 200 builder = (buffer, patch) -> { 201 patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); 202 buffer.putLong(raw); 203 }; 204 } 205 } else if (JavaConstant.isNull(constant)) { 206 boolean compressed = COMPRESSED_NULL.equals(constant); 207 size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind); 208 builder = DataBuilder.zero(size); 209 } else if (constant instanceof SerializableConstant) { 210 SerializableConstant s = (SerializableConstant) constant; 211 size = s.getSerializedSize(); 212 builder = DataBuilder.serializable(s); 213 } else { 214 throw new JVMCIError(String.valueOf(constant)); 215 } 216 217 return new Data(size, size, builder); 218 } 219 220 public Data createDataItem(Constant... constants) { 221 assert constants.length > 0; 222 if (constants.length == 1) { 223 return createSingleDataItem(constants[0]); 224 } else { 225 DataBuilder[] builders = new DataBuilder[constants.length]; 226 int size = 0; 227 int alignment = 1; 228 for (int i = 0; i < constants.length; i++) { 229 Data data = createSingleDataItem(constants[i]); 230 231 assert size % data.getAlignment() == 0 : "invalid alignment in packed constants"; 232 alignment = DataSection.lcm(alignment, data.getAlignment()); 233 234 builders[i] = data.getBuilder(); 235 size += data.getSize(); 236 } 237 DataBuilder ret = (buffer, patches) -> { 238 for (DataBuilder b : builders) { 239 b.emit(buffer, patches); 240 } 241 }; 242 return new Data(alignment, size, ret); 243 } 244 } 245 246 @Override 247 public TargetDescription getTarget() { 248 return target; 249 } 250 251 public String disassemble(InstalledCode code) { 252 if (code.isValid()) { 253 long codeBlob = code.getAddress(); 254 return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob); 255 } 256 return null; 257 } 258 259 public SpeculationLog createSpeculationLog() { 260 return new HotSpotSpeculationLog(); 261 } 262 }