Mercurial > hg > graal-jvmci-8
diff jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java @ 22672:1bbd4a7c274b
Rename jdk.internal.jvmci to jdk.vm.ci
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Thu, 08 Oct 2015 17:28:41 -0700 |
parents | jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCodeCacheProvider.java@456800cd1a17 |
children | ea58bbafd5b9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java Thu Oct 08 17:28:41 2015 -0700 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.vm.ci.hotspot; + +import static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.COMPRESSED_NULL; + +import java.lang.reflect.Field; + +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.CompilationRequest; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.code.CompilationResult.Call; +import jdk.vm.ci.code.CompilationResult.ConstantReference; +import jdk.vm.ci.code.CompilationResult.DataPatch; +import jdk.vm.ci.code.CompilationResult.Mark; +import jdk.vm.ci.code.DataSection; +import jdk.vm.ci.code.DataSection.Data; +import jdk.vm.ci.code.DataSection.DataBuilder; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.SerializableConstant; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.VMConstant; + +/** + * HotSpot implementation of {@link CodeCacheProvider}. + */ +public class HotSpotCodeCacheProvider implements CodeCacheProvider { + + protected final HotSpotJVMCIRuntimeProvider runtime; + public final HotSpotVMConfig config; + protected final TargetDescription target; + protected final RegisterConfig regConfig; + + public HotSpotCodeCacheProvider(HotSpotJVMCIRuntimeProvider runtime, HotSpotVMConfig config, TargetDescription target, RegisterConfig regConfig) { + this.runtime = runtime; + this.config = config; + this.target = target; + this.regConfig = regConfig; + } + + @Override + public String getMarkName(Mark mark) { + int markId = (int) mark.id; + Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); + for (Field f : fields) { + if (f.getName().startsWith("MARKID_")) { + f.setAccessible(true); + try { + if (f.getInt(runtime.getConfig()) == markId) { + return f.getName(); + } + } catch (Exception e) { + } + } + } + return CodeCacheProvider.super.getMarkName(mark); + } + + /** + * Decodes a call target to a mnemonic if possible. + */ + @Override + public String getTargetName(Call call) { + Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); + for (Field f : fields) { + if (f.getName().endsWith("Stub")) { + f.setAccessible(true); + try { + Object address = f.get(runtime.getConfig()); + if (address.equals(call.target)) { + return f.getName() + ":0x" + Long.toHexString((Long) address); + } + } catch (Exception e) { + } + } + } + return CodeCacheProvider.super.getTargetName(call); + } + + @Override + public RegisterConfig getRegisterConfig() { + return regConfig; + } + + @Override + public int getMinimumOutgoingSize() { + return runtime.getConfig().runtimeCallStackSize; + } + + private InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) { + ((HotSpotJVMCIRuntime) runtime).notifyInstall(this, installedCode, compResult); + return installedCode; + } + + public InstalledCode installCode(CompilationRequest compRequest, CompilationResult compResult, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { + HotSpotResolvedJavaMethod method = compRequest != null ? (HotSpotResolvedJavaMethod) compRequest.getMethod() : null; + InstalledCode resultInstalledCode; + if (installedCode == null) { + if (method == null) { + // Must be a stub + resultInstalledCode = new HotSpotRuntimeStub(compResult.getName()); + } else { + resultInstalledCode = new HotSpotNmethod(method, compResult.getName(), isDefault); + } + } else { + resultInstalledCode = installedCode; + } + HotSpotCompiledCode compiledCode; + if (method != null) { + final int id; + final long jvmciEnv; + if (compRequest instanceof HotSpotCompilationRequest) { + HotSpotCompilationRequest hsCompRequest = (HotSpotCompilationRequest) compRequest; + id = hsCompRequest.getId(); + jvmciEnv = hsCompRequest.getJvmciEnv(); + } else { + id = method.allocateCompileId(compRequest.getEntryBCI()); + jvmciEnv = 0L; + } + compiledCode = new HotSpotCompiledNmethod(method, compResult, id, jvmciEnv); + } else { + compiledCode = new HotSpotCompiledCode(compResult); + } + int result = runtime.getCompilerToVM().installCode(target, compiledCode, resultInstalledCode, log); + if (result != config.codeInstallResultOk) { + String resultDesc = config.getCodeInstallResultDescription(result); + if (compiledCode instanceof HotSpotCompiledNmethod) { + HotSpotCompiledNmethod compiledNmethod = (HotSpotCompiledNmethod) compiledCode; + String msg = compiledNmethod.getInstallationFailureMessage(); + if (msg != null) { + msg = String.format("Code installation failed: %s%n%s", resultDesc, msg); + } else { + msg = String.format("Code installation failed: %s", resultDesc); + } + if (result == config.codeInstallResultDependenciesInvalid) { + throw new AssertionError(resultDesc + " " + msg); + } + throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg); + } else { + throw new BailoutException("Error installing %s: %s", compResult.getName(), resultDesc); + } + } + return logOrDump(resultInstalledCode, compResult); + } + + public void invalidateInstalledCode(InstalledCode installedCode) { + runtime.getCompilerToVM().invalidateInstalledCode(installedCode); + } + + public boolean needsDataPatch(JavaConstant constant) { + return constant instanceof HotSpotMetaspaceConstant; + } + + private Data createSingleDataItem(Constant constant) { + int size; + DataBuilder builder; + if (constant instanceof VMConstant) { + VMConstant vmConstant = (VMConstant) constant; + boolean compressed; + if (constant instanceof HotSpotConstant) { + HotSpotConstant c = (HotSpotConstant) vmConstant; + compressed = c.isCompressed(); + } else { + throw new JVMCIError(String.valueOf(constant)); + } + + size = compressed ? 4 : target.wordSize; + if (size == 4) { + builder = (buffer, patch) -> { + patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); + buffer.putInt(0xDEADDEAD); + }; + } else { + assert size == 8; + builder = (buffer, patch) -> { + patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant))); + buffer.putLong(0xDEADDEADDEADDEADL); + }; + } + } else if (JavaConstant.isNull(constant)) { + boolean compressed = COMPRESSED_NULL.equals(constant); + size = compressed ? 4 : target.wordSize; + builder = DataBuilder.zero(size); + } else if (constant instanceof SerializableConstant) { + SerializableConstant s = (SerializableConstant) constant; + size = s.getSerializedSize(); + builder = DataBuilder.serializable(s); + } else { + throw new JVMCIError(String.valueOf(constant)); + } + + return new Data(size, size, builder); + } + + public Data createDataItem(Constant... constants) { + assert constants.length > 0; + if (constants.length == 1) { + return createSingleDataItem(constants[0]); + } else { + DataBuilder[] builders = new DataBuilder[constants.length]; + int size = 0; + int alignment = 1; + for (int i = 0; i < constants.length; i++) { + Data data = createSingleDataItem(constants[i]); + + assert size % data.getAlignment() == 0 : "invalid alignment in packed constants"; + alignment = DataSection.lcm(alignment, data.getAlignment()); + + builders[i] = data.getBuilder(); + size += data.getSize(); + } + DataBuilder ret = (buffer, patches) -> { + for (DataBuilder b : builders) { + b.emit(buffer, patches); + } + }; + return new Data(alignment, size, ret); + } + } + + @Override + public TargetDescription getTarget() { + return target; + } + + public String disassemble(InstalledCode code) { + if (code.isValid()) { + return runtime.getCompilerToVM().disassembleCodeBlob(code); + } + return null; + } + + public SpeculationLog createSpeculationLog() { + return new HotSpotSpeculationLog(); + } + + public long getMaxCallTargetOffset(long address) { + return runtime.getCompilerToVM().getMaxCallTargetOffset(address); + } + + public boolean shouldDebugNonSafepoints() { + return runtime.getCompilerToVM().shouldDebugNonSafepoints(); + } + + /** + * Notifies the VM of statistics for a completed compilation. + * + * @param id the identifier of the compilation + * @param method the method compiled + * @param osr specifies if the compilation was for on-stack-replacement + * @param processedBytecodes the number of bytecodes processed during the compilation, including + * the bytecodes of all inlined methods + * @param time the amount time spent compiling {@code method} + * @param timeUnitsPerSecond the granularity of the units for the {@code time} value + * @param installedCode the nmethod installed as a result of the compilation + */ + public void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode) { + runtime.getCompilerToVM().notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes, time, timeUnitsPerSecond, installedCode); + } + + /** + * Resets all compilation statistics. + */ + public void resetCompilationStatistics() { + runtime.getCompilerToVM().resetCompilationStatistics(); + } +}