Search in sources :

Example 1 with AMD64InstructionPatcher

use of com.oracle.svm.core.graal.code.amd64.AMD64InstructionPatcher in project graal by oracle.

the class NativeImageCodeCache method patchMethods.

/**
 * Patch references from code to other code and constant data. Generate relocation information
 * in the process. More patching can be done, and correspondingly fewer relocation records
 * generated, if the caller passes a non-null rodataDisplacementFromText.
 *
 * @param relocs a relocation map
 */
public void patchMethods(RelocatableBuffer relocs) {
    // in each compilation result...
    for (Entry<HostedMethod, CompilationResult> entry : compilations.entrySet()) {
        HostedMethod method = entry.getKey();
        CompilationResult compilation = entry.getValue();
        // the codecache-relative offset of the compilation
        int compStart = method.getCodeAddressOffset();
        AMD64InstructionPatcher patcher = new AMD64InstructionPatcher(compilation);
        // ... patch direct call sites.
        for (Infopoint infopoint : compilation.getInfopoints()) {
            if (infopoint instanceof Call && ((Call) infopoint).direct) {
                Call call = (Call) infopoint;
                // NOTE that for the moment, we don't make static calls to external
                // (e.g. native) functions. So every static call site has a target
                // which is also in the code cache (a.k.a. a section-local call).
                // This will change, and we will have to case-split here... but not yet.
                int callTargetStart = ((HostedMethod) call.target).getCodeAddressOffset();
                // Patch a PC-relative call.
                // This code handles the case of section-local calls only.
                int pcDisplacement = callTargetStart - (compStart + call.pcOffset);
                patcher.findPatchData(call.pcOffset, pcDisplacement).apply(compilation.getTargetCode());
            }
        }
        // ... and patch references to constant data
        for (DataPatch dataPatch : compilation.getDataPatches()) {
            /*
                 * Constants are allocated offsets in a separate space, which can be emitted as
                 * read-only (.rodata) section.
                 */
            AMD64InstructionPatcher.PatchData patchData = patcher.findPatchData(dataPatch.pcOffset, 0);
            /*
                 * The relocation site is some offset into the instruction, which is some offset
                 * into the method, which is some offset into the text section (a.k.a. code cache).
                 * The offset we get out of the RelocationSiteInfo accounts for the first two, since
                 * we pass it the whole method. We add the method start to get the section-relative
                 * offset.
                 */
            long siteOffset = compStart + patchData.operandPosition;
            /*
                 * Do we have an addend? Yes; it's constStart. BUT x86/x86-64 PC-relative references
                 * are relative to the *next* instruction. So, if the next instruction starts n
                 * bytes from the relocation site, we want to subtract n bytes from our addend.
                 */
            long addend = (patchData.nextInstructionPosition - patchData.operandPosition);
            relocs.addPCRelativeRelocationWithAddend((int) siteOffset, patchData.operandSize, addend, dataPatch.reference);
        }
    }
}
Also used : Call(jdk.vm.ci.code.site.Call) DataPatch(jdk.vm.ci.code.site.DataPatch) AMD64InstructionPatcher(com.oracle.svm.core.graal.code.amd64.AMD64InstructionPatcher) HostedMethod(com.oracle.svm.hosted.meta.HostedMethod) Infopoint(jdk.vm.ci.code.site.Infopoint) DeoptEntryInfopoint(com.oracle.svm.core.deopt.DeoptEntryInfopoint) CompilationResult(org.graalvm.compiler.code.CompilationResult) Infopoint(jdk.vm.ci.code.site.Infopoint) DeoptEntryInfopoint(com.oracle.svm.core.deopt.DeoptEntryInfopoint)

Example 2 with AMD64InstructionPatcher

use of com.oracle.svm.core.graal.code.amd64.AMD64InstructionPatcher in project graal by oracle.

the class InstalledCodeBuilder method installOperation.

@SuppressWarnings("try")
private void installOperation() {
    AMD64InstructionPatcher patcher = new AMD64InstructionPatcher(compilation);
    patchData(patcher);
    int updatedCodeSize = patchCalls(patcher);
    assert updatedCodeSize <= constantsOffset;
    // Store the compiled code
    for (int index = 0; index < updatedCodeSize; index++) {
        code.writeByte(index, compiledBytes[index]);
    }
    /* Primitive constants are written directly to the code memory. */
    ByteBuffer constantsBuffer = SubstrateUtil.wrapAsByteBuffer(code.add(constantsOffset), compilation.getDataSection().getSectionSize());
    /*
         * Object constants are stored in an Object[] array first, because we have to be careful
         * that they are always exposed as roots to the GC.
         */
    ObjectConstantsHolder objectConstants = new ObjectConstantsHolder(compilation);
    compilation.getDataSection().buildDataSection(constantsBuffer, (position, constant) -> {
        objectConstants.add(position, KnownIntrinsics.convertUnknownValue(SubstrateObjectConstant.asObject(constant), Object.class));
    });
    // Open the PinnedAllocator for the meta-information.
    metaInfoAllocator.open();
    try {
        runtimeMethodInfo = metaInfoAllocator.newInstance(RuntimeMethodInfo.class);
        constantsWalker = metaInfoAllocator.newInstance(ConstantsWalker.class);
        ReferenceMapEncoder encoder = new ReferenceMapEncoder();
        encoder.add(objectConstants.referenceMap);
        constantsWalker.referenceMapEncoding = encoder.encodeAll(metaInfoAllocator);
        constantsWalker.referenceMapIndex = encoder.lookupEncoding(objectConstants.referenceMap);
        constantsWalker.constantsAddr = code.add(constantsOffset);
        constantsWalker.constantsSize = compilation.getDataSection().getSectionSize();
        Heap.getHeap().getGC().registerObjectReferenceWalker(constantsWalker);
        /*
             * We now have the constantsWalker initialized and registered, but it is still inactive.
             * Writing the actual object constants to the code memory needs to be atomic regarding
             * to GC. After everything is written, we activate the constantsWalker.
             */
        try (NoAllocationVerifier verifier = NoAllocationVerifier.factory("InstalledCodeBuilder.install")) {
            writeObjectConstantsToCode(objectConstants);
        }
        createCodeChunkInfos();
        InstalledCodeObserver.InstalledCodeObserverHandle[] observerHandles = InstalledCodeObserverSupport.installObservers(codeObservers, metaInfoAllocator);
        runtimeMethodInfo.setData((CodePointer) code, WordFactory.unsigned(codeSize), installedCode, constantsWalker, metaInfoAllocator, observerHandles);
    } finally {
        metaInfoAllocator.close();
    }
    Throwable[] errorBox = { null };
    VMOperation.enqueueBlockingSafepoint("Install code", () -> {
        try {
            CodeInfoTable.getRuntimeCodeCache().addMethod(runtimeMethodInfo);
            /*
                 * This call makes the new code visible, i.e., other threads can start executing it
                 * immediately. So all metadata must be registered at this point.
                 */
            installedCode.setAddress(code.rawValue(), method);
        } catch (Throwable e) {
            errorBox[0] = e;
        }
    });
    if (errorBox[0] != null) {
        throw rethrow(errorBox[0]);
    }
    compilation = null;
}
Also used : RuntimeMethodInfo(com.oracle.svm.core.code.RuntimeMethodInfo) ByteBuffer(java.nio.ByteBuffer) Infopoint(jdk.vm.ci.code.site.Infopoint) ReferenceMapEncoder(com.oracle.svm.core.heap.ReferenceMapEncoder) AMD64InstructionPatcher(com.oracle.svm.core.graal.code.amd64.AMD64InstructionPatcher) NoAllocationVerifier(com.oracle.svm.core.heap.NoAllocationVerifier)

Aggregations

AMD64InstructionPatcher (com.oracle.svm.core.graal.code.amd64.AMD64InstructionPatcher)2 Infopoint (jdk.vm.ci.code.site.Infopoint)2 RuntimeMethodInfo (com.oracle.svm.core.code.RuntimeMethodInfo)1 DeoptEntryInfopoint (com.oracle.svm.core.deopt.DeoptEntryInfopoint)1 NoAllocationVerifier (com.oracle.svm.core.heap.NoAllocationVerifier)1 ReferenceMapEncoder (com.oracle.svm.core.heap.ReferenceMapEncoder)1 HostedMethod (com.oracle.svm.hosted.meta.HostedMethod)1 ByteBuffer (java.nio.ByteBuffer)1 Call (jdk.vm.ci.code.site.Call)1 DataPatch (jdk.vm.ci.code.site.DataPatch)1 CompilationResult (org.graalvm.compiler.code.CompilationResult)1