Path: blob/master/runtime/compiler/arm/codegen/ARMRecompilation.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/ARMRecompilation.hpp"2324#include <stdint.h>25#include "arm/codegen/ARMRecompilationSnippet.hpp"26#include "codegen/CodeGenerator.hpp"27#include "codegen/GenerateInstructions.hpp"28#include "codegen/Snippet.hpp"29#include "env/jittypes.h"30#include "env/VMJ9.h"31#include "il/Node.hpp"32#include "il/Node_inlines.hpp"33#include "il/TreeTop.hpp"34#include "il/TreeTop_inlines.hpp"3536// Allocate a machine-specific recompilation processor for this compilation37//38TR::Recompilation *TR_ARMRecompilation::allocate(TR::Compilation *comp)39{40if (comp->isRecompilationEnabled())41return new (comp->trHeapMemory()) TR_ARMRecompilation(comp);42else43return NULL;44}4546TR_ARMRecompilation::TR_ARMRecompilation(TR::Compilation * comp)47: TR::Recompilation(comp)48{49_countingSupported = true;50setupMethodInfo();51}5253TR_PersistentMethodInfo *TR_ARMRecompilation::getExistingMethodInfo(TR_ResolvedMethod *method)54{55int8_t *startPC = (int8_t *)method->startAddressForInterpreterOfJittedMethod();56TR_PersistentMethodInfo *info = getJittedBodyInfoFromPC(startPC)->getMethodInfo();57return(info);58}5960TR::Instruction *TR_ARMRecompilation::generatePrePrologue()61{62TR_J9VMBase *fej9 = (TR_J9VMBase *)(_compilation->fe());63// If in Full Speed Debug, allow to go through64if (!couldBeCompiledAgain() && !_compilation->getOption(TR_FullSpeedDebug))65return(NULL);6667// gr12 may contain the vtable offset, and must be preserved here68// see PicBuilder.s and Recompilation.s69TR::Instruction *cursor=NULL;70TR::Machine *machine = cg()->machine();71TR::Register *gr4 = machine->getRealRegister(TR::RealRegister::gr4);72TR::Register *lr = machine->getRealRegister(TR::RealRegister::gr14); // link register73TR::Node *firstNode = _compilation->getStartTree()->getNode();74TR::SymbolReference *recompileMethodSymRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_ARMsamplingRecompileMethod);75TR_PersistentJittedBodyInfo *info = getJittedBodyInfo();767778// force creation of switch to interpreter pre prologue if in Full Speed Debug79if (cg()->mustGenerateSwitchToInterpreterPrePrologue())80{81cursor = cg()->generateSwitchToInterpreterPrePrologue(cursor, firstNode);82}8384if (couldBeCompiledAgain())85{86// gr4 must contain the saved LR; see Recompilation.s87if(useSampling())88{89cursor = new (cg()->trHeapMemory()) TR::ARMTrg1Src1Instruction(cursor, TR::InstOpCode::mov, firstNode, gr4, lr, cg());90cursor = generateImmSymInstruction(cg(), TR::InstOpCode::bl, firstNode, (uintptr_t)recompileMethodSymRef->getMethodAddress(), new (cg()->trHeapMemory()) TR::RegisterDependencyConditions((uint8_t)0, 0, cg()->trMemory()), recompileMethodSymRef, NULL, cursor);91}92cursor = new (cg()->trHeapMemory()) TR::ARMImmInstruction(cursor, TR::InstOpCode::dd, firstNode, (int32_t)(intptr_t)info, cg());93cursor->setNeedsAOTRelocation();94((TR::ARMImmInstruction *)cursor)->setReloKind(TR_BodyInfoAddress);9596cursor = generateImmInstruction(cg(), TR::InstOpCode::dd, firstNode, 0, cursor);97}98return(cursor);99}100101TR::Instruction *TR_ARMRecompilation::generatePrologue(TR::Instruction *cursor)102{103if (couldBeCompiledAgain())104{105// gr12 may contain the vtable offset, and must be preserved here106// see PicBuilder.s and Recompilation.s107TR::Machine *machine = cg()->machine();108TR::Register *gr4 = machine->getRealRegister(TR::RealRegister::gr4);109TR::Register *gr5 = machine->getRealRegister(TR::RealRegister::gr5);110TR::Register *lr = machine->getRealRegister(TR::RealRegister::gr14); // link register111TR::Node *firstNode = _compilation->getStartTree()->getNode();112intptr_t addr = (intptr_t)getCounterAddress();113TR::LabelSymbol *snippetLabel = TR::LabelSymbol::create(cg()->trHeapMemory(), cg());114intParts localVal(addr);115116TR_ARMOperand2 *op2_3 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte3(), 24);117TR_ARMOperand2 *op2_2 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte2(), 16);118TR_ARMOperand2 *op2_1 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte1(), 8);119TR_ARMOperand2 *op2_0 = new (cg()->trHeapMemory()) TR_ARMOperand2(localVal.getByte0(), 0);120cursor = generateTrg1Src1Instruction(cg(), TR::InstOpCode::mov, firstNode, gr5, op2_3, cursor);121cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, firstNode, gr5, gr5, op2_2, cursor);122cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, firstNode, gr5, gr5, op2_1, cursor);123cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, firstNode, gr5, gr5, op2_0, cursor);124125cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldr, firstNode, gr4, new (cg()->trHeapMemory()) TR::MemoryReference(gr5, 0, cg()), cursor);126127if (!isProfilingCompilation())128{129cursor = generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::sub_r, firstNode, gr4, gr4, 1, 0, cursor);130cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::str, firstNode,131new (cg()->trHeapMemory()) TR::MemoryReference(gr5, (int32_t)0, cg()), gr4, cursor);132}133else134{135// This only applies to JitProfiling, as JProfiling uses sampling136TR_ASSERT(_compilation->getProfilingMode() == JitProfiling, "JProfiling should use sampling to trigger recompilation");137138cursor = generateSrc1ImmInstruction(cg(), TR::InstOpCode::cmp, firstNode, gr4, 0, 0, cursor);139// this is just padding for consistent code length140cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::orr, firstNode, gr5, gr5, gr5, cursor);141}142143// gr4 must contain the saved LR; see Recompilation.s144cursor = generateTrg1Src1Instruction(cg(), TR::InstOpCode::mov, firstNode, gr4, lr, cursor);145// the instruction below is replaced after successful recompilation146cursor = generateTrg1Src2Instruction(cg(), TR::InstOpCode::orr, firstNode, gr5, gr5, gr5, cursor);147cursor = generateConditionalBranchInstruction(cg(), firstNode, ARMConditionCodeLT, snippetLabel, cursor);148149TR::Snippet *snippet = new (cg()->trHeapMemory()) TR::ARMRecompilationSnippet(snippetLabel, cursor, cg());150cg()->addSnippet(snippet);151}152return(cursor);153}154155156157