001/*
002 * Copyright (c) 2013, 2015, 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 static jdk.internal.jvmci.hotspot.HotSpotCompressedNullConstant.*;
026
027import java.lang.reflect.*;
028
029import jdk.internal.jvmci.code.*;
030import jdk.internal.jvmci.code.CompilationResult.*;
031import jdk.internal.jvmci.code.DataSection.*;
032import jdk.internal.jvmci.common.*;
033import jdk.internal.jvmci.meta.*;
034
035/**
036 * HotSpot implementation of {@link CodeCacheProvider}.
037 */
038public class HotSpotCodeCacheProvider implements CodeCacheProvider {
039
040    protected final HotSpotJVMCIRuntimeProvider runtime;
041    public final HotSpotVMConfig config;
042    protected final TargetDescription target;
043    protected final RegisterConfig regConfig;
044
045    public HotSpotCodeCacheProvider(HotSpotJVMCIRuntimeProvider runtime, HotSpotVMConfig config, TargetDescription target, RegisterConfig regConfig) {
046        this.runtime = runtime;
047        this.config = config;
048        this.target = target;
049        this.regConfig = regConfig;
050    }
051
052    @Override
053    public String getMarkName(Mark mark) {
054        int markId = (int) mark.id;
055        Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
056        for (Field f : fields) {
057            if (f.getName().startsWith("MARKID_")) {
058                f.setAccessible(true);
059                try {
060                    if (f.getInt(runtime.getConfig()) == markId) {
061                        return f.getName();
062                    }
063                } catch (Exception e) {
064                }
065            }
066        }
067        return CodeCacheProvider.super.getMarkName(mark);
068    }
069
070    /**
071     * Decodes a call target to a mnemonic if possible.
072     */
073    @Override
074    public String getTargetName(Call call) {
075        Field[] fields = runtime.getConfig().getClass().getDeclaredFields();
076        for (Field f : fields) {
077            if (f.getName().endsWith("Stub")) {
078                f.setAccessible(true);
079                try {
080                    Object address = f.get(runtime.getConfig());
081                    if (address.equals(call.target)) {
082                        return f.getName() + ":0x" + Long.toHexString((Long) address);
083                    }
084                } catch (Exception e) {
085                }
086            }
087        }
088        return CodeCacheProvider.super.getTargetName(call);
089    }
090
091    @Override
092    public RegisterConfig getRegisterConfig() {
093        return regConfig;
094    }
095
096    @Override
097    public int getMinimumOutgoingSize() {
098        return runtime.getConfig().runtimeCallStackSize;
099    }
100
101    public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
102        HotSpotJVMCIRuntime.runtime().notifyInstall(this, installedCode, compResult);
103        return installedCode;
104    }
105
106    public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv, boolean isDefault) {
107        if (compResult.getId() == -1) {
108            compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
109        }
110        HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault);
111        runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, compResult, jvmciEnv), installedCode, method.getSpeculationLog());
112        return logOrDump(installedCode, compResult);
113    }
114
115    @Override
116    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
117        HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
118        if (compResult.getId() == -1) {
119            compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
120        }
121        InstalledCode installedCode = predefinedInstalledCode;
122        if (installedCode == null) {
123            HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
124            installedCode = code;
125        }
126        HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult);
127        int result = runtime.getCompilerToVM().installCode(compiledCode, installedCode, log);
128        if (result != config.codeInstallResultOk) {
129            String msg = compiledCode.getInstallationFailureMessage();
130            String resultDesc = config.getCodeInstallResultDescription(result);
131            if (msg != null) {
132                msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
133            } else {
134                msg = String.format("Code installation failed: %s", resultDesc);
135            }
136            if (result == config.codeInstallResultDependenciesInvalid) {
137                throw new AssertionError(resultDesc + " " + msg);
138            }
139            throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg);
140        }
141        return logOrDump(installedCode, compResult);
142    }
143
144    @Override
145    public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
146        HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
147        return installMethod(hotspotMethod, compResult, 0L, true);
148    }
149
150    public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
151        HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
152        if (compResult.getId() == -1) {
153            compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI()));
154        }
155        HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
156        HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult);
157        CompilerToVM vm = runtime.getCompilerToVM();
158        int result = vm.installCode(compiled, code, null);
159        if (result != runtime.getConfig().codeInstallResultOk) {
160            return null;
161        }
162        return code;
163    }
164
165    public boolean needsDataPatch(JavaConstant constant) {
166        return constant instanceof HotSpotMetaspaceConstant;
167    }
168
169    public Data createDataItem(Constant constant) {
170        int size;
171        DataBuilder builder;
172        if (constant instanceof VMConstant) {
173            VMConstant vmConstant = (VMConstant) constant;
174            boolean compressed;
175            long raw;
176            if (constant instanceof HotSpotObjectConstant) {
177                HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant;
178                compressed = c.isCompressed();
179                raw = 0xDEADDEADDEADDEADL;
180            } else if (constant instanceof HotSpotMetaspaceConstant) {
181                HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant;
182                compressed = meta.isCompressed();
183                raw = meta.rawValue();
184            } else {
185                throw new JVMCIError(String.valueOf(constant));
186            }
187
188            size = target.getSizeInBytes(compressed ? Kind.Int : target.wordKind);
189            if (size == 4) {
190                builder = (buffer, patch) -> {
191                    patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
192                    buffer.putInt((int) raw);
193                };
194            } else {
195                assert size == 8;
196                builder = (buffer, patch) -> {
197                    patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
198                    buffer.putLong(raw);
199                };
200            }
201        } else if (JavaConstant.isNull(constant)) {
202            boolean compressed = COMPRESSED_NULL.equals(constant);
203            size = target.getSizeInBytes(compressed ? Kind.Int : target.wordKind);
204            builder = DataBuilder.zero(size);
205        } else if (constant instanceof SerializableConstant) {
206            SerializableConstant s = (SerializableConstant) constant;
207            size = s.getSerializedSize();
208            builder = DataBuilder.serializable(s);
209        } else {
210            throw new JVMCIError(String.valueOf(constant));
211        }
212
213        return new Data(size, size, builder);
214    }
215
216    @Override
217    public TargetDescription getTarget() {
218        return target;
219    }
220
221    public String disassemble(InstalledCode code) {
222        if (code.isValid()) {
223            long codeBlob = code.getAddress();
224            return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
225        }
226        return null;
227    }
228
229    public SpeculationLog createSpeculationLog() {
230        return new HotSpotSpeculationLog();
231    }
232}