All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jdk.graal.compiler.hotspot.amd64.AMD64HotSpotBackend Maven / Gradle / Ivy

There is a newer version: 24.1.1
Show newest version
/*
 * Copyright (c) 2012, 2024, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.graal.compiler.hotspot.amd64;

import static jdk.graal.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
import static jdk.vm.ci.amd64.AMD64.r10;
import static jdk.vm.ci.amd64.AMD64.rax;
import static jdk.vm.ci.amd64.AMD64.rbp;
import static jdk.vm.ci.amd64.AMD64.rsp;
import static jdk.vm.ci.code.ValueUtil.asRegister;

import jdk.graal.compiler.asm.BranchTargetOutOfBoundsException;
import jdk.graal.compiler.asm.Label;
import jdk.graal.compiler.asm.amd64.AMD64Address;
import jdk.graal.compiler.asm.amd64.AMD64Assembler;
import jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler;
import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
import jdk.graal.compiler.code.CompilationResult;
import jdk.graal.compiler.core.amd64.AMD64NodeMatchRules;
import jdk.graal.compiler.core.common.GraalOptions;
import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.core.common.alloc.RegisterAllocationConfig;
import jdk.graal.compiler.core.common.spi.ForeignCallLinkage;
import jdk.graal.compiler.core.gen.LIRGenerationProvider;
import jdk.graal.compiler.debug.DebugContext;
import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig;
import jdk.graal.compiler.hotspot.HotSpotDataBuilder;
import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider;
import jdk.graal.compiler.hotspot.HotSpotHostBackend;
import jdk.graal.compiler.hotspot.HotSpotLIRGenerationResult;
import jdk.graal.compiler.hotspot.HotSpotMarkId;
import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProvider;
import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
import jdk.graal.compiler.hotspot.stubs.Stub;
import jdk.graal.compiler.lir.LIR;
import jdk.graal.compiler.lir.amd64.AMD64Call;
import jdk.graal.compiler.lir.amd64.AMD64FrameMap;
import jdk.graal.compiler.lir.asm.CompilationResultBuilder;
import jdk.graal.compiler.lir.asm.CompilationResultBuilderFactory;
import jdk.graal.compiler.lir.asm.DataBuilder;
import jdk.graal.compiler.lir.asm.EntryPointDecorator;
import jdk.graal.compiler.lir.asm.FrameContext;
import jdk.graal.compiler.lir.framemap.FrameMap;
import jdk.graal.compiler.lir.framemap.FrameMapBuilder;
import jdk.graal.compiler.lir.gen.LIRGenerationResult;
import jdk.graal.compiler.lir.gen.LIRGeneratorTool;
import jdk.graal.compiler.nodes.StructuredGraph;
import jdk.graal.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.graal.compiler.options.OptionValues;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaMethod;

/**
 * HotSpot AMD64 specific backend.
 */
public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {

    public AMD64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
        super(config, runtime, providers);
    }

    @Override
    protected FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig, Stub stub) {
        RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
        AMD64FrameMap frameMap = new AMD64HotSpotFrameMap(getCodeCache(), registerConfigNonNull, this, config.preserveFramePointer(stub != null));
        return new AMD64HotSpotFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
    }

    @Override
    public LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes) {
        return new AMD64HotSpotLIRGenerator(getProviders(), config, lirGenRes);
    }

    @Override
    public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
        return new AMD64HotSpotNodeLIRBuilder(graph, lirGen, new AMD64NodeMatchRules(lirGen));
    }

    @Override
    protected void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset) {
        AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm;
        int pos = asm.position();
        asm.movl(new AMD64Address(rsp, -bangOffset), AMD64.rax);
        assert asm.position() - pos >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE : asm.position() + "-" + pos;
    }

    /**
     * The size of the instruction used to patch the verified entry point of an nmethod when the
     * nmethod is made non-entrant or a zombie (e.g. during deopt or class unloading). The first
     * instruction emitted at an nmethod's verified entry point must be at least this length to
     * ensure mt-safe patching.
     */
    public static final int PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE = 5;

    /**
     * Emits code at the verified entry point and return point(s) of a method.
     */
    public class HotSpotFrameContext implements FrameContext {

        final boolean isStub;

        HotSpotFrameContext(boolean isStub) {
            this.isStub = isStub;
        }

        @Override
        public void enter(CompilationResultBuilder crb) {
            AMD64FrameMap frameMap = (AMD64FrameMap) crb.frameMap;
            int frameSize = frameMap.frameSize();
            AMD64HotSpotMacroAssembler asm = (AMD64HotSpotMacroAssembler) crb.asm;

            int verifiedEntryPointOffset = asm.position();
            if (!isStub) {
                emitStackOverflowCheck(crb);
                // assert asm.position() - verifiedEntryPointOffset >=
                // PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE;
            }
            if (frameMap.preserveFramePointer()) {
                // Stack-walking friendly instructions
                asm.push(rbp);
                asm.movq(rbp, rsp);
            }
            if (!isStub && asm.position() == verifiedEntryPointOffset) {
                asm.subqWide(rsp, frameSize);
                assert asm.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE : asm.position() + "-" + verifiedEntryPointOffset;
            } else {
                asm.decrementq(rsp, frameSize);
            }

            assert frameMap.getRegisterConfig().getCalleeSaveRegisters() == null;

            if (!isStub && config.nmethodEntryBarrier != 0) {
                emitNmethodEntryBarrier(crb, asm);
            } else {
                crb.recordMark(HotSpotMarkId.FRAME_COMPLETE);
            }

            if (ZapStackOnMethodEntry.getValue(crb.getOptions())) {
                final int intSize = 4;
                for (int i = 0; i < frameSize / intSize; ++i) {
                    asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1);
                }
            }
        }

        private void emitNmethodEntryBarrier(CompilationResultBuilder crb, AMD64HotSpotMacroAssembler asm) {
            GraalError.guarantee(HotSpotMarkId.ENTRY_BARRIER_PATCH.isAvailable(), "must be available");
            ForeignCallLinkage callTarget = getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.NMETHOD_ENTRY_BARRIER);

            // The assembly sequence is from
            // src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp. It was improved in
            // JDK 20 to be more efficient.
            final Label continuation = new Label();
            final Label entryPoint = new Label();

            // The following code sequence must be emitted in exactly this fashion as HotSpot
            // will check that the barrier is the expected code sequence.
            asm.align(4);
            crb.recordMark(HotSpotMarkId.FRAME_COMPLETE);
            crb.recordMark(HotSpotMarkId.ENTRY_BARRIER_PATCH);
            asm.nmethodEntryCompare(config.threadDisarmedOffset);
            asm.jcc(ConditionFlag.NotEqual, entryPoint);
            crb.getLIR().addSlowPath(null, () -> {
                asm.bind(entryPoint);
                /*
                 * The nmethod entry barrier can deoptimize by manually removing this frame. It
                 * makes some assumptions about the frame layout that aren't always true for Graal.
                 * In particular it assumes the caller`s rbp is always saved in the standard
                 * location. With -XX:+PreserveFramePointer this has been done by the frame setup.
                 * Otherwise it is only saved lazily (i.e. if rbp is actually used by the register
                 * allocator). Since nmethod entry barriers are enabled, the space for rbp has been
                 * reserved in the frame and here we ensure it is properly saved before calling the
                 * nmethod entry barrier.
                 */
                AMD64HotSpotFrameMap frameMap = (AMD64HotSpotFrameMap) crb.frameMap;
                if (!frameMap.preserveFramePointer()) {
                    asm.movq(new AMD64Address(rsp, frameMap.offsetForStackSlot(frameMap.getRBPSpillSlot())), rbp);
                }
                // This is always a near call
                asm.call((before, after) -> {
                    crb.recordDirectCall(before, after, callTarget, null);
                }, callTarget);

                // Return to inline code
                asm.jmp(continuation);
            });
            asm.bind(continuation);
        }

        @Override
        public void leave(CompilationResultBuilder crb) {
            AMD64HotSpotFrameMap frameMap = (AMD64HotSpotFrameMap) crb.frameMap;
            AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm;
            assert frameMap.getRegisterConfig().getCalleeSaveRegisters() == null;

            if (frameMap.preserveFramePointer()) {
                asm.movq(rsp, rbp);
                asm.pop(rbp);
            } else {
                asm.incrementq(rsp, frameMap.frameSize());
            }
        }

        @Override
        public void returned(CompilationResultBuilder crb) {
            // nothing to do
        }

        public void rawEnter(CompilationResultBuilder crb) {
            AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm;
            AMD64FrameMap frameMap = (AMD64FrameMap) crb.frameMap;

            if (frameMap.preserveFramePointer()) {
                // Stack-walking friendly instructions
                asm.push(rbp);
                asm.movq(rbp, rsp);
            }
            asm.decrementq(rsp, frameMap.frameSize());
        }

        public void rawLeave(CompilationResultBuilder crb) {
            leave(crb);
        }
    }

    @Override
    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
        // Omit the frame if the method:
        // - has no spill slots or other slots allocated during register allocation
        // - has no callee-saved registers
        // - has no incoming arguments passed on the stack
        // - has no deoptimization points
        // - makes no foreign calls (which require an aligned stack)
        HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen;
        LIR lir = gen.getLIR();
        assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
        OptionValues options = lir.getOptions();
        DebugContext debug = lir.getDebug();

        Stub stub = gen.getStub();
        AMD64MacroAssembler masm = new AMD64HotSpotMacroAssembler(config, getTarget(), options, getProviders(), config.CPU_HAS_INTEL_JCC_ERRATUM);
        HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
        DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
        CompilationResultBuilder crb = factory.createBuilder(getProviders(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None, lir);
        crb.setTotalFrameSize(frameMap.totalFrameSize());
        crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize());
        crb.setMinDataSectionItemAlignment(getMinDataSectionItemAlignment());
        StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
        if (deoptimizationRescueSlot != null && stub == null) {
            crb.compilationResult.setCustomStackAreaOffset(deoptimizationRescueSlot);
        }

        if (stub != null) {
            updateStub(stub, gen, frameMap);
        }

        return crb;
    }

    @Override
    public void emitCode(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) {
        emitCodeHelper(crb, installedCodeOwner, entryPointDecorator);
        if (GraalOptions.OptimizeLongJumps.getValue(crb.getOptions())) {
            optimizeLongJumps(crb, installedCodeOwner, entryPointDecorator);
        }
    }

    private void emitCodeHelper(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) {
        AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm;
        FrameMap frameMap = crb.frameMap;
        RegisterConfig regConfig = frameMap.getRegisterConfig();

        // Emit the prefix
        emitCodePrefix(installedCodeOwner, crb, asm, regConfig);

        if (entryPointDecorator != null) {
            entryPointDecorator.emitEntryPoint(crb);
        }

        // Emit code for the LIR
        crb.emitLIR();

        // Emit the suffix
        emitCodeSuffix(crb, asm);
    }

    /**
     * Emits the code prior to the verified entry point.
     *
     * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
     */
    public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig) {
        HotSpotProviders providers = getProviders();
        if (installedCodeOwner != null && !installedCodeOwner.isStatic()) {
            JavaType[] parameterTypes = {providers.getMetaAccess().lookupJavaType(Object.class)};
            CallingConvention cc = regConfig.getCallingConvention(HotSpotCallingConventionType.JavaCallee, null, parameterTypes, this);
            Register receiver = asRegister(cc.getArgument(0));
            AMD64Address src = new AMD64Address(receiver, config.hubOffset);
            int before;
            if (config.icSpeculatedKlassOffset == Integer.MAX_VALUE) {
                crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY);
                // c1_LIRAssembler_x86.cpp: const Register IC_Klass = rax;
                Register inlineCacheKlass = rax;

                if (config.useCompressedClassPointers) {
                    Register register = r10;
                    Register heapBase = providers.getRegisters().getHeapBaseRegister();
                    AMD64HotSpotMove.decodeKlassPointer(asm, register, heapBase, src, config);
                    if (config.narrowKlassBase != 0) {
                        // The heap base register was destroyed above, so restore it
                        if (config.narrowOopBase == 0L) {
                            asm.xorq(heapBase, heapBase);
                        } else {
                            asm.movq(heapBase, config.narrowOopBase);
                        }
                    }
                    before = asm.cmpqAndJcc(inlineCacheKlass, register, ConditionFlag.NotEqual, null, false);
                } else {
                    before = asm.cmpqAndJcc(inlineCacheKlass, src, ConditionFlag.NotEqual, null, false);
                }
                crb.recordDirectCall(before, asm.position(), getForeignCalls().lookupForeignCall(IC_MISS_HANDLER), null);
            } else {
                // JDK-8322630 (removed ICStubs)
                Register data = rax;
                Register temp = r10;
                ForeignCallLinkage icMissHandler = getForeignCalls().lookupForeignCall(IC_MISS_HANDLER);

                // Size of IC check sequence checked with a guarantee below.
                int inlineCacheCheckSize = 14;
                if (asm.force4ByteNonZeroDisplacements()) {
                    /*
                     * The mov and cmp below each contain a 1-byte displacement that is emitted as 4
                     * bytes instead, thus we have 3 extra bytes for each of these instructions.
                     */
                    inlineCacheCheckSize += 3 + 3;
                }
                asm.align(config.codeEntryAlignment, asm.position() + inlineCacheCheckSize);

                int startICCheck = asm.position();
                crb.recordMark(HotSpotMarkId.UNVERIFIED_ENTRY);
                AMD64Address icSpeculatedKlass = new AMD64Address(data, config.icSpeculatedKlassOffset);

                AMD64BaseAssembler.OperandSize size;
                if (config.useCompressedClassPointers) {
                    asm.movl(temp, src);
                    size = AMD64BaseAssembler.OperandSize.DWORD;
                } else {
                    asm.movptr(temp, src);
                    size = AMD64BaseAssembler.OperandSize.QWORD;
                }
                before = asm.cmpAndJcc(size, temp, icSpeculatedKlass, ConditionFlag.NotEqual, null, false);
                crb.recordDirectCall(before, asm.position(), icMissHandler, null);

                int actualInlineCacheCheckSize = asm.position() - startICCheck;
                if (actualInlineCacheCheckSize != inlineCacheCheckSize) {
                    // Code emission pattern has changed: adjust `inlineCacheCheckSize`
                    // initialization above accordingly.
                    throw new GraalError("%s != %s", actualInlineCacheCheckSize, inlineCacheCheckSize);
                }
            }
        }

        asm.align(config.codeEntryAlignment);
        crb.recordMark(crb.compilationResult.getEntryBCI() != -1 ? HotSpotMarkId.OSR_ENTRY : HotSpotMarkId.VERIFIED_ENTRY);
    }

    public void emitCodeSuffix(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
        HotSpotProviders providers = getProviders();
        HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
        if (!frameContext.isStub) {
            HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
            if (crb.getPendingImplicitExceptionList() != null) {
                for (CompilationResultBuilder.PendingImplicitException pendingImplicitException : crb.getPendingImplicitExceptionList()) {
                    // Insert stub code that stores the corresponding deoptimization action &
                    // reason, as well as the failed speculation, and calls into
                    // DEOPT_BLOB_UNCOMMON_TRAP. Note that we use the debugging info at the
                    // exceptional PC that triggers this implicit exception, we cannot touch
                    // any register/stack slot in this stub, so as to preserve a valid mapping for
                    // constructing the interpreter frame.
                    int pos = asm.position();
                    Register thread = getProviders().getRegisters().getThreadRegister();
                    // Store deoptimization reason and action into thread local storage.
                    asm.movl(new AMD64Address(thread, config.pendingDeoptimizationOffset), pendingImplicitException.state.deoptReasonAndAction.asInt());

                    JavaConstant deoptSpeculation = pendingImplicitException.state.deoptSpeculation;
                    if (deoptSpeculation.getJavaKind() == JavaKind.Long) {
                        // Store speculation into thread local storage. As AMD64 does not support
                        // 64-bit long integer memory store, we break it into two 32-bit integer
                        // store.
                        long speculationAsLong = pendingImplicitException.state.deoptSpeculation.asLong();
                        if (NumUtil.isInt(speculationAsLong)) {
                            AMD64Assembler.AMD64MIOp.MOV.emit(asm, AMD64BaseAssembler.OperandSize.QWORD,
                                            new AMD64Address(thread, config.pendingFailedSpeculationOffset), (int) speculationAsLong);
                        } else {
                            asm.movl(new AMD64Address(thread, config.pendingFailedSpeculationOffset), (int) speculationAsLong);
                            asm.movl(new AMD64Address(thread, config.pendingFailedSpeculationOffset + 4), (int) (speculationAsLong >> 32));
                        }
                    } else {
                        assert deoptSpeculation.getJavaKind() == JavaKind.Int : deoptSpeculation;
                        int speculationAsInt = pendingImplicitException.state.deoptSpeculation.asInt();
                        asm.movl(new AMD64Address(thread, config.pendingFailedSpeculationOffset), speculationAsInt);
                    }

                    AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP), null, false, pendingImplicitException.state);
                    crb.recordImplicitException(pendingImplicitException.codeOffset, pos, pendingImplicitException.state);
                }
            }
            trampolineCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), HotSpotMarkId.EXCEPTION_HANDLER_ENTRY);
            trampolineCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), HotSpotMarkId.DEOPT_HANDLER_ENTRY);
            if (config.supportsMethodHandleDeoptimizationEntry() && crb.needsMHDeoptHandler()) {
                trampolineCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY);
            }
        }
    }

    private static void trampolineCall(CompilationResultBuilder crb, AMD64MacroAssembler asm, ForeignCallLinkage callTarget, HotSpotMarkId exceptionHandlerEntry) {
        crb.recordMark(AMD64Call.directCall(crb, asm, callTarget, null, false, null), exceptionHandlerEntry);
        // Ensure the return location is a unique pc and that control flow doesn't return here
        asm.halt();
    }

    @Override
    public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo, Object stub) {
        RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
        return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo, config.preserveFramePointer(stub != null));
    }

    /**
     * Performs a code emit from LIR and replaces jumps with 4byte displacement by equivalent
     * instructions with single byte displacement, where possible. If any of these optimizations
     * unexpectedly results in a {@link BranchTargetOutOfBoundsException}, code without any
     * optimized jumps will be emitted.
     */
    private void optimizeLongJumps(CompilationResultBuilder crb, ResolvedJavaMethod installedCodeOwner, EntryPointDecorator entryPointDecorator) {
        // triggers a reset of the assembler during which replaceable jumps are identified
        crb.resetForEmittingCode();
        try {
            emitCodeHelper(crb, installedCodeOwner, entryPointDecorator);
        } catch (BranchTargetOutOfBoundsException e) {
            /*
             * Alignments have invalidated the assumptions regarding short jumps. Trigger fail-safe
             * mode and emit unoptimized code.
             */
            AMD64MacroAssembler masm = (AMD64MacroAssembler) crb.asm;
            masm.disableOptimizeLongJumpsAfterException();
            crb.resetForEmittingCode();
            emitCodeHelper(crb, installedCodeOwner, entryPointDecorator);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy