Path: blob/master/runtime/compiler/arm/codegen/J9CodeGenerator.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/AheadOfTimeCompile.hpp"23#include "codegen/ARMAOTRelocation.hpp"24#include "codegen/ARMJNILinkage.hpp"25#include "codegen/ARMPrivateLinkage.hpp"26#include "compile/SymbolReferenceTable.hpp"27#include "codegen/CodeGenerator.hpp"28#include "codegen/CodeGenerator_inlines.hpp"29#include "codegen/Linkage.hpp"30#include "codegen/Linkage_inlines.hpp"31#include "codegen/PrivateLinkage.hpp"32#include "arm/codegen/ARMSystemLinkage.hpp"33#include "arm/codegen/ARMRecompilation.hpp"34#include "env/OMRMemory.hpp"35#include "codegen/ARMInstruction.hpp"36#include "codegen/GenerateInstructions.hpp"37#include "env/VMJ9.h"383940extern void TEMPORARY_initJ9ARMTreeEvaluatorTable(TR::CodeGenerator *cg);4142J9::ARM::CodeGenerator::CodeGenerator(TR::Compilation *comp) :43J9::CodeGenerator(comp)44{45/**46* Do not add CodeGenerator initialization logic here.47* Use the \c initialize() method instead.48*/49}5051void52J9::ARM::CodeGenerator::initialize()53{54self()->J9::CodeGenerator::initialize();5556/*57* "Statically" initialize the FE-specific tree evaluator functions.58* This code only needs to execute once per JIT lifetime.59*/60static bool initTreeEvaluatorTable = false;61if (!initTreeEvaluatorTable)62{63TEMPORARY_initJ9ARMTreeEvaluatorTable(self());64initTreeEvaluatorTable = true;65}66}6768static int32_t identifyFarConditionalBranches(int32_t estimate, TR::CodeGenerator *cg)69{70TR_Array<TR::ARMConditionalBranchInstruction *> candidateBranches(cg->trMemory(), 256);71TR::Instruction *cursorInstruction = cg->getFirstInstruction();7273while (cursorInstruction)74{75TR::ARMConditionalBranchInstruction *branch = cursorInstruction->getARMConditionalBranchInstruction();76if (branch != NULL)77{78if (abs(branch->getEstimatedBinaryLocation() - branch->getLabelSymbol()->getEstimatedCodeLocation()) > 16384)79{80candidateBranches.add(branch);81}82}83cursorInstruction = cursorInstruction->getNext();84}8586// The following heuristic algorithm penalizes backward branches in87// estimation, since it should be rare that a backward branch needs88// a far relocation.8990for (int32_t i=candidateBranches.lastIndex(); i>=0; i--)91{92int32_t myLocation=candidateBranches[i]->getEstimatedBinaryLocation();93int32_t targetLocation=candidateBranches[i]->getLabelSymbol()->getEstimatedCodeLocation();94int32_t j;9596if (targetLocation >= myLocation)97{98for (j=i+1; j<candidateBranches.size() &&99targetLocation>100candidateBranches[j]->getEstimatedBinaryLocation();101j++)102;103if ((targetLocation-myLocation + (j-i-1)*4) >= 32768)104{105candidateBranches[i]->setFarRelocation(true);106}107else108{109candidateBranches.remove(i);110}111}112else // backward branch113{114for (j=i-1; j>=0 && targetLocation<=115candidateBranches[j]->getEstimatedBinaryLocation();116j--)117;118if ((myLocation-targetLocation + (i-j-1)*4) > 32768)119{120candidateBranches[i]->setFarRelocation(true);121}122else123{124candidateBranches.remove(i);125}126}127}128return(estimate+4*candidateBranches.size());129}130131void J9::ARM::CodeGenerator::doBinaryEncoding()132{133TR::Compilation *comp = self()->comp();134TR::CodeGenerator *cg = self();135int32_t estimate = 0;136TR::Recompilation *recomp = comp->getRecompilationInfo();137TR::Instruction *tempInstruction;138TR::Instruction *cursorInstruction = cg->getFirstInstruction();139TR::Instruction *i2jEntryInstruction;140TR::Instruction *j2jEntryInstruction;141TR::ResolvedMethodSymbol *methodSymbol = comp->getMethodSymbol();142bool isPrivateLinkage = (methodSymbol->getLinkageConvention() == TR_Private);143144if (methodSymbol->isJNI())145{146// leave space for the JNI target address147cursorInstruction = cursorInstruction->getNext();148}149150if (isPrivateLinkage)151{152j2jEntryInstruction = cursorInstruction->getNext();153self()->getLinkage()->loadUpArguments(cursorInstruction);154i2jEntryInstruction = cursorInstruction->getNext();155}156else157{158i2jEntryInstruction = j2jEntryInstruction = cursorInstruction;159160// TODO: Probably bogus; what does loadUpArguments do when cursorInstruction == NULL?161cursorInstruction = NULL;162self()->getLinkage()->loadUpArguments(cursorInstruction);163}164165if (recomp != NULL)166{167recomp->generatePrePrologue();168}169170cursorInstruction = cg->getFirstInstruction();171172while (cursorInstruction && cursorInstruction->getOpCodeValue() != TR::InstOpCode::proc)173{174estimate = cursorInstruction->estimateBinaryLength(estimate);175cursorInstruction = cursorInstruction->getNext();176}177tempInstruction = cursorInstruction;178179if ((recomp != NULL) && (!recomp->useSampling()))180{181tempInstruction = recomp->generatePrologue(tempInstruction);182}183184self()->getLinkage()->createPrologue(tempInstruction);185bool skipOneReturn = false;186while (cursorInstruction)187{188if (cursorInstruction->getOpCodeValue() == TR::InstOpCode::retn)189{190if (skipOneReturn == false)191{192TR::Instruction *temp = cursorInstruction->getPrev();193self()->getLinkage()->createEpilogue(temp);194cursorInstruction = temp->getNext();195skipOneReturn = true;196}197else198{199skipOneReturn = false;200}201}202estimate = cursorInstruction->estimateBinaryLength(estimate);203cursorInstruction = cursorInstruction->getNext();204}205estimate = self()->setEstimatedLocationsForSnippetLabels(estimate);206if (estimate > 32768)207{208estimate = identifyFarConditionalBranches(estimate, self());209}210211self()->setEstimatedWarmLength(estimate);212213cursorInstruction = cg->getFirstInstruction();214uint8_t *coldCode = NULL;215uint8_t *temp = self()->allocateCodeMemory(self()->getEstimatedWarmLength(), 0, &coldCode);216217self()->setBinaryBufferStart(temp);218self()->setBinaryBufferCursor(temp);219220while (cursorInstruction)221{222#ifdef DEBUG223uint32_t estLen = cursorInstruction->estimateBinaryLength((int32_t)0);224#endif225self()->setBinaryBufferCursor(cursorInstruction->generateBinaryEncoding());226self()->addToAtlas(cursorInstruction);227if (cursorInstruction->getNext() == i2jEntryInstruction)228{229self()->setPrePrologueSize(self()->getBinaryBufferCursor() - self()->getBinaryBufferStart());230comp->getSymRefTab()->findOrCreateStartPCSymbolRef()->getSymbol()->getStaticSymbol()->setStaticAddress(self()->getBinaryBufferCursor());231}232#ifdef DEBUG233uint32_t binLen;234binLen = cursorInstruction->getBinaryLength();235if(binLen > estLen)236{237TR_ASSERT(0, "bin length estimated too small");238}239#endif240241cursorInstruction = cursorInstruction->getNext();242if (isPrivateLinkage && cursorInstruction == j2jEntryInstruction)243{244uint32_t linkageInfoWord = self()->initializeLinkageInfo(_returnTypeInfoInstruction->getBinaryEncoding());245((TR::ARMImmInstruction *)_returnTypeInfoInstruction)->setSourceImmediate(linkageInfoWord);246}247}248// Create exception table entries for outlined instructions.249//250ListIterator<TR_ARMOutOfLineCodeSection> oiIterator(&self()->getARMOutOfLineCodeSectionList());251TR_ARMOutOfLineCodeSection *oiCursor = oiIterator.getFirst();252253while (oiCursor)254{255uint32_t startOffset = oiCursor->getFirstInstruction()->getBinaryEncoding() - self()->getCodeStart();256uint32_t endOffset = oiCursor->getAppendInstruction()->getBinaryEncoding() - self()->getCodeStart();257258TR::Block * block = oiCursor->getBlock();259bool needsETE = oiCursor->getFirstInstruction()->getNode()->getOpCode().hasSymbolReference() &&260oiCursor->getFirstInstruction()->getNode()->getSymbolReference() &&261oiCursor->getFirstInstruction()->getNode()->getSymbolReference()->canCauseGC();262263if (needsETE && block && !block->getExceptionSuccessors().empty())264block->addExceptionRangeForSnippet(startOffset, endOffset);265266oiCursor = oiIterator.getNext();267}268}269270// Get or create the TR::Linkage object that corresponds to the given linkage271// convention.272// Even though this method is common, its implementation is machine-specific.273//274TR::Linkage *J9::ARM::CodeGenerator::createLinkage(TR_LinkageConventions lc)275{276TR::Linkage *linkage;277switch (lc)278{279// case TR_InterpretedStatic:280// linkage = new (self()->trHeapMemory()) TR::ARMInterpretedStaticLinkage(this);281// break;282case TR_Private:283linkage = new (self()->trHeapMemory()) J9::ARM::PrivateLinkage(self());284break;285case TR_System:286linkage = new (self()->trHeapMemory()) TR::ARMSystemLinkage(self());287break;288// case TR_AllRegister:289// linkage = new (self()->trHeapMemory()) TR::ARMAllRegisterLinkage(this);290// break;291case TR_CHelper:292case TR_Helper:293linkage = new (self()->trHeapMemory()) J9::ARM::HelperLinkage(self());294break;295case TR_J9JNILinkage:296linkage = new (self()->trHeapMemory()) J9::ARM::JNILinkage(self());297break;298default :299TR_ASSERT(0, "using system linkage for unrecognized convention %d\n", lc);300linkage = new (self()->trHeapMemory()) TR::ARMSystemLinkage(self());301}302self()->setLinkage(lc, linkage);303return linkage;304}305306TR::Recompilation *J9::ARM::CodeGenerator::allocateRecompilationInfo()307{308return TR_ARMRecompilation::allocate(TR::comp());309}310311312