Path: blob/master/runtime/compiler/p/codegen/StackCheckFailureSnippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 2020 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 "p/codegen/StackCheckFailureSnippet.hpp"2324#include "codegen/CodeGenerator.hpp"25#include "codegen/GCStackAtlas.hpp"26#include "codegen/Instruction.hpp"27#include "codegen/Linkage.hpp"28#include "codegen/Linkage_inlines.hpp"29#include "codegen/Machine.hpp"30#include "codegen/RealRegister.hpp"31#include "codegen/Relocation.hpp"32#include "codegen/SnippetGCMap.hpp"33#include "env/CompilerEnv.hpp"34#include "env/IO.hpp"35#include "env/jittypes.h"36#include "env/VMJ9.h"37#include "il/LabelSymbol.hpp"38#include "il/MethodSymbol.hpp"39#include "il/Node.hpp"40#include "il/Node_inlines.hpp"41#include "il/ParameterSymbol.hpp"42#include "il/RegisterMappedSymbol.hpp"43#include "il/ResolvedMethodSymbol.hpp"44#include "il/StaticSymbol.hpp"45#include "il/Symbol.hpp"46#include "runtime/CodeCacheManager.hpp"4748uint8_t *storeArgumentItem(TR::InstOpCode::Mnemonic op, uint8_t *buffer, TR::RealRegister *reg, int32_t offset, TR::CodeGenerator *cg)49{50TR::RealRegister *stackPtr = cg->getLinkage()->cg()->getStackPointerRegister();51TR::InstOpCode opCode(op);52opCode.copyBinaryToBuffer(buffer);53reg->setRegisterFieldRS(toPPCCursor(buffer));54stackPtr->setRegisterFieldRA(toPPCCursor(buffer));55*toPPCCursor(buffer) |= offset & 0x0000ffff;56return(buffer+4);57}5859uint8_t *loadArgumentItem(TR::InstOpCode::Mnemonic op, uint8_t *buffer, TR::RealRegister *reg, int32_t offset, TR::CodeGenerator *cg)60{61TR::RealRegister *stackPtr = cg->getLinkage()->cg()->getStackPointerRegister();62TR::InstOpCode opCode(op);63opCode.copyBinaryToBuffer(buffer);64reg->setRegisterFieldRT(toPPCCursor(buffer));65stackPtr->setRegisterFieldRA(toPPCCursor(buffer));66*toPPCCursor(buffer) |= offset & 0x0000ffff;67return(buffer+4);68}6970uint8_t *TR::PPCStackCheckFailureSnippet::emitSnippetBody()71{72TR::Compilation * comp = cg()->comp();73TR::ResolvedMethodSymbol *bodySymbol=comp->getJittedMethodSymbol();74TR::Machine *machine = cg()->machine();75TR::SymbolReference *sofRef = comp->getSymRefTab()->findOrCreateStackOverflowSymbolRef(comp->getJittedMethodSymbol());76TR::MethodSymbol *sof = sofRef->getSymbol()->castToMethodSymbol();7778int32_t offsetAdjust=cg()->getFrameSizeInBytes();79ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList()));80TR::ParameterSymbol *paramCursor = paramIterator.getFirst();81const TR::PPCLinkageProperties &linkage = cg()->getLinkage()->getProperties();8283uint8_t *buffer = cg()->getBinaryBufferCursor();84uint8_t *bufferStart = buffer;85uint8_t *returnLocation;86bool saveLR = (cg()->getSnippetList().size()<=1 &&87!bodySymbol->isEHAware() &&88!cg()->canExceptByTrap() &&89!machine->getLinkRegisterKilled());90TR::InstOpCode add_opCode(TR::InstOpCode::add);91TR::InstOpCode addi_opCode(TR::InstOpCode::addi);92TR::InstOpCode subf_opCode(TR::InstOpCode::subf);93TR::RealRegister *stackPtr = cg()->getLinkage()->cg()->getStackPointerRegister();94TR::RealRegister *gr12 = machine->getRealRegister(TR::RealRegister::gr12);9596getSnippetLabel()->setCodeLocation(buffer);9798if (offsetAdjust)99{100if (offsetAdjust > UPPER_IMMED) // addi is not applicable101{102// prologue arranged for gr12 to contain offsetAdjust103// add sp, sp, gr12104add_opCode.copyBinaryToBuffer(buffer);105stackPtr->setRegisterFieldRT(toPPCCursor(buffer));106stackPtr->setRegisterFieldRA(toPPCCursor(buffer));107gr12->setRegisterFieldRB(toPPCCursor(buffer));108buffer += 4;109}110else111{112// addi sp, sp, framesize113addi_opCode.copyBinaryToBuffer(buffer);114stackPtr->setRegisterFieldRT(toPPCCursor(buffer));115stackPtr->setRegisterFieldRA(toPPCCursor(buffer));116*toPPCCursor(buffer) |= offsetAdjust & 0x0000ffff;117buffer += 4;118// pass framesize to jitStackOverflow in gr12119// addi gr12, gr0, framesize (ie li gr12, framesize)120addi_opCode.copyBinaryToBuffer(buffer);121gr12->setRegisterFieldRT(toPPCCursor(buffer));122*toPPCCursor(buffer) |= offsetAdjust & 0x0000ffff;123buffer += 4;124}125}126else127{128if (saveLR)129{130// addi sp, sp, -sizeOfJavaPointer131addi_opCode.copyBinaryToBuffer(buffer);132stackPtr->setRegisterFieldRT(toPPCCursor(buffer));133stackPtr->setRegisterFieldRA(toPPCCursor(buffer));134*toPPCCursor(buffer) |= (-TR::Compiler->om.sizeofReferenceAddress()) & 0x0000ffff;135buffer += 4;136}137// pass framesize to jitStackOverflow in gr12138// addi gr12, gr0, framesize (ie li gr12, framesize)139addi_opCode.copyBinaryToBuffer(buffer);140gr12->setRegisterFieldRT(toPPCCursor(buffer));141*toPPCCursor(buffer) |= offsetAdjust & 0x0000ffff;142buffer += 4;143}144145if (saveLR)146{147// mflr gr0148*(int32_t *)buffer = 0x7c0802a6;149buffer += 4;150}151152if (saveLR)153{154if (comp->target().is64Bit())155// std [gr14, 0], gr0156*(int32_t *)buffer = 0xf80e0000;157else158// stw [gr14, 0], gr0159*(int32_t *)buffer = 0x900e0000;160buffer += 4;161}162163intptr_t helperAddress = (intptr_t)sof->getMethodAddress();164if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)buffer))165{166helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(sofRef->getReferenceNumber(), (void *)buffer);167TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)buffer), "Helper address is out of range");168}169170// bl distance171*(int32_t *)buffer = 0x48000001 | ((helperAddress - (intptr_t)buffer) & 0x03ffffff);172cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(buffer,173(uint8_t *)sofRef,174TR_HelperAddress, cg()),175__FILE__, __LINE__, getNode());176buffer += 4;177returnLocation = buffer;178179if (saveLR)180{181// For FSD, we have to reload the return address182if (comp->getOption(TR_FullSpeedDebug))183{184if (comp->target().is64Bit())185// ld gr0, [gr14, 0]186*(int32_t *)buffer = 0xe80e0000;187else188// lwz gr0, [gr14, 0]189*(int32_t *)buffer = 0x800e0000;190buffer += 4;191}192193// mtlr gr0194*(int32_t *)buffer = 0x7c0803a6;195buffer += 4;196}197198if (offsetAdjust)199{200if (offsetAdjust > (-LOWER_IMMED)) // addi is not applicable201{202// prologue arranged for gr12 to contain offsetAdjust203// and gr12 is preserved across the call to jitStackOverflow204// subf sp, gr12, sp205subf_opCode.copyBinaryToBuffer(buffer);206stackPtr->setRegisterFieldRT(toPPCCursor(buffer));207gr12->setRegisterFieldRA(toPPCCursor(buffer));208stackPtr->setRegisterFieldRB(toPPCCursor(buffer));209}210else211{212// addi sp, sp, -framesize213addi_opCode.copyBinaryToBuffer(buffer);214stackPtr->setRegisterFieldRT(toPPCCursor(buffer));215stackPtr->setRegisterFieldRA(toPPCCursor(buffer));216*toPPCCursor(buffer) |= -offsetAdjust & 0x0000ffff;217}218buffer += 4;219}220else if (saveLR)221{222// addi sp, sp, sizeOfJavaPointer223addi_opCode.copyBinaryToBuffer(buffer);224stackPtr->setRegisterFieldRT(toPPCCursor(buffer));225stackPtr->setRegisterFieldRA(toPPCCursor(buffer));226*toPPCCursor(buffer) |= TR::Compiler->om.sizeofReferenceAddress() & 0x0000ffff;227buffer += 4;228}229230// b restartLabel -- assuming it is less than 64MB away.231*(int32_t *)buffer = 0x48000000 | (((intptr_t)getReStartLabel()->getCodeLocation() - (intptr_t)buffer) & 0x03fffffc);232233TR::GCStackAtlas *atlas = cg()->getStackAtlas();234if (atlas)235{236// only the arg references are live at this point237uint32_t numberOfParmSlots = atlas->getNumberOfParmSlotsMapped();238TR_GCStackMap *map = new (cg()->trHeapMemory(), numberOfParmSlots) TR_GCStackMap(numberOfParmSlots);239240map->copy(atlas->getParameterMap());241while (paramCursor != NULL)242{243int32_t intRegArgIndex = paramCursor->getLinkageRegisterIndex();244if (intRegArgIndex >= 0 &&245paramCursor->isReferencedParameter() &&246paramCursor->isCollectedReference())247{248// In full speed debug all the parameters are passed in the stack for this case249// but will also reside in the registers250if (!comp->getOption(TR_FullSpeedDebug))251{252map->resetBit(paramCursor->getGCMapIndex());253}254map->setRegisterBits(cg()->registerBitMask(linkage.getIntegerArgumentRegister(intRegArgIndex)));255}256paramCursor = paramIterator.getNext();257}258259// set the GC map260gcMap().setStackMap(map);261atlas->setParameterMap(map);262}263gcMap().registerStackMap(returnLocation, cg());264return buffer + 4;265}266267268void269TR_Debug::print(TR::FILE *pOutFile, TR::PPCStackCheckFailureSnippet * snippet)270{271uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();272273printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Stack Check Failure Snippet");274275TR::ResolvedMethodSymbol *bodySymbol=_comp->getJittedMethodSymbol();276const TR::PPCLinkageProperties &linkage = _cg->getLinkage()->getProperties();277TR::Machine *machine = _cg->machine();278TR::RealRegister *stackPtr = _cg->getStackPointerRegister();279280bool saveLR = (_cg->getSnippetList().size() <= 1 &&281!bodySymbol->isEHAware() &&282!_cg->canExceptByTrap() &&283!machine->getLinkRegisterKilled());284285int32_t offsetAdjust = _cg->getFrameSizeInBytes();286287if (offsetAdjust)288{289if (offsetAdjust > UPPER_IMMED) // addi is not applicable290{291// prologue arranged for gr12 to contain offsetAdjust292printPrefix(pOutFile, NULL, cursor, 4);293trfprintf(pOutFile, "add \t");294print(pOutFile, stackPtr, TR_WordReg);295trfprintf(pOutFile, ", ");296print(pOutFile, stackPtr, TR_WordReg);297trfprintf(pOutFile, ", gr12");298cursor += 4;299}300else301{302printPrefix(pOutFile, NULL, cursor, 4);303trfprintf(pOutFile, "addi2 \t");304print(pOutFile, stackPtr, TR_WordReg);305trfprintf(pOutFile, ", ");306print(pOutFile, stackPtr, TR_WordReg);307trfprintf(pOutFile, ", 0x%x", offsetAdjust);308cursor += 4;309printPrefix(pOutFile, NULL, cursor, 4);310trfprintf(pOutFile, "li \tgr12");311trfprintf(pOutFile, ", 0x%x", offsetAdjust);312cursor += 4;313}314}315else316{317if (saveLR)318{319printPrefix(pOutFile, NULL, cursor, 4);320trfprintf(pOutFile, "addi2 \t");321print(pOutFile, stackPtr, TR_WordReg);322trfprintf(pOutFile, ", ");323print(pOutFile, stackPtr, TR_WordReg);324trfprintf(pOutFile, ", 0x%x", -TR::Compiler->om.sizeofReferenceAddress());325cursor += 4;326}327printPrefix(pOutFile, NULL, cursor, 4);328trfprintf(pOutFile, "li \tgr12");329trfprintf(pOutFile, ", 0x%x", offsetAdjust);330cursor += 4;331}332333if (saveLR)334{335printPrefix(pOutFile, NULL, cursor, 4);336trfprintf(pOutFile, "mflr \tgr0");337cursor += 4;338}339340if (saveLR)341{342printPrefix(pOutFile, NULL, cursor, 4);343if (_comp->target().is64Bit())344trfprintf(pOutFile, "std \t[gr14, 0], gr0");345else346trfprintf(pOutFile, "stw \t[gr14, 0], gr0");347cursor += 4;348}349350char *info = "";351int32_t distance;352if (isBranchToTrampoline(_comp->getSymRefTab()->element(TR_stackOverflow), cursor, distance))353info = " Through trampoline";354355printPrefix(pOutFile, NULL, cursor, 4);356distance = *((int32_t *) cursor) & 0x03fffffc;357distance = (distance << 6) >> 6; // sign extend358trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t;%s", (intptr_t)cursor + distance, info);359cursor += 4;360361if (saveLR)362{363printPrefix(pOutFile, NULL, cursor, 4);364trfprintf(pOutFile, "mtlr \tgr0");365cursor += 4;366}367368if (offsetAdjust)369{370if (offsetAdjust > (-LOWER_IMMED)) // addi is not applicable371{372// prologue arranged for gr12 to contain offsetAdjust373printPrefix(pOutFile, NULL, cursor, 4);374trfprintf(pOutFile, "subf \t");375print(pOutFile, stackPtr, TR_WordReg);376trfprintf(pOutFile, ", gr12, ");377print(pOutFile, stackPtr, TR_WordReg);378}379else380{381printPrefix(pOutFile, NULL, cursor, 4);382trfprintf(pOutFile, "addi2 \t");383print(pOutFile, stackPtr, TR_WordReg);384trfprintf(pOutFile, ", ");385print(pOutFile, stackPtr, TR_WordReg);386trfprintf(pOutFile, ", 0x%x", -offsetAdjust);387}388cursor += 4;389}390else if (saveLR)391{392printPrefix(pOutFile, NULL, cursor, 4);393trfprintf(pOutFile, "addi2 \t");394print(pOutFile, stackPtr, TR_WordReg);395trfprintf(pOutFile, ", ");396print(pOutFile, stackPtr, TR_WordReg);397trfprintf(pOutFile, ", 0x%x", TR::Compiler->om.sizeofReferenceAddress());398cursor += 4;399}400401// b restartLabel -- assuming it is less than 64MB away.402printPrefix(pOutFile, NULL, cursor, 4);403distance = *((int32_t *) cursor) & 0x03fffffc;404distance = (distance << 6) >> 6; // sign extend405trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; Back to ", (intptr_t)cursor + distance);406print(pOutFile, snippet->getReStartLabel());407}408409uint32_t TR::PPCStackCheckFailureSnippet::getLength(int32_t estimatedSnippetStart)410{411int32_t length = 0;412TR::ResolvedMethodSymbol *bodySymbol=cg()->comp()->getJittedMethodSymbol();413414if (cg()->getSnippetList().size()<=1 &&415!bodySymbol->isEHAware() &&416!cg()->canExceptByTrap() &&417!cg()->machine()->getLinkRegisterKilled())418{419length += 12;420if (cg()->getFrameSizeInBytes() == 0)421length += 8;422if (cg()->comp()->getOption(TR_FullSpeedDebug))423length += 4;424}425426if (cg()->getFrameSizeInBytes())427length += 8;428if (cg()->getFrameSizeInBytes() <= UPPER_IMMED)429length += 4; // to load r12 with framesize430431return(length+8);432}433434435