Path: blob/master/runtime/compiler/p/codegen/PPCRecompilation.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/PPCRecompilation.hpp"2324#include "codegen/CodeGenerator.hpp"25#include "codegen/Machine.hpp"26#include "codegen/RealRegister.hpp"27#include "codegen/Register.hpp"28#include "codegen/Snippet.hpp"29#include "compile/ResolvedMethod.hpp"30#include "env/jittypes.h"31#include "env/CompilerEnv.hpp"32#include "env/VMJ9.h"33#include "il/DataTypes.hpp"34#include "il/LabelSymbol.hpp"35#include "il/Node.hpp"36#include "il/Node_inlines.hpp"37#include "il/TreeTop.hpp"38#include "il/TreeTop_inlines.hpp"39#include "p/codegen/GenerateInstructions.hpp"40#include "p/codegen/PPCInstruction.hpp"41#include "p/codegen/PPCRecompilationSnippet.hpp"42#include "env/CompilerEnv.hpp"4344// Allocate a machine-specific recompilation processor for this compilation45//46TR::Recompilation *TR_PPCRecompilation::allocate(TR::Compilation *comp)47{48if (comp->isRecompilationEnabled())49{50return new (comp->trHeapMemory()) TR_PPCRecompilation(comp);51}5253return NULL;54}5556TR_PPCRecompilation::TR_PPCRecompilation(TR::Compilation * comp)57: TR::Recompilation(comp)58{59_countingSupported = true;6061setupMethodInfo();62}6364TR_PersistentMethodInfo *TR_PPCRecompilation::getExistingMethodInfo(TR_ResolvedMethod *method)65{66int8_t *startPC = (int8_t *)method->startAddressForInterpreterOfJittedMethod();67TR_PersistentMethodInfo *info = getJittedBodyInfoFromPC(startPC)->getMethodInfo();68return(info);69}7071TR::Instruction *TR_PPCRecompilation::generatePrePrologue()72{73TR::Compilation *comp = cg()->comp();74TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());7576// If in Full Speed Debug, allow to go through77if (!couldBeCompiledAgain() && !comp->getOption(TR_FullSpeedDebug))78return(NULL);7980// gr12 may contain the vtable offset, and must be preserved here81// see PicBuilder.s and Recompilation.s82TR::Instruction *cursor=NULL;83TR::Machine *machine = cg()->machine();84TR::Register *gr0 = machine->getRealRegister(TR::RealRegister::gr0);85TR::Node *firstNode = comp->getStartTree()->getNode();86TR::SymbolReference *recompileMethodSymRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_PPCsamplingRecompileMethod);87TR_PersistentJittedBodyInfo *info = getJittedBodyInfo();88// force creation of switch to interpreter pre prologue if in Full Speed Debug89if (cg()->mustGenerateSwitchToInterpreterPrePrologue())90{91cursor = cg()->generateSwitchToInterpreterPrePrologue(cursor, firstNode);92}9394if (useSampling() && couldBeCompiledAgain())95{96// gr0 must contain the saved LR; see Recompilation.s97cursor = new (cg()->trHeapMemory()) TR::PPCTrg1Instruction(TR::InstOpCode::mflr, firstNode, gr0, cursor, cg());98cursor = generateDepImmSymInstruction(cg(), TR::InstOpCode::bl, firstNode, (uintptr_t)recompileMethodSymRef->getMethodAddress(), new (cg()->trHeapMemory()) TR::RegisterDependencyConditions(0,0, cg()->trMemory()), recompileMethodSymRef, NULL, cursor);99if (comp->target().is64Bit())100{101int32_t highBits = (int32_t)((intptr_t)info>>32), lowBits = (int32_t)((intptr_t)info);102cursor = generateImmInstruction(cg(), TR::InstOpCode::dd, firstNode,103comp->target().cpu.isBigEndian()?highBits:lowBits, TR_BodyInfoAddress, cursor);104cursor = generateImmInstruction(cg(), TR::InstOpCode::dd, firstNode,105comp->target().cpu.isBigEndian()?lowBits:highBits, cursor);106}107else108{109cursor = generateImmInstruction(cg(), TR::InstOpCode::dd, firstNode, (int32_t)(intptr_t)info, TR_BodyInfoAddress, cursor);110}111cursor = generateImmInstruction(cg(), TR::InstOpCode::dd, firstNode, 0, cursor);112}113114return(cursor);115}116117118TR::Instruction *TR_PPCRecompilation::generatePrologue(TR::Instruction *cursor)119{120if (couldBeCompiledAgain())121{122// gr12 may contain the vtable offset, and must be preserved here123// see PicBuilder.s and Recompilation.s124TR::Compilation *comp = cg()->comp();125TR::Machine *machine = cg()->machine();126TR::Register *gr0 = machine->getRealRegister(TR::RealRegister::gr0);127TR::Register *gr11 = machine->getRealRegister(TR::RealRegister::gr11);128TR::Register *cr0 = machine->getRealRegister(TR::RealRegister::cr0);129TR::Node *firstNode = comp->getStartTree()->getNode();130intptr_t addr = (intptr_t)getCounterAddress(); // What is the RL category?131TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg());132133if (comp->target().is64Bit())134{135intptr_t adjustedAddr = HI_VALUE(addr);136// lis gr11, upper 16-bits137cursor = generateTrg1ImmInstruction(cg(), TR::InstOpCode::lis, firstNode, gr11, (int16_t)adjustedAddr>>32, cursor );138// ori gr11, gr11, next 16-bit139cursor = generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::ori, firstNode, gr11, gr11, ((adjustedAddr>>16) & 0x0000FFFF), cursor);140// rldicr gr11, gr11, 32, 31141cursor = generateTrg1Src1Imm2Instruction(cg(), TR::InstOpCode::rldicr, firstNode, gr11, gr11, 32, CONSTANT64(0xFFFFFFFF00000000), cursor);142// oris gr11, gr11, next 16-bits143cursor = generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::oris, firstNode, gr11, gr11, (adjustedAddr & 0x0000FFFF), cursor);144}145else146{147cursor = generateTrg1ImmInstruction(cg(), TR::InstOpCode::lis, firstNode, gr11, (int16_t)HI_VALUE(addr), cursor);148}149150// lwzu gr0, last 16-bits(gr11)151cursor = generateTrg1MemInstruction(cg(), (!isProfilingCompilation())?TR::InstOpCode::lwzu:TR::InstOpCode::lwz, firstNode, gr0,152TR::MemoryReference::createWithDisplacement(cg(), gr11, LO_VALUE(addr), 4), cursor);153154if (!isProfilingCompilation())155{156cursor = generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::addic_r, firstNode, gr0, gr0, -1, cursor);157cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::stw, firstNode,158TR::MemoryReference::createWithDisplacement(cg(), gr11, (int32_t)0, 4), gr0, cursor);159}160else161{162// This only applies to JitProfiling, as JProfiling uses sampling163TR_ASSERT(comp->getProfilingMode() == JitProfiling, "JProfiling should not use counting mechanism to trip recompilation");164165cursor = generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::cmpi4, firstNode, cr0, gr0, 0, cursor);166// this is just padding for consistent code length167cursor = generateTrg1Src2Instruction (cg(), TR::InstOpCode::OR, firstNode, gr11, gr11, gr11, cursor);168}169170// gr0 must contain the saved LR; see Recompilation.s171cursor = generateTrg1Instruction(cg(), TR::InstOpCode::mflr, firstNode, gr0, cursor);172// this instruction is replaced after successful recompilation173cursor = generateTrg1Src2Instruction (cg(), TR::InstOpCode::OR, firstNode, gr11, gr11, gr11, cursor);174cursor = generateConditionalBranchInstruction(cg(), TR::InstOpCode::blt, firstNode, snippetLabel, cr0, cursor);175TR::Snippet *snippet = new (cg()->trHeapMemory()) TR::PPCRecompilationSnippet(snippetLabel, cursor->getPPCConditionalBranchInstruction(), cg());176cg()->addSnippet(snippet);177}178return(cursor);179}180181182