Path: blob/master/runtime/compiler/aarch64/codegen/J9CodeGenerator.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2019, 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/ARM64JNILinkage.hpp"24#include "codegen/ARM64PrivateLinkage.hpp"25#include "codegen/ARM64Recompilation.hpp"26#include "codegen/ARM64SystemLinkage.hpp"27#include "codegen/CodeGenerator.hpp"28#include "codegen/CodeGenerator_inlines.hpp"29#include "codegen/GenerateInstructions.hpp"30#include "compile/Compilation.hpp"31#include "runtime/CodeCacheManager.hpp"3233extern void TEMPORARY_initJ9ARM64TreeEvaluatorTable(TR::CodeGenerator *cg);3435J9::ARM64::CodeGenerator::CodeGenerator(TR::Compilation *comp) :36J9::CodeGenerator(comp)37{38/**39* Do not add CodeGenerator initialization logic here.40* Use the \c initialize() method instead.41*/42}4344void45J9::ARM64::CodeGenerator::initialize()46{47self()->J9::CodeGenerator::initialize();4849TR::CodeGenerator *cg = self();50TR::Compilation *comp = cg->comp();5152cg->setAheadOfTimeCompile(new (cg->trHeapMemory()) TR::AheadOfTimeCompile(cg));5354/*55* "Statically" initialize the FE-specific tree evaluator functions.56* This code only needs to execute once per JIT lifetime.57*/58static bool initTreeEvaluatorTable = false;59if (!initTreeEvaluatorTable)60{61TEMPORARY_initJ9ARM64TreeEvaluatorTable(cg);62initTreeEvaluatorTable = true;63}6465cg->setSupportsInliningOfTypeCoersionMethods();66cg->setSupportsDivCheck();67if (!comp->getOption(TR_FullSpeedDebug))68cg->setSupportsDirectJNICalls();6970cg->setSupportsPrimitiveArrayCopy();71cg->setSupportsReferenceArrayCopy();7273static char *disableMonitorCacheLookup = feGetEnv("TR_disableMonitorCacheLookup");74if (!disableMonitorCacheLookup)75{76comp->setOption(TR_EnableMonitorCacheLookup);77}78}7980TR::Linkage *81J9::ARM64::CodeGenerator::createLinkage(TR_LinkageConventions lc)82{83TR::Linkage *linkage;84switch (lc)85{86case TR_Private:87linkage = new (self()->trHeapMemory()) J9::ARM64::PrivateLinkage(self());88break;89case TR_System:90linkage = new (self()->trHeapMemory()) TR::ARM64SystemLinkage(self());91break;92case TR_CHelper:93case TR_Helper:94linkage = new (self()->trHeapMemory()) J9::ARM64::HelperLinkage(self(), lc);95break;96case TR_J9JNILinkage:97linkage = new (self()->trHeapMemory()) J9::ARM64::JNILinkage(self());98break;99default :100linkage = new (self()->trHeapMemory()) TR::ARM64SystemLinkage(self());101TR_ASSERT_FATAL(false, "Unexpected linkage convention");102}103104self()->setLinkage(lc, linkage);105return linkage;106}107108TR::Recompilation *109J9::ARM64::CodeGenerator::allocateRecompilationInfo()110{111return TR_ARM64Recompilation::allocate(self()->comp());112}113114uint32_t115J9::ARM64::CodeGenerator::encodeHelperBranchAndLink(TR::SymbolReference *symRef, uint8_t *cursor, TR::Node *node, bool omitLink)116{117TR::CodeGenerator *cg = self();118uintptr_t target = (uintptr_t)symRef->getMethodAddress();119120if (cg->directCallRequiresTrampoline(target, (intptr_t)cursor))121{122target = TR::CodeCacheManager::instance()->findHelperTrampoline(symRef->getReferenceNumber(), (void *)cursor);123124TR_ASSERT_FATAL(cg->comp()->target().cpu.isTargetWithinUnconditionalBranchImmediateRange(target, (intptr_t)cursor),125"Target address is out of range");126}127128cg->addExternalRelocation(new (cg->trHeapMemory()) TR::ExternalRelocation(129cursor,130(uint8_t *)symRef,131TR_HelperAddress, cg),132__FILE__, __LINE__, node);133134uintptr_t distance = target - (uintptr_t)cursor;135return TR::InstOpCode::getOpCodeBinaryEncoding(omitLink ? (TR::InstOpCode::b) : (TR::InstOpCode::bl)) | ((distance >> 2) & 0x3ffffff); /* imm26 */136}137138void139J9::ARM64::CodeGenerator::generateBinaryEncodingPrePrologue(TR_ARM64BinaryEncodingData &data)140{141TR::Compilation *comp = self()->comp();142TR::Node *startNode = comp->getStartTree()->getNode();143144data.recomp = comp->getRecompilationInfo();145data.cursorInstruction = self()->getFirstInstruction();146data.i2jEntryInstruction = data.cursorInstruction;147148if (data.recomp != NULL)149{150data.recomp->generatePrePrologue();151}152else153{154if (comp->getOption(TR_FullSpeedDebug) || comp->getOption(TR_SupportSwitchToInterpreter))155{156self()->generateSwitchToInterpreterPrePrologue(NULL, startNode);157}158else159{160TR::ResolvedMethodSymbol *methodSymbol = comp->getMethodSymbol();161/* save the original JNI native address if a JNI thunk is generated */162/* thunk is not recompilable, nor does it support FSD */163if (methodSymbol->isJNI())164{165uintptr_t methodAddress = reinterpret_cast<uintptr_t>(methodSymbol->getResolvedMethod()->startAddressForJNIMethod(comp));166uint32_t low = methodAddress & static_cast<uint32_t>(0xffffffff);167uint32_t high = (methodAddress >> 32) & static_cast<uint32_t>(0xffffffff);168TR::Instruction *cursor = new (self()->trHeapMemory()) TR::ARM64ImmInstruction(TR::InstOpCode::dd, startNode, low, NULL, self());169generateImmInstruction(self(), TR::InstOpCode::dd, startNode, high, cursor);170}171}172}173}174175TR::Instruction *176J9::ARM64::CodeGenerator::generateSwitchToInterpreterPrePrologue(TR::Instruction *cursor, TR::Node *node)177{178TR::Compilation *comp = self()->comp();179TR::Register *x8 = self()->machine()->getRealRegister(TR::RealRegister::x8);180TR::Register *lr = self()->machine()->getRealRegister(TR::RealRegister::x30); // link register181TR::Register *xzr = self()->machine()->getRealRegister(TR::RealRegister::xzr); // zero register182TR::ResolvedMethodSymbol *methodSymbol = comp->getJittedMethodSymbol();183TR::SymbolReference *revertToInterpreterSymRef = self()->symRefTab()->findOrCreateRuntimeHelper(TR_ARM64revertToInterpreterGlue);184uintptr_t ramMethod = (uintptr_t)methodSymbol->getResolvedMethod()->resolvedMethodAddress();185TR::SymbolReference *helperSymRef = self()->symRefTab()->findOrCreateRuntimeHelper(TR_j2iTransition);186uintptr_t helperAddr = (uintptr_t)helperSymRef->getMethodAddress();187188// x8 must contain the saved LR; see Recompilation.s189// cannot use generateMovInstruction() here190cursor = new (self()->trHeapMemory()) TR::ARM64Trg1Src2Instruction(TR::InstOpCode::orrx, node, x8, xzr, lr, cursor, self());191cursor = self()->getLinkage()->saveParametersToStack(cursor);192cursor = generateImmSymInstruction(self(), TR::InstOpCode::bl, node,193(uintptr_t)revertToInterpreterSymRef->getMethodAddress(),194new (self()->trHeapMemory()) TR::RegisterDependencyConditions(0, 0, self()->trMemory()),195revertToInterpreterSymRef, NULL, cursor);196cursor = generateRelocatableImmInstruction(self(), TR::InstOpCode::dd, node, (uintptr_t)ramMethod, TR_RamMethod, cursor);197198if (comp->getOption(TR_EnableHCR))199comp->getStaticHCRPICSites()->push_front(cursor);200201cursor = generateRelocatableImmInstruction(self(), TR::InstOpCode::dd, node, (uintptr_t)helperAddr, TR_AbsoluteHelperAddress, helperSymRef, cursor);202// Used in FSD to store an instruction203cursor = generateImmInstruction(self(), TR::InstOpCode::dd, node, 0, cursor);204205return cursor;206}207208bool209J9::ARM64::CodeGenerator::supportsInliningOfIsInstance()210{211return !self()->comp()->getOption(TR_DisableInlineIsInstance);212}213214bool215J9::ARM64::CodeGenerator::suppressInliningOfRecognizedMethod(TR::RecognizedMethod method)216{217return false;218}219220221