blob: b1ccd16d14d29861f429767bbb75b13e1d3fc01b [file] [log] [blame]
/*
* 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.*;
import java.lang.reflect.*;
import jdk.vm.ci.code.*;
import jdk.vm.ci.code.CompilationResult.*;
import jdk.vm.ci.code.DataSection.*;
import jdk.vm.ci.common.*;
import jdk.vm.ci.meta.*;
/**
* 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;
}
public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
HotSpotJVMCIRuntime.runtime().notifyInstall(this, installedCode, compResult);
return installedCode;
}
private InstalledCode installCode(CompilationResult compResult, HotSpotCompiledNmethod compiledCode, InstalledCode installedCode, SpeculationLog log) {
int result = runtime.getCompilerToVM().installCode(target, compiledCode, installedCode, log);
if (result != config.codeInstallResultOk) {
String msg = compiledCode.getInstallationFailureMessage();
String resultDesc = config.getCodeInstallResultDescription(result);
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);
}
return logOrDump(installedCode, compResult);
}
public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv, boolean isDefault) {
if (compResult.getId() == -1) {
compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
}
HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault);
HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(method, compResult, jvmciEnv);
return installCode(compResult, compiledCode, installedCode, method.getSpeculationLog());
}
@Override
public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
if (compResult.getId() == -1) {
compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
}
InstalledCode installedCode = predefinedInstalledCode;
if (installedCode == null) {
HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
installedCode = code;
}
HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult);
return installCode(compResult, compiledCode, installedCode, log);
}
@Override
public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
return installMethod(hotspotMethod, compResult, 0L, true);
}
public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
if (compResult.getId() == -1) {
compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI()));
}
HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult);
CompilerToVM vm = runtime.getCompilerToVM();
int result = vm.installCode(target, compiled, code, null);
if (result != runtime.getConfig().codeInstallResultOk) {
return null;
}
return code;
}
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;
long raw;
if (constant instanceof HotSpotObjectConstant) {
HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant;
compressed = c.isCompressed();
raw = 0xDEADDEADDEADDEADL;
} else if (constant instanceof HotSpotMetaspaceConstant) {
HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant;
compressed = meta.isCompressed();
raw = meta.rawValue();
} else {
throw new JVMCIError(String.valueOf(constant));
}
size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind);
if (size == 4) {
builder = (buffer, patch) -> {
patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
buffer.putInt((int) raw);
};
} else {
assert size == 8;
builder = (buffer, patch) -> {
patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
buffer.putLong(raw);
};
}
} else if (JavaConstant.isNull(constant)) {
boolean compressed = COMPRESSED_NULL.equals(constant);
size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind);
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()) {
long codeBlob = code.getAddress();
return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
}
return null;
}
public SpeculationLog createSpeculationLog() {
return new HotSpotSpeculationLog();
}
}