Path: blob/master/runtime/compiler/z/codegen/S390J9CallSnippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 2022 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "z/codegen/S390J9CallSnippet.hpp"2324#include <stdint.h>25#include "codegen/CodeGenerator.hpp"26#include "codegen/InstOpCode.hpp"27#include "env/CompilerEnv.hpp"28#include "env/IO.hpp"29#include "env/J2IThunk.hpp"30#include "env/jittypes.h"31#include "env/VMJ9.h"32#include "env/VerboseLog.hpp"33#include "il/LabelSymbol.hpp"34#include "il/Node.hpp"35#include "il/Node_inlines.hpp"36#include "runtime/CodeCacheManager.hpp"37#include "runtime/Runtime.hpp"38#include "runtime/RuntimeAssumptions.hpp"3940uint8_t *41TR::S390J9CallSnippet::generateVIThunk(TR::Node * callNode, int32_t argSize, TR::CodeGenerator * cg)42{43TR::Compilation *comp = cg->comp();44TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());45int32_t lengthOfVIThunk = (comp->target().is64Bit()) ? 18 : 12;46int32_t codeSize = instructionCountForArguments(callNode, cg) + lengthOfVIThunk;47uint32_t rEP = (uint32_t) cg->getEntryPointRegister() - 1;4849// make it double-word aligned50codeSize = (codeSize + 7) / 8 * 8 + 8; // Additional 4 bytes to hold size of thunk51uint8_t * thunk, * cursor, * returnValue;52TR::SymbolReference *dispatcherSymbol;5354if (fej9->storeOffsetToArgumentsInVirtualIndirectThunks())55thunk = (uint8_t *)comp->trMemory()->allocateMemory(codeSize, heapAlloc);56else57thunk = (uint8_t *)cg->allocateCodeMemory(codeSize, true);5859cursor = returnValue = thunk + 8;6061switch (callNode->getDataType())62{63case TR::NoType:64dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtual0);65break;66case TR::Int32:67dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtual1);68break;69case TR::Address:70if (comp->target().is64Bit())71{72dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtualJ);73}74else75{76dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtual1);77}7879break;80case TR::Int64:81dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtualJ);82break;83case TR::Float:84dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtualF);85break;86case TR::Double:87dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_S390icallVMprJavaSendVirtualD);88break;89default:90TR_ASSERT(0, "Bad return data type for a call node. DataType was %s\n",91comp->getDebug()->getName(callNode->getDataType()));92}9394cursor = S390flushArgumentsToStack(cursor, callNode, argSize, cg);9596// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!97// if you change the following code,98// make sure 'lengthOfVIThunk' and hence 'codeSize' defined above99// are large enough to cover the VIThunk code.100// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!101// branch to the dispatcher102//103// 0d40 BASR rEP,0104// 5840 400a L rEP,6(,rEP) or LG rEP, 6(,rEP) for 64bit105// 0de4 BCR ,rEP106// <method address>107108*(int16_t *) cursor = 0x0d00 + (((int16_t) rEP) << 4); // BASR rEP,0109cursor += 2;110if (comp->target().is64Bit())111{112*(uint32_t *) cursor = 0xe3000008 + (rEP << 12) + (rEP << 20); // LG rEP,8(,rEP)113cursor += 4;114*(uint16_t *) cursor = 0x0004;115cursor += 2;116}117else118{119*(int32_t *) cursor = 0x58000006 + (rEP << 12) + (rEP << 20); // L rEP,6(,rEP)120cursor += 4;121}122123*(int16_t *) cursor = 0x07f0 + (int16_t) rEP; // BCR rEP124cursor += 2;125126*((int32_t *)thunk + 1) = cursor - returnValue; // patch offset for AOT relocation127128*(uintptr_t *) cursor = (uintptr_t) dispatcherSymbol->getMethodAddress();129130cursor += sizeof(uintptr_t);131132*(int32_t *)thunk = cursor - returnValue; // patch size of thunk133134return returnValue;135}136137TR_J2IThunk *138TR::S390J9CallSnippet::generateInvokeExactJ2IThunk(TR::Node * callNode, int32_t argSize, char* signature, TR::CodeGenerator * cg)139{140uint32_t rEP = (uint32_t) cg->getEntryPointRegister() - 1;141TR::Compilation *comp = cg->comp();142TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());143bool verbose = comp->getOptions()->getVerboseOption(TR_VerboseJ2IThunks);144int32_t finalCallLength = verbose? 6 : 2;145int32_t lengthOfIEThunk = finalCallLength + (comp->target().is64Bit() ? 16 : 10);146int32_t codeSize = instructionCountForArguments(callNode, cg) + lengthOfIEThunk;147// TODO:JSR292: VI thunks have code to ensure they are double-word aligned. Do we need that here?148149TR_J2IThunkTable *thunkTable = comp->getPersistentInfo()->getInvokeExactJ2IThunkTable();150TR_J2IThunk *thunk = TR_J2IThunk::allocate(codeSize, signature, cg, thunkTable);151uint8_t *cursor = thunk->entryPoint();152153TR::SymbolReference *dispatcherSymbol;154switch (callNode->getDataType())155{156case TR::NoType:157dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExact0);158break;159case TR::Int32:160dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExact1);161break;162case TR::Address:163if (comp->target().is64Bit())164dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactJ);165else166dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExact1);167break;168case TR::Int64:169dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactJ);170break;171case TR::Float:172dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactF);173break;174case TR::Double:175dispatcherSymbol = cg->symRefTab()->findOrCreateRuntimeHelper(TR_icallVMprJavaSendInvokeExactD);176break;177default:178TR_ASSERT(0, "Bad return data type for a call node. DataType was %s\n",179comp->getDebug()->getName(callNode->getDataType()));180}181182cursor = S390flushArgumentsToStack(cursor, callNode, argSize, cg);183184// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!185// if you change the following code,186// make sure 'lengthOfVIThunk' and hence 'codeSize' defined above187// are large enough to cover the VIThunk code.188// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!189// branch to the dispatcher190//191// 0d40 BASR rEP,0192// 5840 400a L rEP,6(,rEP) or LG rEP, 8(,rEP) for 64bit193// 0de4 BCR ,rEP -- OR CALL TO methodHandleJ2IGlue --194// <method address>195196*(int16_t *) cursor = 0x0d00 + (((int16_t) rEP) << 4); // BASR rEP,0197cursor += 2;198if (comp->target().is64Bit())199{200*(uint32_t *) cursor = 0xe3000006 + finalCallLength + (rEP << 12) + (rEP << 20); // LG rEP,8(,rEP)201cursor += 4;202*(uint16_t *) cursor = 0x0004;203cursor += 2;sizeof(int16_t);204}205else206{207*(int32_t *) cursor = 0x58000004 + finalCallLength + (rEP << 12) + (rEP << 20); // L rEP,6(,rEP)208cursor += 4;209}210211uintptr_t helperAddress = (uintptr_t)dispatcherSymbol->getMethodAddress();212if (verbose)213{214*(int16_t *) cursor = 0xC0F4; // BRCL <Helper Addr>215cursor += 2;216217TR::SymbolReference *helper = cg->symRefTab()->findOrCreateRuntimeHelper(TR_methodHandleJ2IGlue);218intptr_t destAddr = (intptr_t)helper->getMethodAddress();219#if defined(TR_TARGET_64BIT)220#if defined(J9ZOS390)221if (comp->getOption(TR_EnableRMODE64))222#endif223{224if (NEEDS_TRAMPOLINE(destAddr, cursor, cg))225destAddr = TR::CodeCacheManager::instance()->findHelperTrampoline(helper->getReferenceNumber(), (void *)cursor);226}227#endif228TR_ASSERT(CHECK_32BIT_TRAMPOLINE_RANGE(destAddr, cursor), "Helper Call must be reachable");229*(int32_t *) cursor = (int32_t)((destAddr - (intptr_t)(cursor - 2)) / 2);230cursor += 4;231}232else233{234*(int16_t *) cursor = 0x07f0 + (int16_t) rEP; // BCR rEP235cursor += 2;236}237238*(uintptr_t *) cursor = (uintptr_t) cg->fej9()->getInvokeExactThunkHelperAddress(comp, dispatcherSymbol, callNode->getDataType());239cursor += sizeof(uintptr_t);240241diagnostic("\n-- ( Created invokeExact J2I thunk " POINTER_PRINTF_FORMAT " for node " POINTER_PRINTF_FORMAT " )", thunk, callNode);242243TR_ASSERT(cursor == thunk->entryPoint() + codeSize, "Must allocate correct amount of memory for invokeExact J2I thunk %p. Allocated %d bytes but consumed %d = %d plus argument spills", thunk->entryPoint(), codeSize, cursor - thunk->entryPoint(), lengthOfIEThunk);244245if (verbose)246TR_VerboseLog::writeLineLocked(TR_Vlog_J2I, "Created J2I thunk %s @ %p while compiling %s", thunk->terseSignature(), thunk->entryPoint(), comp->signature());247248return thunk;249}250251252uint8_t *253TR::S390J9CallSnippet::emitSnippetBody()254{255TR::Compilation *comp = cg()->comp();256TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());257258uint8_t * cursor = cg()->getBinaryBufferCursor();259TR::Node * callNode = getNode();260TR::SymbolReference * methodSymRef = getRealMethodSymbolReference();261262if (!methodSymRef)263methodSymRef = callNode->getSymbolReference();264265TR::MethodSymbol * methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();266267AOTcgDiag1(comp, "TR::S390CallSnippet::emitSnippetBody cursor=%x\n", cursor);268getSnippetLabel()->setCodeLocation(cursor);269270// Flush in-register arguments back to the stack for interpreter271cursor = S390flushArgumentsToStack(cursor, callNode, getSizeOfArguments(), cg());272273TR_RuntimeHelper runtimeHelper = getInterpretedDispatchHelper(methodSymRef, callNode->getDataType());274TR::SymbolReference * glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(runtimeHelper);275276// Generate RIOFF if RI is supported.277cursor = generateRuntimeInstrumentationOnOffInstruction(cg(), cursor, TR::InstOpCode::RIOFF);278279// data area start address280uintptr_t dataStartAddr = (uintptr_t) (getPICBinaryLength() + cursor);281282// calculate pad bytes to get the data area aligned283int32_t pad_bytes = (dataStartAddr + (sizeof(uintptr_t) - 1)) / sizeof(uintptr_t) * sizeof(uintptr_t) - dataStartAddr;284285setPadBytes(pad_bytes);286287// branch to the glueRef288//289// 0d40 BASR rEP,0290// 5840 4006 L rEP,6(,rEP) LG rEP, 8(rEP) for 64bit291// 0de4 BASR r14,rEP292293cursor = generatePICBinary(cursor, glueRef);294295// add NOPs to make sure the data area is aligned296if (pad_bytes == 2)297{298*(int16_t *) cursor = 0x0000; // padding 2-bytes299cursor += 2;300}301else if (comp->target().is64Bit())302{303if (pad_bytes == 4) // padding 4-bytes304{305*(int32_t *) cursor = 0x00000000;306cursor += 4;307}308else if (pad_bytes == 6) // padding 6-bytes309{310*(int32_t *) cursor = 0x00000000;311cursor += 4;312*(uint16_t *) cursor = 0x0000;313cursor += 2;314}315}316317// Data Area318// <method address>319// code cache RA320// method pointer321322pad_bytes = (((uintptr_t) cursor + (sizeof(uintptr_t) - 1)) / sizeof(uintptr_t) * sizeof(uintptr_t) - (uintptr_t) cursor);323TR_ASSERT( pad_bytes == 0, "Method address field must be aligned for patching");324325// Method address326*(uintptr_t *) cursor = (uintptr_t) glueRef->getMethodAddress();327AOTcgDiag1(comp, "add TR_AbsoluteHelperAddress cursor=%x\n", cursor);328cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t *)glueRef, TR_AbsoluteHelperAddress, cg()),329__FILE__, __LINE__, callNode);330cursor += sizeof(uintptr_t);331332// Store the code cache RA333*(uintptr_t *) cursor = (uintptr_t) getCallRA();334AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);335cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),336__FILE__, __LINE__, callNode);337cursor += sizeof(uintptr_t);338339//induceOSRAtCurrentPC is implemented in the VM, and it knows, by looking at the current PC, what method it needs to340//continue execution in interpreted mode. Therefore, it doesn't need the method pointer.341if (!glueRef->isOSRInductionHelper())342{343// Store the method pointer: it is NULL for unresolved344// This field must be doubleword aligned for 64-bit and word aligned for 32-bit345if (methodSymRef->isUnresolved() || (comp->compileRelocatableCode() && !comp->getOption(TR_UseSymbolValidationManager)))346{347pad_bytes = (((uintptr_t) cursor + (sizeof(uintptr_t) - 1)) / sizeof(uintptr_t) * sizeof(uintptr_t) - (uintptr_t) cursor);348TR_ASSERT( pad_bytes == 0, "Method Pointer field must be aligned for patching");349*(uintptr_t *) cursor = 0;350if (comp->getOption(TR_EnableHCR))351{352//TODO check what happens when we pass -1 to jitAddPicToPatchOnClassRedefinition an dif it's correct in this case353cg()->jitAddPicToPatchOnClassRedefinition((void*)-1, (void *)cursor, true);354cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation((uint8_t *)cursor, NULL,355TR_HCR, cg()),__FILE__, __LINE__, getNode());356}357}358else359{360uintptr_t ramMethod = (uintptr_t)methodSymRef->getSymbol()->castToResolvedMethodSymbol()->getResolvedMethod()->getPersistentIdentifier();361*(uintptr_t *) cursor = ramMethod;362if (comp->getOption(TR_EnableHCR))363cg()->jitAddPicToPatchOnClassRedefinition((void *)methodSymbol->getMethodAddress(), (void *)cursor);364AOTcgDiag1(comp, "add TR_MethodObject cursor=%x\n", cursor);365if (comp->getOption(TR_UseSymbolValidationManager))366{367TR_ASSERT_FATAL(ramMethod, "cursor = %x, ramMehtod can not be null", cursor);368cg()->addExternalRelocation( new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,369(uint8_t *)ramMethod,370(uint8_t *)TR::SymbolType::typeMethod,371TR_SymbolFromManager,372cg()),373__FILE__, __LINE__, callNode);374}375#if defined(J9VM_OPT_JITSERVER)376else if (!comp->isOutOfProcessCompilation()) // Since we query this information from the client, remote compilations don't need to add relocation records for TR_MethodObject377#else378else379#endif /* defined(J9VM_OPT_JITSERVER) */380{381cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t *) callNode->getSymbolReference(), getNode() ? (uint8_t *)(intptr_t)getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_MethodObject, cg()),382__FILE__, __LINE__, callNode);383}384}385}386387return cursor + sizeof(uintptr_t);388}389390TR_RuntimeHelper TR::S390J9CallSnippet::getInterpretedDispatchHelper(TR::SymbolReference *methodSymRef, TR::DataType type)391{392TR::Compilation *comp = cg()->comp();393TR::MethodSymbol * methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();394bool isJitInduceOSRCall = false;395if (methodSymbol->isHelper() &&396methodSymRef->isOSRInductionHelper())397{398isJitInduceOSRCall = true;399}400401if (methodSymRef->isUnresolved() || (comp->compileRelocatableCode() && !comp->getOption(TR_UseSymbolValidationManager)))402{403TR_ASSERT(!isJitInduceOSRCall || !comp->compileRelocatableCode(), "calling jitInduceOSR is not supported yet under AOT\n");404if (methodSymbol->isStatic())405return TR_S390interpreterUnresolvedStaticGlue;406else407return TR_S390interpreterUnresolvedSpecialGlue;408}409else if (isJitInduceOSRCall)410{411return (TR_RuntimeHelper) methodSymRef->getReferenceNumber();412}413else if (methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative())414{415return TR_S390nativeStaticHelper;416}417else418{419return TR_S390interpreterStaticSpecialCallGlue;420}421}422423uint32_t424TR::S390J9CallSnippet::getPICBinaryLength()425{426if (self()->getKind() == TR::Snippet::IsUnresolvedCall)427return 14; /* LARL + LG/LGF + BCR */428else429return 6;430}431432uint8_t *433TR::S390J9CallSnippet::generatePICBinary(uint8_t * cursor, TR::SymbolReference* glueRef)434{435// Branch to the dispatcher.436// Since N3 instructions are supported, we can use relative long instructions.437// i.e.:438// BRASL r14, <target Addr>.439// - or -440// LARL r14, <target Addr>. // Unresolved Calls only.441// LG/LGF rEP, 0(r14).442// BCR rEP443uint32_t rEP = (uint32_t) cg()->getEntryPointRegister() - 1;444445if (self()->getKind() == TR::Snippet::IsUnresolvedCall)446{447// Generate LARL r14, <Start of Data Const>448*(int16_t *) cursor = 0xC0E0;449cursor += sizeof(int16_t);450intptr_t destAddr = (intptr_t)(cursor + getPICBinaryLength() + self()->getPadBytes() - 2);451*(int32_t *) cursor = (int32_t)((destAddr - (intptr_t)(cursor - 2)) / 2);452cursor += sizeof(int32_t);453454*(int32_t *) cursor = 0xe300e000 + (rEP << 20); // LG/F rEP, 0(r14)455cursor += sizeof(int32_t);456*(int16_t *) cursor = cg()->comp()->target().is64Bit() ? 0x0004 : 0x0014;457cursor += sizeof(int16_t);458459// BCR rEP460*(int16_t *) cursor = 0x07F0 + rEP;461cursor += sizeof(int16_t);462}463else464{465// Generate BRASL instruction.466intptr_t instructionStartAddress = (intptr_t)cursor;467*(int16_t *) cursor = 0xC0E5;468cursor += sizeof(int16_t);469470// Calculate the relative offset to get to helper method.471// If MCC is not supported, everything should be reachable.472// If MCC is supported, we will look up the appropriate trampoline, if473// necessary.474intptr_t destAddr = (intptr_t)(glueRef->getSymbol()->castToMethodSymbol()->getMethodAddress());475476#if defined(TR_TARGET_64BIT)477#if defined(J9ZOS390)478if (cg()->comp()->getOption(TR_EnableRMODE64))479#endif480{481if (cg()->directCallRequiresTrampoline(destAddr, instructionStartAddress))482{483// Destination is beyond our reachable jump distance, we'll find the484// trampoline.485destAddr = TR::CodeCacheManager::instance()->findHelperTrampoline(glueRef->getReferenceNumber(), (void *)cursor);486self()->setUsedTrampoline(true);487}488}489#endif490491TR_ASSERT_FATAL(cg()->comp()->target().cpu.isTargetWithinBranchRelativeRILRange(destAddr, instructionStartAddress),492"Helper Call is not reachable.");493self()->setSnippetDestAddr(destAddr);494495*(int32_t *) cursor = (int32_t)((destAddr - instructionStartAddress) / 2);496AOTcgDiag1(cg()->comp(), "add TR_AbsoluteHelperAddress cursor=%x\n", cursor);497cg()->addProjectSpecializedRelocation(cursor, (uint8_t*) glueRef, NULL, TR_HelperAddress,498__FILE__, __LINE__, self()->getNode());499cursor += sizeof(int32_t);500}501return cursor;502}503504uint32_t505TR::S390J9CallSnippet::getLength(int32_t estimatedSnippetStart)506{507// *this swipeable for debugger508// length = instructionCountForArgsInBytes + (BASR + L(or LG) + BASR +3*sizeof(uintptr_t)) + NOPs509// number of pad bytes has not been set when this method is called to510// estimate codebuffer size, so -- i'll put an conservative number here...511return (instructionCountForArguments(getNode(), cg()) +512getPICBinaryLength() +5133 * sizeof(uintptr_t) +514getRuntimeInstrumentationOnOffInstructionLength(cg()) +515sizeof(uintptr_t)); // the last item is for padding516}517518void519TR::S390J9CallSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)520{521uint8_t * bufferPos = getSnippetLabel()->getCodeLocation();522TR::Node * callNode = getNode();523TR::SymbolReference * methodSymRef = getRealMethodSymbolReference();524if(!methodSymRef)525methodSymRef = callNode->getSymbolReference();526527TR::MethodSymbol * methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();528TR::SymbolReference * glueRef;529int8_t padbytes = getPadBytes();530531debug->printSnippetLabel(pOutFile, getSnippetLabel(), bufferPos,532methodSymRef->isUnresolved() ? "Unresolved Call Snippet" : "Call Snippet");533534bufferPos = debug->printS390ArgumentsFlush(pOutFile, callNode, bufferPos, getSizeOfArguments());535536if (methodSymRef->isUnresolved() || (cg()->comp()->compileRelocatableCode() && !cg()->comp()->getOption(TR_UseSymbolValidationManager)))537{538if (methodSymbol->isStatic())539glueRef = cg()->getSymRef(TR_S390interpreterUnresolvedStaticGlue);540else541glueRef = cg()->getSymRef(TR_S390interpreterUnresolvedSpecialGlue);542}543else if ((methodSymbol->isVMInternalNative() || methodSymbol->isJITInternalNative()))544{545glueRef = cg()->getSymRef(TR_S390nativeStaticHelper);546}547else548{549glueRef = cg()->getSymRef(TR_S390interpreterStaticSpecialCallGlue);550}551552bufferPos = debug->printRuntimeInstrumentationOnOffInstruction(pOutFile, bufferPos, false); // RIOFF553554if (getKind() == TR::Snippet::IsUnresolvedCall)555{556debug->printPrefix(pOutFile, NULL, bufferPos, 6);557trfprintf(pOutFile, "LARL \tGPR14, *+%d <%p>\t# Start of Data Const.",5588 + 6 + padbytes,559bufferPos + 8 + 6 + padbytes);560bufferPos += 6;561debug->printPrefix(pOutFile, NULL, bufferPos, 6);562trfprintf(pOutFile, cg()->comp()->target().is64Bit() ? "LG \tGPR_EP, 0(,GPR14)" : "LGF \tGPR_EP, 0(,GPR14");563bufferPos += 6;564565debug->printPrefix(pOutFile, NULL, bufferPos, 2);566trfprintf(pOutFile, "BCR \tGPR_EP");567bufferPos += 2;568}569else570{571debug->printPrefix(pOutFile, NULL, bufferPos, 6);572trfprintf(pOutFile, "BRASL \tGPR14, <%p>\t# Branch to Helper Method %s",573getSnippetDestAddr(),574usedTrampoline() ? "- Trampoline Used.":"");575bufferPos += 6;576}577578if (padbytes == 2)579{580debug->printPrefix(pOutFile, NULL, bufferPos, 2);581trfprintf(pOutFile, "DC \t0x0000 \t\t\t# 2-bytes padding for alignment");582bufferPos += 2;583}584else if (padbytes == 4)585{586debug->printPrefix(pOutFile, NULL, bufferPos, 4) ;587trfprintf(pOutFile, "DC \t0x00000000 \t\t# 4-bytes padding for alignment");588bufferPos += 4;589}590else if (padbytes == 6)591{592debug->printPrefix(pOutFile, NULL, bufferPos, 6) ;593trfprintf(pOutFile, "DC \t0x000000000000 \t\t# 6-bytes padding for alignment");594bufferPos += 6;595}596597debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));598trfprintf(pOutFile, "DC \t%p \t\t# Method Address", glueRef->getMethodAddress());599bufferPos += sizeof(intptr_t);600601602debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));603trfprintf(pOutFile, "DC \t%p \t\t# Call Site RA", getCallRA());604bufferPos += sizeof(intptr_t);605606if (methodSymRef->isUnresolved())607{608debug->printPrefix(pOutFile, NULL, bufferPos, 0);609}610else611{612debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));613}614trfprintf(pOutFile, "DC \t%p \t\t# Method Pointer", methodSymRef->isUnresolved() ? 0 : methodSymbol->getMethodAddress());615}616617uint8_t *618TR::S390UnresolvedCallSnippet::emitSnippetBody()619{620TR::Compilation *comp = cg()->comp();621TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());622623uint8_t * cursor = TR::S390J9CallSnippet::emitSnippetBody();624625TR::SymbolReference * methodSymRef = getNode()->getSymbolReference();626TR::MethodSymbol * methodSymbol = methodSymRef->getSymbol()->castToMethodSymbol();627int32_t helperLookupOffset;628629switch (getNode()->getDataType())630{631case TR::NoType:632helperLookupOffset = 0;633break;634case TR::Int32:635helperLookupOffset = TR::Compiler->om.sizeofReferenceAddress();636break;637case TR::Address:638if (comp->target().is64Bit())639{640helperLookupOffset = 2 * TR::Compiler->om.sizeofReferenceAddress();641}642else643{644helperLookupOffset = TR::Compiler->om.sizeofReferenceAddress();645}646647break;648case TR::Int64:649helperLookupOffset = 2 * TR::Compiler->om.sizeofReferenceAddress();650break;651case TR::Float:652helperLookupOffset = 3 * TR::Compiler->om.sizeofReferenceAddress();653break;654case TR::Double:655helperLookupOffset = 4 * TR::Compiler->om.sizeofReferenceAddress();656break;657}658659// Constant Pool660*(uintptr_t *) cursor = (uintptr_t) methodSymRef->getOwningMethod(comp)->constantPool();661AOTcgDiag1(comp, "add TR_ConstantPool cursor=%x\n", cursor);662663#if defined(TR_TARGET_64BIT)664#if defined(J9ZOS390)665if (comp->getOption(TR_EnableRMODE64))666#endif667{668cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, *(uint8_t **)cursor, getNode() ? (uint8_t *)(intptr_t)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,669TR_Trampolines, cg()),670__FILE__, __LINE__,getNode());671}672#if defined(J9ZOS390)673else674{675cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, *(uint8_t **)cursor, getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool, cg()),676__FILE__, __LINE__, getNode());677}678#endif679#else680cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, *(uint8_t **)cursor, getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool, cg()),681__FILE__, __LINE__, getNode());682#endif683684cursor += sizeof(uintptr_t);685686// Constant Pool Index687*(uint32_t *) cursor = (helperLookupOffset << 24) | methodSymRef->getCPIndexForVM();688689#if defined(TR_TARGET_64BIT)690#if defined(J9ZOS390)691if (comp->getOption(TR_EnableRMODE64))692#endif693{694if ((comp->compileRelocatableCode() || comp->isOutOfProcessCompilation()) && comp->getOption(TR_TraceRelocatableDataDetailsCG))695{696traceMsg(comp, "<relocatableDataTrampolinesCG>\n");697traceMsg(comp, "%s\n", comp->signature());698traceMsg(comp, "%-8s", "cpIndex");699traceMsg(comp, "cp\n");700traceMsg(comp, "%-8x", methodSymRef->getCPIndexForVM());701traceMsg(comp, "%x\n", methodSymRef->getOwningMethod(comp)->constantPool());702traceMsg(comp, "</relocatableDataTrampolinesCG>\n");703}704}705#endif706707return cursor + sizeof(int32_t);708}709710uint32_t711TR::S390UnresolvedCallSnippet::getLength(int32_t estimatedSnippetStart)712{713return TR::S390J9CallSnippet::getLength(estimatedSnippetStart) + sizeof(uintptr_t) + sizeof(int32_t);714}715716uint8_t *717TR::S390VirtualSnippet::emitSnippetBody()718{719return NULL;720}721722uint32_t723TR::S390VirtualSnippet::getLength(int32_t estimatedSnippetStart)724{725return 0;726}727728uint8_t *729TR::S390VirtualUnresolvedSnippet::emitSnippetBody()730{731uint8_t * cursor = cg()->getBinaryBufferCursor();732TR::Node * callNode = getNode();733TR::Compilation *comp = cg()->comp();734TR::SymbolReference * glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390virtualUnresolvedHelper);735736getSnippetLabel()->setCodeLocation(cursor);737738// Generate RIOFF if RI is supported.739cursor = generateRuntimeInstrumentationOnOffInstruction(cg(), cursor, TR::InstOpCode::RIOFF);740741cursor = generatePICBinary(cursor, glueRef);742743744// Method address745*(uintptr_t *) cursor = (uintptr_t) glueRef->getMethodAddress();746AOTcgDiag1(comp, "add TR_AbsoluteHelperAddress cursor=%x\n", cursor);747cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t *)glueRef, TR_AbsoluteHelperAddress, cg()),748__FILE__, __LINE__, callNode);749cursor += sizeof(uintptr_t);750751// Store the code cache RA752*(uintptr_t *) cursor = (uintptr_t) getCallRA();753AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);754cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),755__FILE__, __LINE__, callNode);756cursor += sizeof(uintptr_t);757758// CP addr759*(uintptr_t *) cursor = (uintptr_t) callNode->getSymbolReference()->getOwningMethod(comp)->constantPool();760761// J2I relocation information for private nestmate calls762auto j2iRelocInfo = reinterpret_cast<TR_RelocationRecordInformation*>(comp->trMemory()->allocateMemory(sizeof(TR_RelocationRecordInformation), heapAlloc));763j2iRelocInfo->data1 = *(uintptr_t *) cursor; // CP address764j2iRelocInfo->data2 = (uintptr_t)(callNode ? callNode->getInlinedSiteIndex() : -1); // inlined site index765uintptr_t cpAddrPosition = (uintptr_t)cursor; // for data3 calculation766cursor += sizeof(uintptr_t);767768// save CPIndex as sign extended 8 byte value on 64bit as it's assumed in J9 helpers -- def#63837769*(uintptr_t *) cursor = (uintptr_t) callNode->getSymbolReference()->getCPIndexForVM();770cursor += TR::Compiler->om.sizeofReferenceAddress();771772// instruction to be patched773*(uintptr_t *) cursor = (uintptr_t) (getPatchVftInstruction()->getBinaryEncoding());774AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);775cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),776__FILE__, __LINE__, callNode);777cursor += sizeof(uintptr_t);778779// Field used by nestmate private calls780// J9Method pointer of the callee. Initialized to 0.781*(uintptr_t *) cursor = 0;782cursor += sizeof(uintptr_t);783784// Field used by nestmate private calls785// J2I thunk address786// No explicit call to `addExternalRelocation` because its relocation info is passed to CP_addr `addExternalRelocation` call.787*(uintptr_t *) cursor = (uintptr_t) thunkAddress;788j2iRelocInfo->data3 = (uintptr_t)cursor - cpAddrPosition; // data3 is the offset of CP_addr to J2I thunk789AOTcgDiag1(comp, "add TR_J2IVirtualThunkPointer cursor=%x\n", cursor);790cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation((uint8_t*)cpAddrPosition, (uint8_t*)j2iRelocInfo, NULL,791TR_J2IVirtualThunkPointer, cg()),792__FILE__, __LINE__, callNode);793cursor += sizeof(uintptr_t);794795// Field used by nestmate private calls796// For private functions, this is the return address.797// Add a 2 bytes off set because it's the instruction after the BASR, which is 2-byte long798// The assumption here is that S390 J9 private linkage indirect dispatch is emitting BASR.799TR_ASSERT_FATAL(getIndirectCallInstruction() && getIndirectCallInstruction()->getOpCodeValue() == TR::InstOpCode::BASR,800"Unexpected branch instruction in VirtualUnresolvedSnippet.\n");801802*(uintptr_t *) cursor = (uintptr_t) (getIndirectCallInstruction()->getBinaryEncoding() + getIndirectCallInstruction()->getBinaryLength());803AOTcgDiag1(comp, "add PrivateRA cursor=%x\n", cursor);804cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),805__FILE__, __LINE__, callNode);806807cursor += sizeof(uintptr_t);808809return cursor;810}811812uint32_t813TR::S390VirtualUnresolvedSnippet::getLength(int32_t estimatedSnippetStart)814{815TR::Compilation* comp = cg()->comp();816uint32_t length = getPICBinaryLength() + 7 * sizeof(uintptr_t) + TR::Compiler->om.sizeofReferenceAddress();817length += getRuntimeInstrumentationOnOffInstructionLength(cg());818return length;819}820821TR::S390InterfaceCallSnippet::S390InterfaceCallSnippet(822TR::CodeGenerator *cg,823TR::Node *c,824TR::LabelSymbol *lab,825int32_t s,826int8_t n,827void *thunkPtr,828bool useCLFIandBRCL)829: TR::S390VirtualSnippet(cg, c, lab, s),830_numInterfaceCallCacheSlots(n),831_useCLFIandBRCL(useCLFIandBRCL)832{833_dataSnippet = new (cg->trHeapMemory()) TR::J9S390InterfaceCallDataSnippet(cg,c,n,thunkPtr);834cg->addDataConstantSnippet(_dataSnippet);835}836837uint8_t *838TR::S390InterfaceCallSnippet::emitSnippetBody()839{840uint8_t * cursor = cg()->getBinaryBufferCursor();841getSnippetLabel()->setCodeLocation(cursor);842TR::Compilation *comp = cg()->comp();843TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());844845uint32_t rEP = (uint32_t) cg()->getEntryPointRegister() - 1;846TR::SymbolReference * glueRef ;847848if (getNumInterfaceCallCacheSlots() == 0)849{850glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interfaceCallHelper);851}852else if (comp->getOption(TR_enableInterfaceCallCachingSingleDynamicSlot))853{854glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interfaceCallHelperSingleDynamicSlot);855}856else857{858glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_S390interfaceCallHelperMultiSlots);859}860861// Set up the start of data constants and jump to helper.862// LARL r14, <Start of DC>863// BRCL <Helper Addr>864865// LARL - Add Relocation the data constants to this LARL.866cg()->addRelocation(new (cg()->trHeapMemory()) TR::LabelRelative32BitRelocation(cursor, getDataConstantSnippet()->getSnippetLabel()));867868*(int16_t *) cursor = 0xC0E0;869cursor += sizeof(int16_t);870871// Place holder. Proper offset will be calculated by relocation.872*(int32_t *) cursor = 0xDEADBEEF;873cursor += sizeof(int32_t);874875// BRCL876*(int16_t *) cursor = 0xC0F4;877cursor += sizeof(int16_t);878879// Calculate the relative offset to get to helper method.880// If MCC is not supported, everything should be reachable.881// If MCC is supported, we will look up the appropriate trampoline, if882// necessary.883intptr_t destAddr = (intptr_t)(glueRef->getMethodAddress());884885#if defined(TR_TARGET_64BIT)886#if defined(J9ZOS390)887if (comp->getOption(TR_EnableRMODE64))888#endif889{890if (NEEDS_TRAMPOLINE(destAddr, cursor, cg()))891{892// Destination is beyond our reachable jump distance, we'll find the893// trampoline.894destAddr = TR::CodeCacheManager::instance()->findHelperTrampoline(glueRef->getReferenceNumber(), (void *)cursor);895this->setUsedTrampoline(true);896}897}898#endif899900TR_ASSERT(CHECK_32BIT_TRAMPOLINE_RANGE(destAddr, cursor), "Helper Call is not reachable.");901this->setSnippetDestAddr(destAddr);902903*(int32_t *) cursor = (int32_t)((destAddr - (intptr_t)(cursor - 2)) / 2);904AOTcgDiag1(comp, " add TR_HelperAddress cursor=%x\n", cursor);905cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t*) glueRef, TR_HelperAddress, cg()),906__FILE__, __LINE__, getNode());907cursor += sizeof(int32_t);908909// Set up the code RA to the data snippet.910getDataConstantSnippet()->setCodeRA(getCallRA());911912return cursor;913}914915uint32_t916TR::S390InterfaceCallSnippet::getLength(int32_t estimatedSnippetStart)917{918return 12; // LARL + BRCL919}920921922923void924TR_Debug::print(TR::FILE *pOutFile, TR::S390UnresolvedCallSnippet * snippet)925{926uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation() + snippet->getLength(0)927- sizeof(intptr_t) - sizeof(int32_t) // 2 DC's at end of this snippet.928- (sizeof(intptr_t) - snippet->getPadBytes()); // padding929930TR::SymbolReference * methodSymRef = snippet->getNode()->getSymbolReference();931932int32_t helperLookupOffset;933switch (snippet->getNode()->getDataType())934{935case TR::NoType:936helperLookupOffset = 0;937break;938case TR::Int32:939case TR::Address:940helperLookupOffset = 4;941break;942case TR::Int64:943helperLookupOffset = 8;944break;945case TR::Float:946helperLookupOffset = 12;947break;948case TR::Double:949helperLookupOffset = 16;950break;951}952helperLookupOffset <<= 24;953954snippet->print(pOutFile, this);955956printPrefix(pOutFile, NULL, bufferPos, sizeof(uintptr_t));957trfprintf(pOutFile, "DC \t%p \t\t# Address Of Constant Pool", getOwningMethod(methodSymRef)->constantPool());958bufferPos += sizeof(uintptr_t);959960printPrefix(pOutFile, NULL, bufferPos, 4);961trfprintf(pOutFile, "DC \t0x%08x \t\t# Offset | Flag | CP Index", helperLookupOffset | methodSymRef->getCPIndexForVM());962}963964965void966TR_Debug::print(TR::FILE *pOutFile, TR::S390VirtualSnippet * snippet)967{968uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();969printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, "Virtual Call Snippet");970}971972973void974TR_Debug::print(TR::FILE *pOutFile, TR::S390VirtualUnresolvedSnippet * snippet)975{976uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();977TR::SymbolReference * methodSymRef = snippet->getNode()->getSymbolReference();978TR::SymbolReference * glueRef = _cg->getSymRef(TR_S390virtualUnresolvedHelper);979980printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, "Virtual Unresolved Call Snippet");981982bufferPos = printRuntimeInstrumentationOnOffInstruction(pOutFile, bufferPos, false); // RIOFF983984printPrefix(pOutFile, NULL, bufferPos, 6);985trfprintf(pOutFile, "BRASL \tGPR14, <%p>\t# Branch to Helper Method %s",986snippet->getSnippetDestAddr(),987snippet->usedTrampoline()?"- Trampoline Used.":"");988bufferPos += 6;989990printPrefix(pOutFile, NULL, bufferPos, 4);991trfprintf(pOutFile, "DC \t%p\t\t# Method Address", *((uintptr_t *)bufferPos));992bufferPos += sizeof(intptr_t);993994printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));995trfprintf(pOutFile, "DC \t%p \t\t# Call Site RA", snippet->getCallRA());996bufferPos += sizeof(intptr_t);997998printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));999trfprintf(pOutFile, "DC \t%p \t\t# Address Of Constant Pool", (intptr_t) getOwningMethod(methodSymRef)->constantPool());1000bufferPos += sizeof(intptr_t);10011002printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1003trfprintf(pOutFile, "DC \t0x%08x \t\t# CP Index", methodSymRef->getCPIndexForVM());1004bufferPos += sizeof(intptr_t);10051006printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1007trfprintf(pOutFile, "DC \t%p \t\t# Instruction to be patched with vft offset", snippet->getPatchVftInstruction()->getBinaryEncoding());1008bufferPos += sizeof(intptr_t);10091010printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1011trfprintf(pOutFile, "DC \t%p \t\t# Private J9Method pointer", 0);1012bufferPos += sizeof(intptr_t);10131014printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1015trfprintf(pOutFile, "DC \t%p \t\t# J2I thunk address for private", snippet->getJ2IThunkAddress());1016bufferPos += sizeof(intptr_t);10171018printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1019trfprintf(pOutFile, "DC \t%p \t\t# RA for private", snippet->getBranchInstruction()->getBinaryEncoding() + snippet->getIndirectCallInstruction()->getBinaryLength());1020}102110221023void1024TR_Debug::print(TR::FILE *pOutFile, TR::S390InterfaceCallSnippet * snippet)1025{1026uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();1027TR::SymbolReference * methodSymRef = snippet->getNode()->getSymbolReference();1028TR::SymbolReference * glueRef = _cg->getSymRef(TR_S390interfaceCallHelperMultiSlots);1029int i;10301031printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, "Interface Call Snippet");10321033printPrefix(pOutFile, NULL, bufferPos, 6);1034trfprintf(pOutFile, "LARL \tGPR14, <%p>\t# Addr of DataConst",1035(intptr_t) snippet->getDataConstantSnippet()->getSnippetLabel()->getCodeLocation());1036bufferPos += 6;10371038printPrefix(pOutFile, NULL, bufferPos, 6);1039trfprintf(pOutFile, "BRCL \t<%p>\t\t# Branch to Helper %s",1040snippet->getSnippetDestAddr(),1041snippet->usedTrampoline()?"- Trampoline Used.":"");1042bufferPos += 6;1043}10441045void1046TR_Debug::print(TR::FILE *pOutFile, TR::J9S390InterfaceCallDataSnippet * snippet)1047{1048uint8_t * bufferPos = snippet->getSnippetLabel()->getCodeLocation();10491050// This follows the snippet format in TR::J9S390InterfaceCallDataSnippet::emitSnippetBody1051uint8_t refSize = TR::Compiler->om.sizeofReferenceAddress();10521053printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, "Interface call cache data snippet");1054printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1055trfprintf(pOutFile, "DC \t0x%016lx # Call site RA", *(intptr_t*)bufferPos);1056bufferPos += refSize;10571058printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1059trfprintf(pOutFile, "DC \t0x%016lx # Address of constant pool", *(intptr_t*)bufferPos);1060bufferPos += refSize;10611062printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1063trfprintf(pOutFile, "DC \t0x%016lx # CP index", *(intptr_t*)bufferPos);1064bufferPos += refSize;10651066printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1067trfprintf(pOutFile, "DC \t0x%016lx # Interface class", *(intptr_t*)bufferPos);1068bufferPos += refSize;10691070printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1071trfprintf(pOutFile, "DC \t0x%016lx # Method index", *(intptr_t*)bufferPos);1072bufferPos += refSize;10731074printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1075trfprintf(pOutFile, "DC \t0x%016lx # J2I thunk address ", *(intptr_t*)bufferPos);1076bufferPos += refSize;10771078// zero cache slot1079if (snippet->getNumInterfaceCallCacheSlots() == 0)1080{1081printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1082trfprintf(pOutFile, "DC \t0x%016lx # flags", *(intptr_t*)bufferPos);1083bufferPos += refSize;1084}10851086// non-single cache slots1087bool isSingleDynamicSlot = comp()->getOption(TR_enableInterfaceCallCachingSingleDynamicSlot);1088if (!isSingleDynamicSlot)1089{1090// flags1091printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1092trfprintf(pOutFile, "DC \t0x%016lx # flags", *(intptr_t*)bufferPos);1093bufferPos += refSize;10941095// lastCachedSlot1096printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1097trfprintf(pOutFile, "DC \t0x%016lx # last cached slot", *(intptr_t*)bufferPos);1098bufferPos += refSize;10991100// firstSlot1101printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1102trfprintf(pOutFile, "DC \t0x%016lx # first slot", *(intptr_t*)bufferPos);1103bufferPos += refSize;11041105// lastSlot1106printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1107trfprintf(pOutFile, "DC \t0x%016lx # last slot", *(intptr_t*)bufferPos);1108bufferPos += refSize;1109}11101111// print profiled class list1112int32_t numInterfaceCallCacheSlots = snippet->getNumInterfaceCallCacheSlots();1113bool isUseCLFIandBRCL = snippet->isUseCLFIandBRCL();1114TR::list<TR_OpaqueClassBlock*> * profiledClassesList = comp()->cg()->getPICsListForInterfaceSnippet(snippet);11151116if (profiledClassesList)1117{1118for (auto iter = profiledClassesList->begin(); iter != profiledClassesList->end(); ++iter)1119{1120numInterfaceCallCacheSlots--;1121printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1122trfprintf(pOutFile, "DC \t0x%016lx # profiled class", *(intptr_t*)bufferPos);1123bufferPos += refSize;11241125printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1126trfprintf(pOutFile, "DC \t0x%016lx # profiled method", *(intptr_t*)bufferPos);1127bufferPos += refSize;1128}1129}11301131// print remaining class list1132for (uint32_t i = 0; i < numInterfaceCallCacheSlots; i++)1133{1134if (isUseCLFIandBRCL)1135{1136// address of CLFI's immediate field1137printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1138trfprintf(pOutFile, "DC \t0x%016lx # address of CLFI's immediate field", *(intptr_t*)bufferPos);1139bufferPos += refSize;1140}1141else1142{1143// class pointer1144printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1145trfprintf(pOutFile, "DC \t0x%016lx # class pointer %d", *(intptr_t*)bufferPos, i);1146bufferPos += refSize;11471148// method pointer1149printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1150trfprintf(pOutFile, "DC \t0x%016lx # method pointer %d", *(intptr_t*)bufferPos, i);1151bufferPos += refSize;1152}1153}11541155if (isSingleDynamicSlot)1156{1157// flags1158printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1159trfprintf(pOutFile, "DC \t0x%016lx # method pointer", *(intptr_t*)bufferPos);1160bufferPos += refSize;1161}1162return;1163}11641165///////////////////////////////////////////////////////////////////////////////1166// TR::J9S390InterfaceCallDataSnippet member functions1167///////////////////////////////////////////////////////////////////////////////1168TR::J9S390InterfaceCallDataSnippet::J9S390InterfaceCallDataSnippet(TR::CodeGenerator * cg,1169TR::Node * node,1170uint8_t n,1171void *thunkPtr,1172bool useCLFIandBRCL)1173: TR::S390ConstantDataSnippet(cg,node,generateLabelSymbol(cg),0),1174_numInterfaceCallCacheSlots(n),1175_codeRA(NULL),1176_thunkAddress(thunkPtr),1177_useCLFIandBRCL(useCLFIandBRCL)1178{1179}11801181/**1182* \brief1183* Emits interface call data snippet, which can take three layouts: 0-slot, single-dynamic-slot, and 4-slot layouts.1184* The default layout has 4-slots.1185*/1186uint8_t *1187TR::J9S390InterfaceCallDataSnippet::emitSnippetBody()1188{11891190/*1191* 4-slot Layout (example showing 64-bit fields). 4-slot is the default case.1192*1193* Note: some fields and PIC slots will be unused if interface call turns out to be a direct dispatch.1194*1195* Snippet Label L0049: ; Interface call cache data snippet1196* DC 0x0000000084e00244 # Call site RA1197* DC 0x0000000000202990 # Address of constant pool1198* DC 0x0000000000000008 # CP index1199* DC 0x0000000000000000 # Interface class (vm helper will fill it up with call resolution class info)1200* DC 0x0000000000000000 # Method index (vm helper will fill it up with call resolution method info. This contains1201* J9method if it's direct dispatch. It's I-table offset if it's a normal interface call)1202* DC 0x0000000084ffd408 # J2I thunk (J2I thunk address)1203* DC 0x0000000000000000 # flags (this 64-bit number is initially 0, meaning the call is unresolved. It'll be 1 once resolved)1204* DC 0x0000000084e00408 # last cached slot1205* DC 0x0000000084e00418 # first slot (address of class pointer 0)1206* DC 0x0000000084e00448 # last slot (address of class pointer 3)1207* DC 0x0000000000000000 # class pointer 0 (8 or 16 byte aligned PIC slots. all PICs starting from this point are1208* un-used if the call is resolved as private, which is direct dispatch)1209* DC 0x0000000000000000 # method pointer 01210* DC 0x0000000000000000 # class pointer 11211* DC 0x0000000000000000 # method pointer 11212* DC 0x0000000000000000 # class pointer 21213* DC 0x0000000000000000 # method pointer 21214* DC 0x0000000000000000 # class pointer 31215* DC 0x0000000000000000 # method pointer 31216*1217* If we use CLFI / BRCL1218* DC 0x0000000000000000 ; Patch slot of the first CLFI (Class 1)1219* DC 0x0000000000000000 ; Patch slot of the second CLFI (Class 2)1220* DC 0x0000000000000000 ; Patch slot of the third CLFI (Class 3)1221* and so on ...1222*1223*1224* Single dynamic slot layout1225*1226* Snippet Label L0049: ; Interface call cache data snippet1227* DC 0x00000000529941ca # Call site RA1228* DC 0x0000000000202990 # Address of constant pool1229* DC 0x0000000000000008 # CP index1230* DC 0x0000000000000000 # Interface class1231* DC 0x0000000000000000 # Method index1232* DC 0x0000000052b91408 # J2I thunk1233* DC 0x0000000000000000 # class pointer 01234* DC 0x0000000000000000 # method pointer 01235* DC 0x0000000000000000 # flags1236*1237*1238* 0-slot example1239*1240* Snippet Label L0041: ; Interface call cache data snippet1241* DC 0x0000000065a7f156 # Call site RA1242* DC 0x0000000000202990 # Address of constant pool1243* DC 0x000000000000000e # CP index1244* DC 0x0000000000000000 # Interface class1245* DC 0x0000000000000000 # Method index1246* DC 0x0000000065c7c408 # Interpreter thunk1247* DC 0x0000000000000000 # flags1248*/1249TR::Compilation *comp = cg()->comp();1250int32_t i = 0;1251uint8_t * cursor = cg()->getBinaryBufferCursor();1252AOTcgDiag1(comp, "TR::S390InterfaceCallDataSnippet::emitSnippetBody cursor=%x\n", cursor);12531254// Class Pointer must be double word aligned.1255// For 64-bit single dynamic slot, LPQ and STPQ instructions will be emitted; and they require quadword alignment1256int32_t alignment = comp->getOption(TR_enableInterfaceCallCachingSingleDynamicSlot) ? 16 : 8;1257intptr_t startOfPIC = (intptr_t)cursor + 6 * sizeof(intptr_t);1258int32_t padSize = 0;12591260if ((startOfPIC % alignment) != 0)1261{1262padSize = (alignment - (startOfPIC % alignment));1263}12641265cursor += padSize;12661267getSnippetLabel()->setCodeLocation(cursor);1268TR::Node * callNode = getNode();126912701271intptr_t snippetStart = (intptr_t)cursor;12721273// code cache RA1274TR_ASSERT_FATAL(_codeRA != NULL, "Interface Call Data Constant's code return address not initialized.\n");1275*(uintptr_t *) cursor = (uintptr_t)_codeRA;1276AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);1277cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),1278__FILE__, __LINE__, callNode);12791280cursor += TR::Compiler->om.sizeofReferenceAddress();12811282// constant pool1283*(uintptr_t *) cursor = (uintptr_t) callNode->getSymbolReference()->getOwningMethod(comp)->constantPool();12841285// J2I relocation information for private nestmate calls1286auto j2iRelocInfo = reinterpret_cast<TR_RelocationRecordInformation*>(comp->trMemory()->allocateMemory(sizeof(TR_RelocationRecordInformation), heapAlloc));1287j2iRelocInfo->data1 = *(uintptr_t *) cursor; // CP address1288j2iRelocInfo->data2 = (uintptr_t)(callNode ? callNode->getInlinedSiteIndex() : -1); // inlined site index1289uintptr_t cpAddrPosition = (uintptr_t)cursor; // for data3 calculation12901291cursor += TR::Compiler->om.sizeofReferenceAddress();12921293// save CPIndex as sign extended 8 byte value on 64bit as it's assumed in J9 helpers1294// cp index1295*(intptr_t *) cursor = (intptr_t) callNode->getSymbolReference()->getCPIndex();1296cursor += TR::Compiler->om.sizeofReferenceAddress();12971298//interface class1299*(uintptr_t *) cursor = 0;1300cursor += TR::Compiler->om.sizeofReferenceAddress();13011302// method index1303*(intptr_t *) cursor = 0;1304cursor += TR::Compiler->om.sizeofReferenceAddress();13051306// J2I thunk address.1307// Note that J2I thunk relocation is associated with CP addr and the call to `addExternalRelocation` uses CP-Addr cursor.1308*(intptr_t *) cursor = (intptr_t)_thunkAddress;1309j2iRelocInfo->data3 = (uintptr_t)cursor - cpAddrPosition; // data3 is the offset of CP_addr to J2I thunk13101311AOTcgDiag1(comp, "add TR_J2IVirtualThunkPointer cursor=%x\n", cursor);1312cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation((uint8_t*)cpAddrPosition, (uint8_t*)j2iRelocInfo, NULL,1313TR_J2IVirtualThunkPointer, cg()),1314__FILE__, __LINE__, callNode);13151316cursor += TR::Compiler->om.sizeofReferenceAddress();13171318if (getNumInterfaceCallCacheSlots() == 0)1319{1320// Flags1321*(intptr_t *) (cursor) = 0;1322cursor += TR::Compiler->om.sizeofReferenceAddress();1323return cursor;1324}1325uint8_t * cursorlastCachedSlot = 0;1326bool isSingleDynamic = comp->getOption(TR_enableInterfaceCallCachingSingleDynamicSlot);13271328if (!isSingleDynamic)1329{1330// Flags1331*(intptr_t *) (cursor) = 0;1332cursor += TR::Compiler->om.sizeofReferenceAddress();13331334// lastCachedSlot1335cursorlastCachedSlot = cursor;1336*(intptr_t *) (cursor) = snippetStart + getFirstSlotOffset() - (2 * TR::Compiler->om.sizeofReferenceAddress());1337AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);1338cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),1339__FILE__, __LINE__, callNode);13401341cursor += TR::Compiler->om.sizeofReferenceAddress();13421343// firstSlot1344*(intptr_t *) (cursor) = snippetStart + getFirstSlotOffset();1345AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);1346cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),1347__FILE__, __LINE__, callNode);1348cursor += TR::Compiler->om.sizeofReferenceAddress();13491350// lastSlot1351*(intptr_t *) (cursor) = snippetStart + getLastSlotOffset();1352AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);1353cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),1354__FILE__, __LINE__, callNode);1355cursor += TR::Compiler->om.sizeofReferenceAddress();1356}13571358// Cursor must be double word aligned by this point1359// so that 64-bit single dynamic slot can use LPQ to concurrently load a quadword.1360TR_ASSERT_FATAL( (!isSingleDynamic && (intptr_t)cursor % 8 == 0)1361|| (comp->target().is64Bit() && isSingleDynamic && (intptr_t)cursor % 16 == 0),1362"Interface Call Data Snippet Class Ptr is not double word aligned.");13631364bool updateField = false;1365int32_t numInterfaceCallCacheSlots = getNumInterfaceCallCacheSlots();1366TR::list<TR_OpaqueClassBlock*> * profiledClassesList = cg()->getPICsListForInterfaceSnippet(this);1367if (profiledClassesList)1368{1369for (auto valuesIt = profiledClassesList->begin(); valuesIt != profiledClassesList->end(); ++valuesIt)1370{1371TR::SymbolReference *methodSymRef = callNode->getSymbolReference();1372TR_ResolvedMethod * profiledMethod = methodSymRef->getOwningMethod(comp)->getResolvedInterfaceMethod(comp,1373(TR_OpaqueClassBlock *)(*valuesIt), methodSymRef->getCPIndex());1374numInterfaceCallCacheSlots--;1375updateField = true;1376if (comp->target().is64Bit() && TR::Compiler->om.generateCompressedObjectHeaders())1377*(uintptr_t *) cursor = (uintptr_t) (*valuesIt) << 32;1378else1379*(uintptr_t *) cursor = (uintptr_t) (*valuesIt);13801381if (comp->getOption(TR_EnableHCR))1382{1383cg()->jitAddPicToPatchOnClassRedefinition(*valuesIt, (void *) cursor);1384}13851386if (cg()->fe()->isUnloadAssumptionRequired((TR_OpaqueClassBlock *)(*valuesIt), comp->getCurrentMethod()))1387{1388cg()->jitAddPicToPatchOnClassUnload(*valuesIt, (void *) cursor);1389}13901391cursor += TR::Compiler->om.sizeofReferenceAddress();13921393// Method Pointer1394*(uintptr_t *) (cursor) = (uintptr_t)profiledMethod->startAddressForJittedMethod();1395cursor += TR::Compiler->om.sizeofReferenceAddress();1396}13971398}13991400// Skip the top cache slots that are filled with IProfiler data by setting the cursorlastCachedSlot to point to the fist dynamic cache slot1401if (updateField)1402{1403*(intptr_t *) (cursorlastCachedSlot) = snippetStart + getFirstSlotOffset() + ((getNumInterfaceCallCacheSlots()-numInterfaceCallCacheSlots-1)*2 * TR::Compiler->om.sizeofReferenceAddress());1404}14051406for (i = 0; i < numInterfaceCallCacheSlots; i++)1407{1408if (isUseCLFIandBRCL())1409{1410// Get Address of CLFI's immediate field (2 bytes into CLFI instruction).1411// jitAddPicToPatchOnClassUnload is called by PicBuilder code when the cache is populated.1412*(intptr_t*) cursor = (intptr_t)(getFirstCLFI()->getBinaryEncoding() ) + (intptr_t)(i * 12 + 2);1413cursor += TR::Compiler->om.sizeofReferenceAddress();1414}1415else1416{1417// Class Pointer - jitAddPicToPatchOnClassUnload is called by PicBuilder code when the cache is populated.1418*(intptr_t *) cursor = 0;1419cursor += TR::Compiler->om.sizeofReferenceAddress();14201421// Method Pointer1422*(intptr_t *) (cursor) = 0;1423cursor += TR::Compiler->om.sizeofReferenceAddress();1424}1425}14261427if (isSingleDynamic)1428{1429// Flags1430*(intptr_t *) (cursor) = 0;1431cursor += TR::Compiler->om.sizeofReferenceAddress();1432}14331434return cursor;1435}143614371438uint32_t1439TR::J9S390InterfaceCallDataSnippet::getCallReturnAddressOffset()1440{1441return 0;1442}14431444uint32_t1445TR::J9S390InterfaceCallDataSnippet::getSingleDynamicSlotOffset()1446{1447return getCallReturnAddressOffset() + 6 * TR::Compiler->om.sizeofReferenceAddress();1448}14491450uint32_t1451TR::J9S390InterfaceCallDataSnippet::getLastCachedSlotFieldOffset()1452{1453return getCallReturnAddressOffset() + 7 * TR::Compiler->om.sizeofReferenceAddress();1454}14551456uint32_t1457TR::J9S390InterfaceCallDataSnippet::getFirstSlotFieldOffset()1458{1459return getLastCachedSlotFieldOffset() + TR::Compiler->om.sizeofReferenceAddress();1460}14611462uint32_t1463TR::J9S390InterfaceCallDataSnippet::getLastSlotFieldOffset()1464{1465return getFirstSlotFieldOffset() + TR::Compiler->om.sizeofReferenceAddress();1466}14671468uint32_t1469TR::J9S390InterfaceCallDataSnippet::getFirstSlotOffset()1470{1471return getLastSlotFieldOffset() + TR::Compiler->om.sizeofReferenceAddress();1472}14731474uint32_t1475TR::J9S390InterfaceCallDataSnippet::getLastSlotOffset()1476{1477return (getFirstSlotOffset() +1478(getNumInterfaceCallCacheSlots() - 1) *1479((isUseCLFIandBRCL()?1:2) * TR::Compiler->om.sizeofReferenceAddress()));1480}14811482uint32_t1483TR::J9S390InterfaceCallDataSnippet::getLength(int32_t)1484{1485TR::Compilation *comp = cg()->comp();1486// the 1st item is for padding...1487if (getNumInterfaceCallCacheSlots()== 0)1488return 3 * TR::Compiler->om.sizeofReferenceAddress() + 8 * TR::Compiler->om.sizeofReferenceAddress();14891490if (comp->getOption(TR_enableInterfaceCallCachingSingleDynamicSlot))1491return 3 * TR::Compiler->om.sizeofReferenceAddress() + getSingleDynamicSlotOffset() + 4 * TR::Compiler->om.sizeofReferenceAddress();14921493if (getNumInterfaceCallCacheSlots() > 0)1494return 3 * TR::Compiler->om.sizeofReferenceAddress() + getLastSlotOffset() + TR::Compiler->om.sizeofReferenceAddress();14951496TR_ASSERT(0,"Interface Call Data Snippet has 0 size.");1497return 0;1498}149915001501uint32_t1502TR::S390JNICallDataSnippet::getJNICallOutFrameFlagsOffset()1503{1504return TR::Compiler->om.sizeofReferenceAddress();1505}15061507uint32_t1508TR::S390JNICallDataSnippet::getReturnFromJNICallOffset()1509{1510return 2 * TR::Compiler->om.sizeofReferenceAddress();1511}15121513uint32_t1514TR::S390JNICallDataSnippet::getSavedPCOffset()1515{1516return 3 * TR::Compiler->om.sizeofReferenceAddress();1517}15181519uint32_t1520TR::S390JNICallDataSnippet::getTagBitsOffset()1521{1522return 4 * TR::Compiler->om.sizeofReferenceAddress();1523}15241525uint32_t1526TR::S390JNICallDataSnippet::getPCOffset()1527{1528return 5 * TR::Compiler->om.sizeofReferenceAddress();1529}15301531uint32_t1532TR::S390JNICallDataSnippet::getLiteralsOffset()1533{1534return 6 * TR::Compiler->om.sizeofReferenceAddress();1535}15361537uint32_t1538TR::S390JNICallDataSnippet::getJitStackFrameFlagsOffset()1539{1540return 7 * TR::Compiler->om.sizeofReferenceAddress();1541}15421543uint32_t1544TR::S390JNICallDataSnippet::getConstReleaseVMAccessMaskOffset()1545{1546return 8 * TR::Compiler->om.sizeofReferenceAddress();1547}15481549uint32_t1550TR::S390JNICallDataSnippet::getConstReleaseVMAccessOutOfLineMaskOffset()1551{1552return 9 * TR::Compiler->om.sizeofReferenceAddress();1553}15541555uint32_t1556TR::S390JNICallDataSnippet::getTargetAddressOffset()1557{1558return 10 * TR::Compiler->om.sizeofReferenceAddress();1559}15601561uint32_t1562TR::S390JNICallDataSnippet::getLength(int32_t estimatedSnippetStart)1563{1564return 12 * TR::Compiler->om.sizeofReferenceAddress(); /*one ptr more for possible padding */1565}156615671568TR::S390JNICallDataSnippet::S390JNICallDataSnippet(TR::CodeGenerator * cg,1569TR::Node * node)1570: TR::S390ConstantDataSnippet(cg, node, generateLabelSymbol(cg),0),1571_baseRegister(0),1572_ramMethod(0),1573_JNICallOutFrameFlags(0),1574_returnFromJNICallLabel(0),1575_savedPC(0),1576_tagBits(0),1577_pc(0),1578_literals(0),1579_jitStackFrameFlags(0),1580_constReleaseVMAccessMask(0),1581_constReleaseVMAccessOutOfLineMask(0),1582_targetAddress(0)1583{1584return;1585}15861587uint8_t *1588TR::S390JNICallDataSnippet::emitSnippetBody()1589{1590uint8_t * cursor = cg()->getBinaryBufferCursor();15911592/* TR::S390JNICallDataSnippet Layout: all fields are pointer sized1593ramMethod1594JNICallOutFrameFlags1595returnFromJNICall1596savedPC1597tagBits1598pc1599literals1600jitStackFrameFlags1601constReleaseVMAccessMask1602constReleaseVMAccessOutOfLineMask1603targetAddress1604*/1605TR::Compilation *comp = cg()->comp();16061607AOTcgDiag1(comp, "TR::S390JNICallDataSnippet::emitSnippetBody cursor=%x\n", cursor);1608// Ensure pointer sized alignment1609int32_t alignSize = TR::Compiler->om.sizeofReferenceAddress();1610int32_t padBytes = ((intptr_t)cursor + alignSize -1) / alignSize * alignSize - (intptr_t)cursor;1611cursor += padBytes;16121613getSnippetLabel()->setCodeLocation(cursor);1614TR::Node * callNode = getNode();16151616intptr_t snippetStart = (intptr_t)cursor;16171618// JNI Callout Frame data1619// _ramMethod1620*(intptr_t *) cursor = (intptr_t) _ramMethod;16211622TR_ExternalRelocationTargetKind reloType;1623if (getNode()->getSymbol()->castToResolvedMethodSymbol()->isSpecial())1624reloType = TR_SpecialRamMethodConst;1625else if (getNode()->getSymbol()->castToResolvedMethodSymbol()->isStatic())1626reloType = TR_StaticRamMethodConst;1627else if (getNode()->getSymbol()->castToResolvedMethodSymbol()->isVirtual())1628reloType = TR_VirtualRamMethodConst;1629else1630{1631reloType = TR_NoRelocation;1632TR_ASSERT(0,"JNI relocation not supported.");1633}16341635AOTcgDiag2(comp, "add relocation (%d) cursor=%x\n", reloType, cursor);1636if (cg()->needClassAndMethodPointerRelocations())1637{1638cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, (uint8_t *) callNode->getSymbolReference(),1639callNode ? (uint8_t *)(intptr_t)callNode->getInlinedSiteIndex() : (uint8_t *)-1,1640reloType, cg()),1641__FILE__, __LINE__, callNode);1642}16431644cursor += TR::Compiler->om.sizeofReferenceAddress();16451646// _JNICallOutFrameFlags1647*(intptr_t *) cursor = (intptr_t) _JNICallOutFrameFlags;1648cursor += TR::Compiler->om.sizeofReferenceAddress();1649// _returnFromJNICall1650*(intptr_t *) cursor = (intptr_t) (_returnFromJNICallLabel->getCodeLocation());16511652AOTcgDiag1(comp, "add TR_AbsoluteMethodAddress cursor=%x\n", cursor);1653cg()->addRelocation(new (cg()->trHeapMemory()) TR::LabelAbsoluteRelocation(cursor, _returnFromJNICallLabel));1654cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, NULL, TR_AbsoluteMethodAddress, cg()),1655__FILE__, __LINE__, getNode());16561657cursor += TR::Compiler->om.sizeofReferenceAddress();1658// _savedPC1659*(intptr_t *) cursor = (intptr_t) _savedPC;1660cursor += TR::Compiler->om.sizeofReferenceAddress();1661// _tagBits1662*(intptr_t *) cursor = (intptr_t) _tagBits;1663cursor += TR::Compiler->om.sizeofReferenceAddress();16641665//VMThread data1666// _pc1667*(intptr_t *) cursor = (intptr_t) _pc;1668cursor += TR::Compiler->om.sizeofReferenceAddress();1669// _literals1670*(intptr_t *) cursor = (intptr_t) _literals;1671cursor += TR::Compiler->om.sizeofReferenceAddress();1672// _jitStackFrameFlags1673*(intptr_t *) cursor = (intptr_t) _jitStackFrameFlags;1674cursor += TR::Compiler->om.sizeofReferenceAddress();16751676// _constReleaseVMAccessMask1677*(intptr_t *) cursor = (intptr_t) _constReleaseVMAccessMask;1678cursor += TR::Compiler->om.sizeofReferenceAddress();1679// _constReleaseVMAccessOutOfLineMask1680*(intptr_t *) cursor = (intptr_t) _constReleaseVMAccessOutOfLineMask;1681cursor += TR::Compiler->om.sizeofReferenceAddress();16821683// _targetAddress/function pointer of native method1684*(intptr_t *) cursor = (intptr_t) _targetAddress;1685TR_OpaqueMethodBlock *method = getNode()->getSymbol()->castToResolvedMethodSymbol()->getResolvedMethod()->getPersistentIdentifier();16861687#ifdef J9VM_OPT_JITSERVER1688if (comp->isOutOfProcessCompilation())1689{1690// For JITServer we need to build a list of assumptions that will be sent to client at end of compilation1691intptr_t offset = cursor - cg()->getBinaryBufferStart();1692SerializedRuntimeAssumption* sar = new (cg()->trHeapMemory()) SerializedRuntimeAssumption(RuntimeAssumptionOnRegisterNative, (uintptr_t)method, offset);1693comp->getSerializedRuntimeAssumptions().push_front(sar);1694}1695else1696#endif // J9VM_OPT_JITSERVER1697{1698TR_PatchJNICallSite::make(cg()->fe(), cg()->trPersistentMemory(), (uintptr_t) method, cursor, comp->getMetadataAssumptionList());1699}17001701if (getNode()->getSymbol()->castToResolvedMethodSymbol()->isSpecial())1702reloType = TR_JNISpecialTargetAddress;1703else if (getNode()->getSymbol()->castToResolvedMethodSymbol()->isStatic())1704reloType = TR_JNIStaticTargetAddress;1705else if (getNode()->getSymbol()->castToResolvedMethodSymbol()->isVirtual())1706reloType = TR_JNIVirtualTargetAddress;1707else1708{1709reloType = TR_NoRelocation;1710TR_ASSERT(0,"JNI relocation not supported.");1711}17121713if (cg()->needClassAndMethodPointerRelocations())1714{1715TR_RelocationRecordInformation *info = new (comp->trHeapMemory()) TR_RelocationRecordInformation();1716info->data1 = 0;1717info->data2 = reinterpret_cast<uintptr_t>(callNode->getSymbolReference());1718int16_t inlinedSiteIndex = callNode ? callNode->getInlinedSiteIndex() : -1;1719info->data3 = static_cast<uintptr_t>(inlinedSiteIndex);17201721cg()->addExternalRelocation(1722new (cg()->trHeapMemory()) TR::ExternalRelocation(1723cursor,1724reinterpret_cast<uint8_t *>(info),1725reloType,1726cg()),1727__FILE__, __LINE__, callNode);1728}17291730cursor += TR::Compiler->om.sizeofReferenceAddress();17311732return cursor;1733}17341735void1736TR::S390JNICallDataSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)1737{1738/*1739ramMethod1740JNICallOutFrameFlags1741returnFromJNICall1742savedPC1743tagBits1744pc1745literals1746jitStackFrameFlags1747constReleaseVMAccessMask1748constReleaseVMAccessOutOfLineMask1749targetAddress17501751*/1752TR_FrontEnd *fe = cg()->comp()->fe();1753uint8_t * bufferPos = getSnippetLabel()->getCodeLocation();17541755int i = 0;17561757debug->printSnippetLabel(pOutFile, getSnippetLabel(), bufferPos, "JNI Call Data Snippet");17581759debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1760trfprintf(pOutFile, "DC \t%p \t\t# ramMethod",*((intptr_t*)bufferPos));1761bufferPos += sizeof(intptr_t);17621763debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1764trfprintf(pOutFile, "DC \t%p \t\t# JNICallOutFrameFlags",*((intptr_t*)bufferPos));1765bufferPos += sizeof(intptr_t);17661767debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1768trfprintf(pOutFile, "DC \t%p \t\t# returnFromJNICall", *((intptr_t*)bufferPos));1769bufferPos += sizeof(intptr_t);17701771debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1772trfprintf(pOutFile, "DC \t%p \t\t# savedPC", *((intptr_t*)bufferPos));1773bufferPos += sizeof(intptr_t);17741775debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1776trfprintf(pOutFile, "DC \t%p \t\t# tagBits", *((intptr_t*)bufferPos));1777bufferPos += sizeof(intptr_t);17781779debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1780trfprintf(pOutFile, "DC \t%p \t\t# pc", *((intptr_t*)bufferPos));1781bufferPos += sizeof(intptr_t);17821783debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1784trfprintf(pOutFile, "DC \t%p \t\t# literals", *((intptr_t*)bufferPos));1785bufferPos += sizeof(intptr_t);17861787debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1788trfprintf(pOutFile, "DC \t%p \t\t# jitStackFrameFlags", *((intptr_t*)bufferPos));1789bufferPos += sizeof(intptr_t);17901791debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1792trfprintf(pOutFile, "DC \t%p \t\t# constReleaseVMAccessMask",*((intptr_t*)bufferPos));1793bufferPos += sizeof(intptr_t);17941795debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1796trfprintf(pOutFile, "DC \t%p \t\t# constReleaseVMAccessOutOfLineMask",*((intptr_t*)bufferPos));1797bufferPos += sizeof(intptr_t);17981799debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(intptr_t));1800trfprintf(pOutFile, "DC \t%p \t\t# targetAddress",*((intptr_t*)bufferPos));1801bufferPos += sizeof(intptr_t);1802}180318041805