Path: blob/master/runtime/compiler/aarch64/codegen/StackCheckFailureSnippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2019, 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 "codegen/StackCheckFailureSnippet.hpp"2324#include "codegen/ARM64Instruction.hpp"25#include "codegen/CodeGenerator.hpp"26#include "codegen/GCStackAtlas.hpp"27#include "codegen/Linkage.hpp"28#include "codegen/Machine.hpp"29#include "il/ParameterSymbol.hpp"30#include "il/ResolvedMethodSymbol.hpp"3132uint8_t *33TR::ARM64StackCheckFailureSnippet::emitSnippetBody()34{35TR::ResolvedMethodSymbol *bodySymbol = cg()->comp()->getJittedMethodSymbol();36TR::Machine *machine = cg()->machine();37TR::SymbolReference *sofRef = cg()->comp()->getSymRefTab()->findOrCreateStackOverflowSymbolRef(bodySymbol);38ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList()));39TR::ParameterSymbol *paramCursor = paramIterator.getFirst();4041uint8_t *cursor = cg()->getBinaryBufferCursor();42uint8_t *returnLocation;4344getSnippetLabel()->setCodeLocation(cursor);4546// Pass cg()->getFrameSizeInBytes() to jitStackOverflow in register x9.47//48const TR::ARM64LinkageProperties &linkage = cg()->getLinkage()->getProperties();49uint32_t frameSize = cg()->getFrameSizeInBytes();5051if (frameSize <= 0xffff)52{53// mov x9, #frameSize54*(int32_t *)cursor = 0xd2800009 | (frameSize << 5);55cursor += ARM64_INSTRUCTION_LENGTH;56}57else58{59TR_ASSERT(false, "Frame size too big. Not supported yet");60}6162// add J9SP, J9SP, x963*(int32_t *)cursor = 0x8b090294;64cursor += ARM64_INSTRUCTION_LENGTH;6566// str LR, [J9SP]67// ToDo: Skip saving/restoring LR when not required68*(int32_t *)cursor = 0xf900029e;69cursor += ARM64_INSTRUCTION_LENGTH;7071// bl helper72*(int32_t *)cursor = cg()->encodeHelperBranchAndLink(sofRef, cursor, getNode());73cursor += ARM64_INSTRUCTION_LENGTH;74returnLocation = cursor;7576// ldr LR, [J9SP]77*(int32_t *)cursor = 0xf940029e;78cursor += ARM64_INSTRUCTION_LENGTH;7980// sub J9SP, J9SP, x9 ; assume that jitStackOverflow does not clobber x981*(int32_t *)cursor = 0xcb090294;82cursor += ARM64_INSTRUCTION_LENGTH;8384// b restartLabel85intptr_t destination = (intptr_t)getReStartLabel()->getCodeLocation();86if (!cg()->directCallRequiresTrampoline(destination, (intptr_t)cursor))87{88intptr_t distance = destination - (intptr_t)cursor;89*(int32_t *)cursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b) | ((distance >> 2) & 0x3ffffff); // imm2690}91else92{93TR_ASSERT(false, "Target too far away. Not supported yet");94}9596TR::GCStackAtlas *atlas = cg()->getStackAtlas();97if (atlas)98{99// only the arg references are live at this point100uint32_t numberOfParmSlots = atlas->getNumberOfParmSlotsMapped();101TR_GCStackMap *map = new (cg()->trHeapMemory(), numberOfParmSlots) TR_GCStackMap(numberOfParmSlots);102103map->copy(atlas->getParameterMap());104while (paramCursor != NULL)105{106int32_t intRegArgIndex = paramCursor->getLinkageRegisterIndex();107if (intRegArgIndex >= 0 &&108paramCursor->isReferencedParameter() &&109paramCursor->isCollectedReference())110{111// In full speed debug all the parameters are passed in the stack for this case112// but will also reside in the registers113if (!cg()->comp()->getOption(TR_FullSpeedDebug))114{115map->resetBit(paramCursor->getGCMapIndex());116}117map->setRegisterBits(1 << (linkage.getIntegerArgumentRegister(intRegArgIndex) - 1));118}119paramCursor = paramIterator.getNext();120}121122// set the GC map123gcMap().setStackMap(map);124atlas->setParameterMap(map);125}126gcMap().registerStackMap(returnLocation, cg());127128return cursor+ARM64_INSTRUCTION_LENGTH;129}130131void132TR_Debug::print(TR::FILE *pOutFile, TR::ARM64StackCheckFailureSnippet * snippet)133{134TR::ResolvedMethodSymbol *bodySymbol = _comp->getJittedMethodSymbol();135TR::SymbolReference *sofRef = _comp->getSymRefTab()->findOrCreateStackOverflowSymbolRef(bodySymbol);136uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation();137138printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet));139140TR::Machine *machine = _cg->machine();141TR::RealRegister *x9 = machine->getRealRegister(TR::RealRegister::x9);142TR::RealRegister *stackPtr = _cg->getStackPointerRegister();143TR::RealRegister *lr = machine->getRealRegister(TR::RealRegister::x30);144uint32_t frameSize = _cg->getFrameSizeInBytes();145146if (frameSize <= 0xffff)147{148// mov x9, #frameSize149printPrefix(pOutFile, NULL, bufferPos, 4);150trfprintf(pOutFile, "movzx \t");151print(pOutFile, x9, TR_WordReg);152trfprintf(pOutFile, ", 0x%04x", frameSize);153bufferPos += ARM64_INSTRUCTION_LENGTH;154}155else156{157TR_ASSERT(false, "Frame size too big. Not supported yet");158}159160printPrefix(pOutFile, NULL, bufferPos, 4);161trfprintf(pOutFile, "addx \t");162print(pOutFile, stackPtr, TR_WordReg); trfprintf(pOutFile, ", ");163print(pOutFile, stackPtr, TR_WordReg); trfprintf(pOutFile, ", ");164print(pOutFile, x9, TR_WordReg);165bufferPos += ARM64_INSTRUCTION_LENGTH;166167printPrefix(pOutFile, NULL, bufferPos, 4);168trfprintf(pOutFile, "strimmx \t");169print(pOutFile, lr, TR_WordReg);170trfprintf(pOutFile, ", [");171print(pOutFile, stackPtr, TR_WordReg);172trfprintf(pOutFile, "]");173bufferPos += ARM64_INSTRUCTION_LENGTH;174175char *info = "";176intptr_t target = (intptr_t)(sofRef->getMethodAddress());177int32_t distance;178if (isBranchToTrampoline(sofRef, bufferPos, distance))179{180target = (intptr_t)distance + (intptr_t)bufferPos;181info = " Through trampoline";182}183printPrefix(pOutFile, NULL, bufferPos, 4);184trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t;%s", target, info);185bufferPos += ARM64_INSTRUCTION_LENGTH;186187printPrefix(pOutFile, NULL, bufferPos, 4);188trfprintf(pOutFile, "ldrimmx \t");189print(pOutFile, lr, TR_WordReg);190trfprintf(pOutFile, ", [");191print(pOutFile, stackPtr, TR_WordReg);192trfprintf(pOutFile, "]");193bufferPos += ARM64_INSTRUCTION_LENGTH;194195printPrefix(pOutFile, NULL, bufferPos, 4);196trfprintf(pOutFile, "subx \t");197print(pOutFile, stackPtr, TR_WordReg); trfprintf(pOutFile, ", ");198print(pOutFile, stackPtr, TR_WordReg); trfprintf(pOutFile, ", ");199print(pOutFile, x9, TR_WordReg);200bufferPos += ARM64_INSTRUCTION_LENGTH;201202intptr_t destination = (intptr_t)snippet->getReStartLabel()->getCodeLocation();203// assuming that the distance to the destination is in the range +/- 128MB204printPrefix(pOutFile, NULL, bufferPos, 4);205trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; Back to ", destination);206print(pOutFile, snippet->getReStartLabel());207}208209uint32_t210TR::ARM64StackCheckFailureSnippet::getLength(int32_t estimatedSnippetStart)211{212uint32_t frameSize = cg()->getFrameSizeInBytes();213214if (frameSize <= 0xffff)215{216return 7*ARM64_INSTRUCTION_LENGTH;217}218else219{220TR_ASSERT(false, "Frame size too big. Not supported yet");221return 0;222}223}224225226