/*
* Copyright (c) 2012, 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 com.oracle.max.vm.ext.t1x;
import static com.oracle.max.cri.intrinsics.IntrinsicIDs.*;
import static com.oracle.max.vm.ext.t1x.T1XOptions.*;
import static com.oracle.max.vm.ext.t1x.T1XTemplateTag.*;
import static com.sun.max.platform.Platform.*;
import static com.sun.max.vm.MaxineVM.*;
import static com.sun.max.vm.compiler.target.Safepoints.*;
import static com.sun.max.vm.intrinsics.MaxineIntrinsicIDs.*;
import static com.sun.max.vm.stack.VMFrameLayout.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import com.oracle.max.criutils.*;
import com.oracle.max.vm.ext.maxri.*;
import com.sun.cri.bytecode.*;
import com.sun.cri.ci.CiCallingConvention.Type;
import com.sun.cri.ci.*;
import com.sun.cri.ci.CiUtil.RefMapFormatter;
import com.sun.cri.ri.*;
import com.sun.max.annotate.*;
import com.sun.max.lang.*;
import com.sun.max.platform.*;
import com.sun.max.program.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.*;
import com.sun.max.vm.MaxineVM.Phase;
import com.sun.max.vm.actor.holder.*;
import com.sun.max.vm.actor.member.*;
import com.sun.max.vm.bytecode.*;
import com.sun.max.vm.classfile.*;
import com.sun.max.vm.classfile.constant.*;
import com.sun.max.vm.compiler.*;
import com.sun.max.vm.compiler.target.*;
import com.sun.max.vm.heap.debug.*;
import com.sun.max.vm.hosted.*;
import com.sun.max.vm.layout.*;
import com.sun.max.vm.runtime.*;
import com.sun.max.vm.stack.*;
import com.sun.max.vm.ti.*;
import com.sun.max.vm.type.*;
import com.sun.max.vm.verifier.*;
/**
* The template JIT compiler based on C1X.
*/
public class T1X implements RuntimeCompiler {
static {
ClassfileReader.bytecodeTemplateClasses.add(T1X_TEMPLATE.class);
ClassfileReader.bytecodeTemplateClasses.add(T1X_INTRINSIC_TEMPLATE.class);
}
public final T1XTemplate[] templates = new T1XTemplate[T1XTemplateTag.values().length];
public Map<RiMethod, T1XTemplate> intrinsicTemplates;
/**
* Class defining the template definitions, default is {@link T1XTemplateSource}.
*/
private Class<?> templateSource;
/**
* When using non-standard template definitions, this compiler provides the
* standard implementation for any non-overridden templates.
*/
@CONSTANT
public static T1X stdT1X;
/**
* This compiler is used when a method needs to be compiled to generate VMTI events.
*/
private T1X vmtiT1X;
/**
* Factory that creates the appropriate subclass of {@link T1XCompilation}.
*/
protected final T1XCompilationFactory t1XCompilationFactory;
@HOSTED_ONLY
private static class InitializationCompleteCallback implements JavaPrototype.InitializationCompleteCallback {
@Override
public void initializationComplete() {
stdT1X.vmtiT1X = (T1X) VMTI.handler().runtimeCompiler(stdT1X);
}
}
static {
JavaPrototype.registerInitializationCompleteCallback(new InitializationCompleteCallback());
}
@HOSTED_ONLY
public T1X() {
this(T1XTemplateSource.class, new T1XCompilationFactory());
stdT1X = this;
}
/**
* Creates a compiler in which some template definitions may be overridden.
* by calling {@link #setTemplateSource(Class)} before {@link #initialize}.
* @param templateSource class defining the modified template definitions
* @param factory for creating {@link T1XCompilation} instances
*/
@HOSTED_ONLY
public T1X(Class<?> templateSource, T1XCompilationFactory factory) {
this.templateSource = templateSource;
this.t1XCompilationFactory = factory;
}
private final ThreadLocal<T1XCompilation> compilation = new ThreadLocal<T1XCompilation>() {
@Override
protected T1XCompilation initialValue() {
return t1XCompilationFactory.newT1XCompilation(T1X.this);
}
};
@Override
public RuntimeCompiler.Nature nature() {
return RuntimeCompiler.Nature.BASELINE;
}
public TargetMethod compile(ClassMethodActor method, boolean isDeopt, boolean install, CiStatistics stats) {
T1X t1x = this;
if (!MaxineVM.isHosted() && useVMTITemplates(method)) {
// Use JVMTI templates to create code-related events.
t1x = vmtiT1X;
}
T1XCompilation c = t1x.compilation.get();
boolean reentrant = false;
if (c.method != null) {
// Re-entrant call to T1X - use a new compilation object that will be discarded
// once the compilation is done. This should be a very rare occurrence.
c = t1x.t1XCompilationFactory.newT1XCompilation(t1x);
reentrant = true;
if (VMOptions.verboseOption.verboseCompilation || PrintCompilation) {
Log.println("Created temporary compilation object for re-entrant T1X compilation");
}
}
long startTime = 0;
int index = T1XMetrics.CompiledMethods++;
if (PrintCompilation) {
TTY.print(String.format("T1X %4d %-70s %-45s | ", index, method.holder().name(), method.name()));
startTime = System.nanoTime();
}
TTY.Filter filter = PrintFilter == null ? null : new TTY.Filter(PrintFilter, method);
try {
T1XTargetMethod t1xMethod = c.compile(method, isDeopt, install);
T1XMetrics.BytecodesCompiled += t1xMethod.codeAttribute.code().length;
T1XMetrics.CodeBytesEmitted += t1xMethod.code().length;
if (stats != null) {
stats.bytecodeCount = t1xMethod.codeAttribute.code().length;
}
printMachineCode(c, t1xMethod, reentrant);
return t1xMethod;
} finally {
if (filter != null) {
filter.remove();
}
if (PrintCompilation) {
long time = (System.nanoTime() - startTime) / 100000;
TTY.println(String.format("%3d.%dms", time / 10, time % 10));
}
c.cleanup();
}
}
/**
* Checks whether to use the JVMTI templates.
* @param methodActor
*/
private boolean useVMTITemplates(ClassMethodActor classMethodActor) {
if (MaxineVM.isHosted()) {
return false;
}
return VMTI.handler().needsVMTICompilation(classMethodActor);
}
private static final int MIN_OPCODE_LINE_LENGTH = 100;
void printMachineCode(T1XCompilation c, T1XTargetMethod t1xMethod, boolean reentrant) {
if (!PrintCFGToFile || reentrant || c.method == null || TTY.isSuppressed()) {
return;
}
if (!isHosted() && !isRunning()) {
// Cannot write to file system at runtime until the VM is in the RUNNING phase
return;
}
ByteArrayOutputStream buf = new ByteArrayOutputStream();
CompilationPrinter cprinter = new CompilationPrinter(buf);
cprinter.printCompilation(c.method);
byte[] code = t1xMethod.code();
final Platform platform = Platform.platform();
HexCodeFile hcf = new HexCodeFile(code, t1xMethod.codeStart().toLong(), platform.isa.name(), platform.wordWidth().numberOfBits);
HexCodeFile.addAnnotations(hcf, c.codeAnnotations);
addOpcodeComments(hcf, t1xMethod);
addExceptionHandlersComment(t1xMethod, hcf);
addSafepointPositionComments(t1xMethod, hcf);
String label = CiUtil.format("T1X %f %R %H.%n(%P)", c.method);
cprinter.printMachineCode(HexCodeFileTool.toText(hcf), label);
String bytecodes = c.method.format("%f %R %H.%n(%P)") + String.format("%n%s", CodeAttributePrinter.toString(c.method.codeAttribute()));
cprinter.printBytecodes(bytecodes);
cprinter.flush();
OutputStream cout = CompilationPrinter.globalOut();
if (cout != null) {
synchronized (cout) {
try {
cout.write(buf.toByteArray());
} catch (IOException e) {
TTY.println("WARNING: Error writing CFGPrinter output for %s to disk: %s", c.method, e.getMessage());
}
}
}
}
private static void addSafepointPositionComments(T1XTargetMethod t1xMethod, HexCodeFile hcf) {
if (t1xMethod.safepoints().size() != 0) {
Safepoints safepoints = t1xMethod.safepoints();
Object[] directCallees = t1xMethod.directCallees();
JVMSFrameLayout frame = t1xMethod.frame;
RefMapFormatter slotFormatter = new RefMapFormatter(target().arch, target().spillSlotSize, frame.framePointerReg(), frame.frameReferenceMapOffset());
int dcIndex = 0;
for (int safepointIndex = 0; safepointIndex < safepoints.size(); ++safepointIndex) {
int pos = safepoints.posAt(safepointIndex);
int causePos = safepoints.causePosAt(safepointIndex);
CiDebugInfo info = t1xMethod.debugInfoAt(safepointIndex, null);
hcf.addComment(pos, CiUtil.append(new StringBuilder(100), info, slotFormatter).toString());
String callComment = null;
if (safepoints.isSetAt(DIRECT_CALL, safepointIndex)) {
Object callee = directCallees[dcIndex];
callComment = String.valueOf(callee);
dcIndex++;
} else if (safepoints.isSetAt(TEMPLATE_CALL, safepointIndex)) {
callComment = "<template_call>";
} else if (safepoints.isSetAt(INDIRECT_CALL, safepointIndex)) {
CiCodePos codePos = info.codePos;
if (codePos != null) {
RiMethod callee = t1xMethod.codeAttribute.calleeAt(codePos.bci);
if (callee != null) {
callComment = String.valueOf(callee);
}
}
}
if (callComment != null) {
hcf.addOperandComment(causePos, callComment);
}
}
}
}
private static void addExceptionHandlersComment(T1XTargetMethod t1xMethod, HexCodeFile hcf) {
if (t1xMethod.handlers.length != 0) {
String nl = HexCodeFile.NEW_LINE;
StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl);
for (CiExceptionHandler e : t1xMethod.handlers) {
if (e.catchTypeCPI == T1XTargetMethod.SYNC_METHOD_CATCH_TYPE_CPI) {
buf.append(" <any> @ [").
append(e.startBCI()).
append(" .. ").
append(e.endBCI()).
append(") -> ").
append(e.handlerBCI()).
append(nl);
} else {
buf.append(" ").
append(e.catchType == null ? "<any>" : e.catchType).append(" @ [").
append(t1xMethod.posForBci(e.startBCI())).append(" .. ").
append(t1xMethod.posForBci(e.endBCI())).append(") -> ").
append(t1xMethod.posForBci(e.handlerBCI())).append(nl);
}
}
hcf.addComment(0, buf.toString());
}
}
private static void addOpcodeComments(HexCodeFile hcf, T1XTargetMethod t1xMethod) {
int[] bciToPos = t1xMethod.bciToPos;
BytecodeStream s = new BytecodeStream(t1xMethod.codeAttribute.code());
for (int bci = 0; bci < bciToPos.length; ++bci) {
int pos = bciToPos[bci];
if (pos != 0) {
StringBuilder sb = new StringBuilder(MIN_OPCODE_LINE_LENGTH);
if (bci != bciToPos.length - 1) {
sb.append("-------------------- ");
s.setBCI(bci);
sb.append(bci).append(": ").append(Bytecodes.nameOf(s.currentBC()));
for (int i = bci + 1; i < s.nextBCI(); ++i) {
sb.append(' ').append(s.readUByte(i));
}
sb.append(" --------------------");
} else {
sb.append("-------------------- <epilogue> --------------------");
}
while (sb.length() < MIN_OPCODE_LINE_LENGTH) {
sb.append('-');
}
hcf.addComment(pos, sb.toString());
}
}
}
public void initialize(Phase phase) {
if (isHosted() && phase == Phase.HOSTED_COMPILING) {
RuntimeCompiler compiler = createBootCompiler();
createTemplates(compiler, templateSource, true, templates);
if (stdT1X != this) {
intrinsicTemplates = stdT1X.intrinsicTemplates;
} else {
intrinsicTemplates = createIntrinsicTemplates(compiler);
}
if (vmtiT1X != null) {
vmtiT1X.initialize(phase);
}
}
if (phase == Phase.TERMINATING) {
if (T1XOptions.PrintMetrics) {
T1XMetrics.print();
}
if (T1XOptions.PrintTimers) {
T1XTimer.print();
}
}
}
@HOSTED_ONLY
protected RuntimeCompiler createBootCompiler() {
// Create a boot compiler to compile the templates
RuntimeCompiler compiler = vm().compilationBroker.optimizingCompiler;
if (compiler == null) {
compiler = CompilationBroker.instantiateCompiler(RuntimeCompiler.optimizingCompilerOption.getValue());
compiler.initialize(Phase.HOSTED_COMPILING);
}
return compiler;
}
/**
* Create a set of templates from the methods annotated with {@link T1X_TEMPLATE} in the given class.
* Undefined templates are filled from the templates associated with {@link #stdT1X}. The latter
* maybe null iff {@code checkComplete} is {@code false}, in which case the result will only
* contain the templates defined in the class.
* @param templateSourceClass class containing template methods
* @param checkComplete if {@code true} check the array for completeness.
* @param templates an existing instance that will be incrementally updated.
* Value may be null, in which case a new array will be created.
*
* @return the templates array, either as passed in or created.
*/
@HOSTED_ONLY
public T1XTemplate[] createTemplates(RuntimeCompiler compiler, Class<?> templateSourceClass, boolean checkComplete, T1XTemplate[] templates) {
Trace.begin(1, "creating T1X templates from " + templateSourceClass.getName());
if (templates == null) {
templates = new T1XTemplate[T1XTemplateTag.values().length];
}
long startTime = System.currentTimeMillis();
ClassActor.fromJava(T1XRuntime.class);
ClassVerifier verifier = new TypeCheckingVerifier(ClassActor.fromJava(templateSourceClass));
final Method[] templateMethods = templateSourceClass.getDeclaredMethods();
int codeSize = 0;
for (Method method : templateMethods) {
if (Platform.platform().isAcceptedBy(method.getAnnotation(PLATFORM.class))) {
T1X_TEMPLATE anno = method.getAnnotation(T1X_TEMPLATE.class);
if (anno != null) {
T1XTemplateTag tag = anno.value();
ClassMethodActor templateSource = ClassMethodActor.fromJava(method);
try {
templateSource.verify(verifier);
} catch (VerifyError e) {
FatalError.unexpected("Error verifying " + templateSource, e);
}
MaxTargetMethod templateCode = compileTemplate(compiler, templateSource);
codeSize += templateCode.codeLength();
T1XTemplate template = templates[tag.ordinal()];
if (template != null) {
FatalError.unexpected("Template tag " + tag + " is already bound to " + template.method + ", cannot rebind to " + templateSource);
}
templates[tag.ordinal()] = new T1XTemplate(templateCode, tag, templateSource);
}
}
}
if (checkComplete) {
// ensure everything is implemented
for (int i = 0; i < T1XTemplateTag.values().length; i++) {
T1XTemplateTag tag = T1XTemplateTag.values()[i];
if (templates[i] == null && !isUnimplemented(tag)) {
if (stdT1X == this || (stdT1X.templates[i] == null && !stdT1X.isUnimplemented(tag))) {
FatalError.unexpected("Template tag " + tag + " is not implemented");
} else {
templates[i] = stdT1X.templates[i];
}
}
}
}
Trace.end(1, "creating T1X templates from " + templateSourceClass.getName() + " [templates code size: " + codeSize + "]", startTime);
return templates;
}
/**
* These templates are not used by T1X, but may be used by the variants (e.g., VMA). Since enums cannot be
* subclassed, it is convenient to keep them in {@link T1XTemplateTag} and just avoid checking
* that they are implemented.
*/
protected static final EnumSet UNIMPLEMENTED_TEMPLATES = EnumSet.of(NOP, ACONST_NULL, ICONST, LCONST, FCONST, DCONST, BIPUSH, SIPUSH, LDC$int, LDC$long, LDC$float, LDC$double,
LDC$reference$resolved, ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP,
IINC, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, IFNULL, IFNONNULL, GOTO, GOTO_W,
INVOKESPECIAL$void$resolved, INVOKESPECIAL$float$resolved, INVOKESPECIAL$long$resolved, INVOKESPECIAL$double$resolved, INVOKESPECIAL$reference$resolved,
INVOKESPECIAL$word$resolved, INVOKESTATIC$void$init, INVOKESTATIC$float$init, INVOKESTATIC$long$init, INVOKESTATIC$double$init, INVOKESTATIC$reference$init,
INVOKESTATIC$word$init, INVOKEVIRTUAL$adviseafter, INVOKEINTERFACE$adviseafter, INVOKESPECIAL$adviseafter, INVOKESTATIC$adviseafter,
BREAKPOINT);
protected boolean isUnimplemented(T1XTemplateTag tag) {
return UNIMPLEMENTED_TEMPLATES.contains(tag);
}
private MaxTargetMethod compileTemplate(RuntimeCompiler bootCompiler, ClassMethodActor templateSource) {
FatalError.check(templateSource.isTemplate(), "Method with " + T1X_TEMPLATE.class.getSimpleName() + " annotation should be a template: " + templateSource);
FatalError.check(!hasStackParameters(templateSource), "Template must not have *any* stack parameters: " + templateSource);
FatalError.check(templateSource.resultKind().stackKind == templateSource.resultKind(), "Template return type must be a stack kind: " + templateSource);
for (int i = 0; i < templateSource.getParameterKinds().length; i++) {
Kind k = templateSource.getParameterKinds()[i];
FatalError.check(k.stackKind == k, "Template parameter " + i + " is not a stack kind: " + templateSource);
}
final MaxTargetMethod templateCode = (MaxTargetMethod) bootCompiler.compile(templateSource, false, true, null);
FatalError.check(templateCode.scalarLiterals() == null, "Template must not have *any* scalar literals: " + templateCode);
int frameSlots = Ints.roundUp(templateCode.frameSize(), STACK_SLOT_SIZE) / STACK_SLOT_SIZE;
if (frameSlots > T1XTargetMethod.templateSlots) {
T1XTargetMethod.templateSlots = frameSlots;
}
return templateCode;
}
@HOSTED_ONLY
private static final Set<String> templateIntriniscIDs = new HashSet<String>(Arrays.asList(
UCMP_AT, UCMP_AE, UCMP_BT, UCMP_BE,
UDIV, UREM,
LSB, MSB,
PREAD_OFF, PREAD_IDX, PWRITE_OFF, PWRITE_IDX, PCMPSWP,
HERE,
PAUSE
));
/**
* List of intrinsic that T1X cannot handle, i.e., methods that call these intrinsics lead to a bailout.
*/
public static final Set<String> unsafeIntrinsicIDs = new HashSet<String>(Arrays.asList(
READREG, WRITEREG, IFLATCHBITREAD,
SAFEPOINT_POLL, HERE, INFO, BREAKPOINT_TRAP,
ALLOCA
));
@HOSTED_ONLY
private static final Class[] templateIntrinsicClasses = {
com.sun.max.unsafe.Pointer.class,
com.oracle.max.cri.intrinsics.UnsignedMath.class,
com.sun.max.vm.intrinsics.Infopoints.class,
com.sun.max.vm.Intrinsics.class
};
@HOSTED_ONLY
public static List<ClassMethodActor> intrinsicTemplateMethods() {
// Process all classes of the statically defined list above, then check that the list does not miss any classes.
// The rational behind that: The list of classes processed must be stable, otherwise the code generator
// complains that the generated wrapper source code has changed, which requires a recompile cycle.
ArrayList<ClassMethodActor> result = new ArrayList<ClassMethodActor>();
for (Class clazz : templateIntrinsicClasses) {
for (MethodActor methodActor : ClassActor.fromJava(clazz).getLocalMethodActors()) {
if (T1X.templateIntriniscIDs.contains(methodActor.intrinsic())) {
result.add((ClassMethodActor) methodActor);
}
}
}
for (ClassActor classActor : ClassRegistry.allBootImageClasses()) {
for (MethodActor methodActor : classActor.getLocalMethodActors()) {
if (T1X.templateIntriniscIDs.contains(methodActor.intrinsic()) && !result.contains(methodActor)) {
System.out.printf("%nClass with intrinisc methods found that should be in templateIntrinsicClasses: class %s, method %s%n%n",
classActor, methodActor);
System.exit(1);
}
}
}
return result;
}
@HOSTED_ONLY
public Map<RiMethod, T1XTemplate> createIntrinsicTemplates(RuntimeCompiler bootCompiler) {
Map<RiMethod, T1XTemplate> result = new HashMap<RiMethod, T1XTemplate>();
Trace.begin(1, "creating T1X templates for intrinsics");
long startTime = System.currentTimeMillis();
ClassActor source = ClassActor.fromJava(T1XIntrinsicTemplateSource.class);
for (ClassMethodActor intrinsicMethod : intrinsicTemplateMethods()) {
ClassMethodActor templateSource = source.findLocalStaticMethodActor(SymbolTable.makeSymbol(T1XIntrinsicTemplateGenerator.templateInvokerName(intrinsicMethod)));
MaxTargetMethod templateCode = compileTemplate(bootCompiler, templateSource);
result.put(intrinsicMethod, new T1XTemplate(templateCode, null, templateSource));
}
Trace.end(1, "creating T1X templates for intrinsics", startTime);
return result;
}
static {
JavaPrototype.registerGeneratedCodeCheckerCallback(new GeneratedCodeCheckerCallback());
}
@HOSTED_ONLY
private static class GeneratedCodeCheckerCallback implements JavaPrototype.GeneratedCodeCheckerCallback {
@Override
public void checkGeneratedCode() {
try {
if (T1XTemplateGenerator.generate(true, T1XTemplateSource.class)) {
String thisFile = T1XTemplateSource.class.getSimpleName();
System.out.printf("%nThe generated content in %s " +
" is out of sync. Edit %s instead to make the desired changes and then run 'max t1xgen', " +
"recompile %s (or refresh it in your IDE) and restart the bootstrapping process.%n%n",
thisFile, T1XTemplateGenerator.class.getSimpleName(), thisFile);
System.exit(1);
}
} catch (Exception e) {
FatalError.unexpected("Error while generating source for " + T1XTemplateSource.class, e);
}
try {
boolean modified = T1XIntrinsicTemplateGenerator.generate(T1XIntrinsicTemplateSource.class);
if (modified) {
System.out.printf("%nThe generated content in %s was regenerated. Recompile (or refresh it in your IDE) and restart the bootstrapping process.%n%n", T1XIntrinsicTemplateSource.class.getSimpleName());
System.exit(1);
}
} catch (Exception e) {
FatalError.unexpected("Error while generating source for " + T1XIntrinsicTemplateSource.class, e);
}
}
}
@HOSTED_ONLY
private static boolean hasStackParameters(ClassMethodActor classMethodActor) {
for (CiValue arg : vm().registerConfigs.standard.getCallingConvention(Type.JavaCall, CiUtil.signatureToKinds(classMethodActor), target(), false).locations) {
if (!arg.isRegister()) {
return true;
}
}
return false;
}
@Override
public String toString() {
return getClass().getSimpleName();
}
@Override
public boolean matches(String compilerName) {
return compilerName.equals("T1X");
}
/**
* Gets the displacement from the start of the code to the address of some data co-located with the code.
*
* @param objectLiteralsLength the total number of object literals associated with the code
* @param scalarLiteralsLength the size of the serialized scalar literals associated with the code
* @param dataIndex the index into the object literals array or the serialized scalar literals of the data
* @param isObject specifies if the data is an object
*/
public static int dispFromCodeStart(int objectLiteralsLength, int scalarLiteralsLength, int dataIndex, boolean isObject) {
int distance = Layout.byteArrayLayout().headerSize();
if (DebugHeap.isTagging()) {
distance += Word.size();
}
if (isObject) {
distance += (objectLiteralsLength - dataIndex) * Word.size();
} else {
distance += objectLiteralsLength * Word.size();
distance += Layout.referenceArrayLayout().headerSize();
if (DebugHeap.isTagging()) {
distance += Word.size();
}
distance += scalarLiteralsLength - dataIndex;
}
return -distance;
}
/**
* Determines if the target ISA is AMD64.
*/
@FOLD
public static boolean isAMD64() {
return platform().isa == ISA.AMD64;
}
/**
* Called to denote some functionality is not yet implemented for the target ISA.
*/
@NEVER_INLINE
public static FatalError unimplISA() {
throw FatalError.unexpected("Unimplemented platform: " + platform().isa);
}
}