Path: blob/master/runtime/compiler/x/codegen/J9UnresolvedDataSnippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 2021 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 "codegen/UnresolvedDataSnippet.hpp"23#include "codegen/UnresolvedDataSnippet_inlines.hpp"2425#include <algorithm>26#include "codegen/CodeGenerator.hpp"27#include "codegen/Instruction.hpp"28#include "compile/SymbolReferenceTable.hpp"29#include "env/CompilerEnv.hpp"30#include "env/IO.hpp"31#include "env/TRMemory.hpp"32#include "env/jittypes.h"33#include "env/VMJ9.h"34#include "il/Node.hpp"35#include "il/Node_inlines.hpp"36#include "il/StaticSymbol.hpp"37#include "il/StaticSymbol_inlines.hpp"38#include "il/Symbol.hpp"39#include "runtime/CodeCacheManager.hpp"40#include "runtime/J9Runtime.hpp"41#include "x/codegen/X86Instruction.hpp"42#include "codegen/InstOpCode.hpp"4344J9::X86::UnresolvedDataSnippet::UnresolvedDataSnippet(45TR::CodeGenerator *cg,46TR::Node *node,47TR::SymbolReference *symRef,48bool isStore,49bool isGCSafePoint) :50J9::UnresolvedDataSnippet(cg, node, symRef, isStore, isGCSafePoint),51_numLiveX87Registers(0),52_glueSymRef(NULL)53{54TR_ASSERT(symRef->getSymbol(), "symbol should not be NULL");5556if (symRef->getSymbol()->getDataType()==TR::Float ||57symRef->getSymbol()->getDataType()==TR::Double)58{59setIsFloatData();60}61}626364TR_RuntimeHelper65J9::X86::UnresolvedDataSnippet::getHelper()66{67if (getDataSymbol()->isShadow())68return isUnresolvedStore() ? TR_X86interpreterUnresolvedFieldSetterGlue :69TR_X86interpreterUnresolvedFieldGlue;7071if (getDataSymbol()->isClassObject())72return getDataSymbol()->addressIsCPIndexOfStatic() ? TR_X86interpreterUnresolvedClassFromStaticFieldGlue :73TR_X86interpreterUnresolvedClassGlue;7475if (getDataSymbol()->isConstString())76return TR_X86interpreterUnresolvedStringGlue;7778if (getDataSymbol()->isConstMethodType())79return TR_interpreterUnresolvedMethodTypeGlue;8081if (getDataSymbol()->isConstMethodHandle())82return TR_interpreterUnresolvedMethodHandleGlue;8384if (getDataSymbol()->isCallSiteTableEntry())85return TR_interpreterUnresolvedCallSiteTableEntryGlue;8687if (getDataSymbol()->isMethodTypeTableEntry())88return TR_interpreterUnresolvedMethodTypeTableEntryGlue;8990if (getDataSymbol()->isConstantDynamic())91return TR_X86interpreterUnresolvedConstantDynamicGlue;9293// Must be a static data reference9495return isUnresolvedStore() ? TR_X86interpreterUnresolvedStaticFieldSetterGlue :96TR_X86interpreterUnresolvedStaticFieldGlue;97}9899100uint8_t *101J9::X86::UnresolvedDataSnippet::emitSnippetBody()102{103uint8_t *cursor = cg()->getBinaryBufferCursor();104105uint8_t *snippetStart = cursor;106getSnippetLabel()->setCodeLocation(snippetStart);107TR::Instruction *stackMapInstr = getDataReferenceInstruction();108109if (!stackMapInstr)110{111return TR::InstOpCode(TR::InstOpCode::bad).binary(cursor);112}113114_glueSymRef = cg()->symRefTab()->findOrCreateRuntimeHelper(getHelper());115116if (cg()->comp()->target().is64Bit())117{118cursor = emitResolveHelperCall(cursor);119cursor = emitConstantPoolAddress(cursor);120cursor = emitConstantPoolIndex(cursor);121cursor = emitUnresolvedInstructionDescriptor(cursor);122}123else124{125cursor = emitConstantPoolIndex(cursor);126cursor = emitConstantPoolAddress(cursor);127cursor = emitResolveHelperCall(cursor);128cursor = emitUnresolvedInstructionDescriptor(cursor);129}130131cursor = fixupDataReferenceInstruction(cursor);132133// If there is a GC map for this snippet, register it at the point that this134// snippet is called.135//136gcMap().registerStackMap(stackMapInstr, cg());137138return cursor;139}140141142143uint8_t *144J9::X86::UnresolvedDataSnippet::emitResolveHelperCall(uint8_t *cursor)145{146// Get the address for the glue routine (or its trampoline)147//148intptr_t glueAddress = (intptr_t)_glueSymRef->getMethodAddress();149150cg()->addProjectSpecializedRelocation(cursor+1, (uint8_t *)_glueSymRef, NULL, TR_HelperAddress,151__FILE__, __LINE__, getNode());152153// Call to the glue routine154//155const intptr_t rip = (intptr_t)(cursor+5);156if ((cg()->needRelocationsForHelpers() && cg()->comp()->target().is64Bit()) ||157NEEDS_TRAMPOLINE(glueAddress, rip, cg()))158{159TR_ASSERT(cg()->comp()->target().is64Bit(), "should not require a trampoline on 32-bit");160glueAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(_glueSymRef->getReferenceNumber(), (void *)cursor);161TR_ASSERT(IS_32BIT_RIP(glueAddress, rip), "Local helper trampoline should be reachable directly.\n");162}163164*cursor++ = 0xe8; // TR::InstOpCode::CALLImm4165166int32_t offset = (int32_t)((intptr_t)glueAddress - rip);167*(int32_t *)cursor = offset;168cursor += 4;169170TR_ASSERT((intptr_t)cursor == rip, "assertion failure");171172return cursor;173}174175176uint32_t177J9::X86::UnresolvedDataSnippet::getUnresolvedStaticStoreDeltaWithMemBarrier()178{179// If the this is not a store operation on an unresolved static field, return.180//181if (getDataSymbol()->isClassObject() || getDataSymbol()->isConstObjectRef())182{183return 0;184}185186// Find the delta between the start of the memory barrier that should be guarding the store to the static field, and the start of the store instruction187//188TR::Instruction *instIter = getDataReferenceInstruction();189uint8_t *dataRefInstOffset = getDataReferenceInstruction()->getBinaryEncoding();190191instIter = instIter->getNext();192uint8_t delta = instIter->getBinaryEncoding() - dataRefInstOffset;193194if (cg()->comp()->getOption(TR_X86UseMFENCE))195{196while ( instIter->getOpCode().getOpCodeValue() != TR::InstOpCode::MFENCE && delta <= 20)197{198instIter = instIter->getNext();199delta = instIter->getBinaryEncoding() - dataRefInstOffset;200}201202// Return the appropriate offset flag.203//204if (delta == 20 && instIter->getOpCode().getOpCodeValue() == TR::InstOpCode::MFENCE)205{206return cpIndex_extremeStaticMemBarPos;207}208else if (delta == 16 && instIter->getOpCode().getOpCodeValue() == TR::InstOpCode::MFENCE)209{210return cpIndex_genStaticMemBarPos;211}212else213{214TR_ASSERT(0, "Invalid computed offset between start of store to static field and start of memory barrier: %d. Should be 16 or 20.", delta);215return 0;216}217}218else219{220while ( instIter->getOpCode().getOpCodeValue() != TR::InstOpCode::LOR4MemImms && delta <= 24)221{222instIter = instIter->getNext();223delta = instIter->getBinaryEncoding() - dataRefInstOffset;224}225226// Return the appropriate offset flag.227//228if (delta == 24 && instIter->getOpCode().getOpCodeValue() == TR::InstOpCode::LOR4MemImms)229{230return cpIndex_extremeStaticMemBarPos;231}232else if (delta == 16 && instIter->getOpCode().getOpCodeValue() == TR::InstOpCode::LOR4MemImms)233{234return cpIndex_genStaticMemBarPos;235}236else237{238TR_ASSERT(0, "Invalid computed offset between start of store to static field and start of memory barrier: %d. Should be 16 or 24.", delta);239return 0;240}241}242}243244245uint8_t *246J9::X86::UnresolvedDataSnippet::emitUnresolvedInstructionDescriptor(uint8_t *cursor)247{248// On 64-bit a descriptor byte is only required for unresolved fields because249// the 4-byte disp32 field250//251if (cg()->comp()->target().is64Bit() && !getDataSymbol()->isShadow())252return cursor;253254// Descriptor255// Bits:256// 7-4: template instruction length257// 3-0: offset of data reference from start of instruction258//259uint8_t *instructionStart = getDataReferenceInstruction()->getBinaryEncoding();260const uint8_t instructionLength = getDataReferenceInstruction()->getBinaryLength();261const size_t dataReferenceOffset = getAddressOfDataReference() - instructionStart;262263TR_ASSERT(instructionLength != 0, "getDataReferenceInstruction()->getBinaryLength() should not be zero");264265const int32_t maxLen = 15;266TR_ASSERT(instructionLength <= maxLen, "Instruction length (%d) must fit in descriptor", instructionLength);267TR_ASSERT(dataReferenceOffset <= maxLen, "Data reference offset (%d) must fit in descriptor", dataReferenceOffset);268269*cursor++ = (uint8_t)((instructionLength << 4) | dataReferenceOffset);270271return cursor;272}273274275uint8_t *276J9::X86::UnresolvedDataSnippet::emitConstantPoolAddress(uint8_t *cursor)277{278TR::Compilation *comp = cg()->comp();279if (comp->target().is32Bit())280{281*cursor++ = 0x68; // push imm4282}283284*(intptr_t *)cursor = (intptr_t)getDataSymbolReference()->getOwningMethod(comp)->constantPool();285// in MT JRE, it might have no data reference instruction286if (getDataReferenceInstruction())287{288TR::Node *node = getDataReferenceInstruction()->getNode();289if (node && ((node->getOpCodeValue() == TR::checkcastAndNULLCHK) || (node->getOpCodeValue() == TR::NULLCHK)))290{291node = node->getChild(0);292}293294cg()->addProjectSpecializedRelocation(cursor,(uint8_t *)getDataSymbolReference()->getOwningMethod(comp)->constantPool(),295node ? (uint8_t *)(uintptr_t)node->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool,296__FILE__, __LINE__, node);297}298299cursor += TR::Compiler->om.sizeofReferenceAddress();300return cursor;301}302303304uint8_t *305J9::X86::UnresolvedDataSnippet::emitConstantPoolIndex(uint8_t *cursor)306{307308// Anatomy of a cpIndex passed to the runtime:309//310// byte 3 byte 2 byte 1 byte 0311//312// 3 222 2 222 1 1 0 0 0313// 10987654 32109876 54321098 76543210314// ||||__| ||| |_________________|315// ||| | ||| |316// ||| | ||| +---------------- cpIndex (0-16)317// |||| | ||| ||+-------------------------- upper long dword resolution (17)318// |||| | ||| |+--------------------------- lower long dword resolution (18)319// |||| | ||| +---------------------------- check volatility (19)320// |||| | ||+------------------------------ resolve, but do not patch snippet template (21)321// |||| | |+------------------------------- resolve, but do not patch mainline code (22)322// |||| | +-------------------------------- long push instruction (23)323// |||| +------------------------------------ number of live X87 registers across this resolution (24-27)324// |||+-------------------------------------- has live XMM registers (28)325// ||+--------------------------------------- static resolution (29)326// |+---------------------------------------- 64-bit: resolved value is 8 bytes (30)327// | 32-bit: resolved value is high word of long pair (30)328// +----------------------------------------- 64 bit: extreme static memory barrier position (31)329330TR::Compilation *comp = cg()->comp();331TR::Symbol *dataSymbol = getDataSymbolReference()->getSymbol();332int32_t cpIndex;333if (dataSymbol->isCallSiteTableEntry())334{335cpIndex = dataSymbol->castToCallSiteTableEntrySymbol()->getCallSiteIndex();336}337else if (dataSymbol->isMethodTypeTableEntry())338{339cpIndex = dataSymbol->castToMethodTypeTableEntrySymbol()->getMethodTypeIndex();340}341else // constant pool index342{343cpIndex = getDataSymbolReference()->getCPIndex();344}345346if (getNumLiveX87Registers() > 0) cpIndex |= (getNumLiveX87Registers() << 24);347if (hasLiveXMMRegisters() && comp->target().is32Bit()) cpIndex |= cpIndex_hasLiveXMMRegisters;348349// For unresolved object refs, the snippet need not be patched because its350// data is already correct.351//352if (getDataSymbol()->isConstObjectRef()) cpIndex |= cpIndex_doNotPatchSnippet;353354// Identify static resolution.355//356if (!getDataSymbol()->isShadow() && !getDataSymbol()->isClassObject() && !getDataSymbol()->isConstObjectRef())357{358cpIndex |= cpIndex_isStaticResolution;359}360361if (resolveMustPatch8Bytes())362{363TR_ASSERT(comp->target().is64Bit(), "resolveMustPatch8Bytes must only be set on 64-bit");364cpIndex |= cpIndex_patch8ByteResolution;365}366367if (comp->target().is32Bit())368{369if (getDataSymbolReference()->getOffset() == 4)370{371TR_ASSERT(((!getDataSymbol()->isShadow() && !getDataSymbol()->isClassObject() && !getDataSymbol()->isConstObjectRef()) || getDataSymbol()->isShadow()),372"unexpected symbol kind for offset 4, instruction=%x\n", getDataReferenceInstruction());373374// On 32-bit, an unresolved reference with a 4-byte offset is the high word375// of an unresolved long. The offset will be added at runtime.376//377cpIndex |= cpIndex_isHighWordOfLongPair;378}379}380381if (!comp->getOption(TR_DisableNewX86VolatileSupport) && getDataReferenceInstruction() != NULL)382{383TR::Instruction *dataRefInst = getDataReferenceInstruction();384TR::InstOpCode::Mnemonic opCode = dataRefInst->getOpCode().getOpCodeValue();385386// If this is a store operation on an unresolved field, set the volatility check flag.387//388if (comp->target().isSMP())389{390if (!getDataSymbol()->isClassObject() && !getDataSymbol()->isConstObjectRef() && isUnresolvedStore() && opCode != TR::InstOpCode::CMPXCHG8BMem && getDataSymbol()->isVolatile())391{392cpIndex |= cpIndex_checkVolatility;393394if (comp->target().is64Bit() && ((TR::X86MemInstruction *)dataRefInst)->getMemoryReference())395{396if (((TR::X86MemInstruction *)dataRefInst)->getMemoryReference()->processAsFPVolatile())397{398cpIndex |= cpIndex_isFloatStore;399}400}401402if (comp->target().is64Bit() && !getDataSymbol()->isShadow())403{404//If this is a store into a static field, we need to know the offset between the start of the store instruction and the memory barrier.405//406cpIndex |= getUnresolvedStaticStoreDeltaWithMemBarrier();407}408}409410if (comp->target().is32Bit())411{412// If this is a portion of a long store, flag which half of the long413// is being stored414//415if (dataRefInst->getKind() == TR::Instruction::IsRegMem)416{417if (((TR::X86RegMemInstruction *)dataRefInst)->getMemoryReference()->processAsLongVolatileLow())418{419cpIndex |= cpIndex_procAsLongLow | cpIndex_checkVolatility;420}421else if (((TR::X86RegMemInstruction *)dataRefInst)->getMemoryReference()->processAsLongVolatileHigh())422{423cpIndex |= cpIndex_procAsLongHigh | cpIndex_checkVolatility;424}425}426}427}428}429430if (comp->target().is32Bit())431{432if (cpIndex <= 127 && cpIndex >= -128)433{434*cursor++ = 0x6a; // push imms435*(int8_t *)cursor++ = (int8_t)cpIndex;436}437else438{439*cursor++ = 0x68; // push imm4440*(int32_t *)cursor = (cpIndex | cpIndex_longPushTag);441cursor += 4;442}443}444else445{446*(int32_t *)cursor = cpIndex;447cursor += 4;448}449return cursor;450}451452453uint8_t *454J9::X86::UnresolvedDataSnippet::fixupDataReferenceInstruction(uint8_t *cursor)455{456uint8_t *instructionStart = getDataReferenceInstruction()->getBinaryEncoding();457uint8_t bytesToCopy;458TR::Compilation *comp = cg()->comp();459460// Only for unresolved statics whose reference instruction may be executed in place461// in the snippet should the entire reference instruction be copied. All other462// unresolved references should copy 8 bytes only (this may include bytes from463// the following instruction).464//465if (!getDataSymbol()->isShadow() && !getDataSymbol()->isClassObject() && !getDataSymbol()->isConstObjectRef())466{467// Unresolved statics may result in the instruction being patched and executed in the snippet468// rather than the mainline code. A return instruction is necessary in this case.469//470uint8_t length = getDataReferenceInstruction()->getBinaryLength();471472bytesToCopy = std::max<uint8_t>(8, length);473memcpy(cursor, instructionStart, bytesToCopy);474475// If the TR::InstOpCode::RET will overwrite one of the eight bytes that will eventually be patched476// then the byte it overwrites needs to be preserved.477//478if (length < 8)479{480uint8_t b = *(cursor+length);481*(cursor+length) = 0xc3; // TR::InstOpCode::RET482cursor += bytesToCopy;483*cursor++ = b;484}485else486{487*(cursor+length) = 0xc3; // TR::InstOpCode::RET488cursor += (bytesToCopy + 1);489}490}491else492{493if (comp->target().is64Bit())494{495// Unresolved instance fields require 4 byte patching at a variable instruction496// offset so the 8 bytes following the start of the instruction need to be497// cached.498//499// For unresolved strings and classes only 2 bytes (REX+Op) are necessary.500//501bytesToCopy = getDataSymbol()->isShadow() ? 8 : 2;502}503else504{505if (getDataSymbol()->isConstObjectRef())506{507bytesToCopy = std::max<uint8_t>(8, getDataReferenceInstruction()->getBinaryLength());508}509else510{511bytesToCopy = 8;512}513}514515memcpy(cursor, instructionStart, bytesToCopy);516cursor += bytesToCopy;517518// For object ref constants, the original instruction already loaded a valid constant pool519// address and since it was copied to the snippet it needs a relocation here.520//521// This assumes that the string reference instruction is a MOV Reg, Imm32 (32-bit)522// or a MOV Reg, Imm64 (64-bit) instruction.523//524if (comp->target().is32Bit() && getDataSymbol()->isConstObjectRef())525{526uint8_t *stringConstantPtr = (cursor - bytesToCopy) + getDataReferenceInstruction()->getBinaryLength() - TR::Compiler->om.sizeofReferenceAddress();527528cg()->addProjectSpecializedRelocation(stringConstantPtr, (uint8_t *)getDataSymbolReference()->getOwningMethod(comp)->constantPool(),529getDataReferenceInstruction()->getNode() ? (uint8_t *)(uintptr_t)getDataReferenceInstruction()->getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool,530__FILE__, __LINE__, getDataReferenceInstruction()->getNode());531}532}533534// Write a call to this snippet over the original data reference instruction535//536uint8_t *originalInstruction = getDataReferenceInstruction()->getBinaryEncoding();537*originalInstruction = 0xe8; // CallImm32538*(int32_t *)(originalInstruction+1) = (int32_t)(cg()->getBinaryBufferCursor() - 5 - originalInstruction);539540return cursor;541}542543544uint32_t545J9::X86::UnresolvedDataSnippet::getLength(int32_t estimatedSnippetStart)546{547uint32_t length;548549length = 5; // TR::InstOpCode::CALLImm4 to resolve helper550551// cpAddr552//553length += sizeof(intptr_t);554555// cpIndex556//557// This is a conservative approximation.558//559length += 4;560561// 32-bit adjustments562//563if (cg()->comp()->target().is32Bit())564{565length += (5661 // TR::InstOpCode::PUSHImm4 for cpAddr567+1 // TR::InstOpCode::PUSHImm4 for cpIndex568+1 // descriptor byte569);570}571572if (!getDataSymbol()->isShadow() && !getDataSymbol()->isClassObject() && !getDataSymbol()->isConstObjectRef())573{574// Static reference.575//576uint32_t instructionLength = getDataReferenceInstruction()->getBinaryLength();577578// +1 is for either a TR::InstOpCode::RET instruction if instructionLength > 7 or for a copy of579// the byte that the TR::InstOpCode::RET instruction overwrites if instructionLength < 8.580//581length += std::max<uint32_t>(8, instructionLength) + 1;582}583else584{585if (cg()->comp()->target().is32Bit())586{587if (getDataSymbol()->isConstObjectRef())588{589uint32_t instructionLength = getDataReferenceInstruction()->getBinaryLength();590length += std::max<uint32_t>(8, instructionLength);591}592else593{594length += 8;595}596}597else598{599if (getDataSymbol()->isShadow())600{601length += (6028 // cached instruction bytes603+1 // descriptor byte604);605}606else607{608length += 2; // REX+opcode609}610}611}612613return length;614}615616617void618TR_Debug::print(TR::FILE *pOutFile, TR::UnresolvedDataSnippet * snippet)619{620if (pOutFile == NULL)621return;622623uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation();624printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet));625trfprintf(pOutFile, " for instr [%s]", getName(snippet->getDataReferenceInstruction()));626627if (_comp->target().is64Bit())628{629printPrefix(pOutFile, NULL, bufferPos, 5);630631TR_RuntimeHelper helperIndex = snippet->getHelper();632TR::SymbolReference *glueSymRef = _cg->getSymRef(helperIndex);633trfprintf(pOutFile, "call\t%s", getName(glueSymRef));634bufferPos += 5;635636printPrefix(pOutFile, NULL, bufferPos, 8);637trfprintf(pOutFile,638"%s\t" POINTER_PRINTF_FORMAT "\t%s address of constant pool for this method",639dqString(),640getOwningMethod(snippet->getDataSymbolReference())->constantPool(),641commentString());642bufferPos += 8;643644printPrefix(pOutFile, NULL, bufferPos, 4);645trfprintf(pOutFile,646"%s\t0x%08x\t\t\t\t%s constant pool index",647ddString(),648snippet->getDataSymbolReference()->getCPIndex(),649commentString());650bufferPos += 4;651652if (snippet->getDataSymbol()->isShadow())653{654printPrefix(pOutFile, NULL, bufferPos, 1);655656uint8_t descriptor = *bufferPos;657uint8_t length = (descriptor >> 4) & 0xf;658uint8_t offset = (descriptor & 0xf);659660trfprintf(661pOutFile,662"%s\t%02x\t\t\t\t\t\t\t%s instruction descriptor: length=%d, disp32 offset=%d",663dbString(),664descriptor,665commentString(),666length,667offset668);669670bufferPos++;671}672673}674else675{676if (!snippet->getDataReferenceInstruction())677{678// when do not patch mainline flag on, there is no data reference instruction copy in snippet679printPrefix(pOutFile, NULL, bufferPos, 1);680trfprintf(pOutFile, "int \t3\t\t\t%s (No data reference instruction; NEVER CALLED)",681commentString());682return;683}684685// 0x68 == PUSHImm32686//687int32_t size = (*bufferPos == 0x68) ? 5 : 2;688printPrefix(pOutFile, NULL, bufferPos, size);689trfprintf(690pOutFile,691"push\t" POINTER_PRINTF_FORMAT "\t\t%s constant pool index",692snippet->getDataSymbolReference()->getCPIndex(),693commentString());694bufferPos += size;695696printPrefix(pOutFile, NULL, bufferPos, 5);697trfprintf(698pOutFile,699"push\t" POINTER_PRINTF_FORMAT "\t\t%s address of constant pool for this method",700getOwningMethod(snippet->getDataSymbolReference())->constantPool(),701commentString());702bufferPos += 5;703704printPrefix(pOutFile, NULL, bufferPos, 5);705TR::SymbolReference *glueSymRef = _cg->getSymRef(snippet->getHelper());706trfprintf(pOutFile, "call\t%s", getName(glueSymRef));707bufferPos += 5;708}709710if (!snippet->getDataSymbol()->isShadow() &&711!snippet->getDataSymbol()->isClassObject() &&712!snippet->getDataSymbol()->isConstObjectRef() &&713!snippet->getDataSymbol()->isMethodTypeTableEntry())714{715int32_t length = snippet->getDataReferenceInstruction()->getBinaryLength();716int32_t bytesToCopy = std::max<int32_t>(8, length);717718if (length < 8)719{720printPrefix(pOutFile, NULL, bufferPos, bytesToCopy);721bufferPos += bytesToCopy;722trfprintf(pOutFile, "%s\t(%d)\t\t\t%s patch instruction bytes + TR::InstOpCode::RET + residue",723dbString(),724bytesToCopy,725commentString());726printPrefix(pOutFile, NULL, bufferPos, 1);727trfprintf(pOutFile, "%s\t\t\t\t\t\t%s byte that TR::InstOpCode::RET overwrote",728dbString(),729commentString());730bufferPos ++;731}732else733{734printPrefix(pOutFile, NULL, bufferPos, bytesToCopy+1);735bufferPos += (bytesToCopy + 1);736trfprintf(pOutFile, "%s\t(%d)\t\t\t\t%s patch instruction bytes + TR::InstOpCode::RET",737dbString(),738(bytesToCopy+1),739commentString());740}741}742else743{744int32_t bytesToCopy;745746if (_comp->target().is64Bit())747{748if (snippet->getDataSymbol()->isShadow())749{750bytesToCopy = 8;751printPrefix(pOutFile, NULL, bufferPos, bytesToCopy);752bufferPos += bytesToCopy;753trfprintf(pOutFile, "%s\t(%d)\t\t\t\t\t\t%s patch instruction bytes",754dbString(),755bytesToCopy,756commentString());757}758else759{760bytesToCopy = 2;761printPrefix(pOutFile, NULL, bufferPos, bytesToCopy);762bufferPos += bytesToCopy;763trfprintf(pOutFile, "%s\t\t\t\t\t\t\t\t%s REX + op of TR::InstOpCode::MOV8RegImm64",764dwString(),765commentString());766}767}768else769{770if (snippet->getDataSymbol()->isConstString())771{772// TODO:JSR292: isConstMethodType773// TODO:JSR292: isConstMethodHandle774bytesToCopy = std::max<int32_t>(8, snippet->getDataReferenceInstruction()->getBinaryLength());775printPrefix(pOutFile, NULL, bufferPos, bytesToCopy);776bufferPos += bytesToCopy;777trfprintf(pOutFile, "%s\t(%d)\t\t\t\t\t\t%s patched string instruction bytes",778dbString(),779bytesToCopy,780commentString());781}782else783{784bytesToCopy = 8;785printPrefix(pOutFile, NULL, bufferPos, bytesToCopy);786bufferPos += bytesToCopy;787trfprintf(pOutFile, "%s\t(%d)\t\t\t\t\t\t%s patch instruction bytes",788dbString(),789bytesToCopy,790commentString());791}792}793}794}795796797