Path: blob/master/runtime/compiler/p/codegen/J9PPCSnippet.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/J9PPCSnippet.hpp"2324#include <stdint.h>25#include "j9.h"26#include "thrdsup.h"27#include "thrtypes.h"28#include "codegen/CodeGenerator.hpp"29#include "codegen/Machine.hpp"30#include "codegen/Relocation.hpp"31#include "codegen/TreeEvaluator.hpp"32#include "codegen/SnippetGCMap.hpp"33#include "env/CompilerEnv.hpp"34#include "env/IO.hpp"35#include "env/jittypes.h"36#include "env/VMJ9.h"37#include "il/DataTypes.hpp"38#include "il/LabelSymbol.hpp"39#include "il/Node.hpp"40#include "il/Node_inlines.hpp"41#include "p/codegen/PPCEvaluator.hpp"42#include "p/codegen/PPCInstruction.hpp"43#include "p/codegen/GenerateInstructions.hpp"44#include "runtime/CodeCache.hpp"45#include "runtime/CodeCacheManager.hpp"4647#if defined(TR_HOST_POWER)48extern uint32_t getPPCCacheLineSize();49#else50uint32_t getPPCCacheLineSize()51{52return 32;53}54#endif5556TR::PPCReadMonitorSnippet::PPCReadMonitorSnippet(57TR::CodeGenerator *codeGen,58TR::Node *monitorEnterNode,59TR::Node *monitorExitNode,60TR::LabelSymbol *recurCheckLabel,61TR::LabelSymbol *monExitCallLabel,62TR::LabelSymbol *restartLabel,63TR::InstOpCode::Mnemonic loadOpCode,64int32_t loadOffset,65TR::Register *objectClassReg)66: _monitorEnterHelper(monitorEnterNode->getSymbolReference()),67_recurCheckLabel(recurCheckLabel),68_loadOpCode(loadOpCode),69_loadOffset(loadOffset),70_objectClassReg(objectClassReg),71TR::PPCHelperCallSnippet(codeGen, monitorExitNode, monExitCallLabel, monitorExitNode->getSymbolReference(), restartLabel)72{73recurCheckLabel->setSnippet(this);74// Helper call, preserves all registers75//76gcMap().setGCRegisterMask(0xFFFFFFFF);77}7879uint8_t *TR::PPCReadMonitorSnippet::emitSnippetBody()80{81TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());828384// The 32-bit code for the snippet looks like:85// recurCheckLabel:86// rlwinm monitorReg, monitorReg, 0, LOCK_THREAD_PTR_MASK87// cmp cndReg, metaReg, monitorReg88// bne cndReg, slowPath89// <load>90// b restartLabel91// slowPath:92// bl monitorEnterHelper93// <load>94// bl monitorExitHelper95// b restartLabel;9697// for 64-bit the rlwinm is replaced with:98// rldicr threadReg, monitorReg, 0, (long) LOCK_THREAD_PTR_MASK99100TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();101102TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();103TR::RealRegister *monitorReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(0)->getRealRegister());104TR::RealRegister *cndReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());105TR::RealRegister *loadResultReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());106bool isResultCollectable = deps->getPostConditions()->getRegisterDependency(3)->getRegister()->containsCollectedReference();107TR::RealRegister *loadBaseReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(4)->getRealRegister());108TR::Compilation *comp = cg()->comp();109TR::InstOpCode opcode;110111uint8_t *buffer = cg()->getBinaryBufferCursor();112113_recurCheckLabel->setCodeLocation(buffer);114115if (comp->target().is64Bit())116{117opcode.setOpCodeValue(TR::InstOpCode::rldicr);118buffer = opcode.copyBinaryToBuffer(buffer);119monitorReg->setRegisterFieldRA((uint32_t *)buffer);120monitorReg->setRegisterFieldRS((uint32_t *)buffer);121// sh = 0122// assumption here that thread pointer is in upper bits, so MB = 0123// ME = 32 + LOCK_LAST_RECURSION_BIT_NUMBER - 1124int32_t ME = 32 + LOCK_LAST_RECURSION_BIT_NUMBER - 1;125int32_t me_field_encoding = (ME >> 5) | ((ME & 0x1F) << 1);126*(int32_t *)buffer |= (me_field_encoding << 5);127}128else129{130opcode.setOpCodeValue(TR::InstOpCode::rlwinm);131buffer = opcode.copyBinaryToBuffer(buffer);132monitorReg->setRegisterFieldRA((uint32_t *)buffer);133monitorReg->setRegisterFieldRS((uint32_t *)buffer);134// sh = 0135// assumption here that thread pointer is in upper bits, so MB = 0136// ME = LOCK_LAST_RECURSION_BIT_NUMBER - 1137*(int32_t *)buffer |= ((LOCK_LAST_RECURSION_BIT_NUMBER - 1) << 1);138}139buffer += PPC_INSTRUCTION_LENGTH;140141opcode.setOpCodeValue(TR::InstOpCode::Op_cmp);142buffer = opcode.copyBinaryToBuffer(buffer);143cndReg->setRegisterFieldRT((uint32_t *)buffer);144metaReg->setRegisterFieldRA((uint32_t *)buffer);145monitorReg->setRegisterFieldRB((uint32_t *)buffer);146buffer += PPC_INSTRUCTION_LENGTH;147148opcode.setOpCodeValue(TR::InstOpCode::bne);149buffer = opcode.copyBinaryToBuffer(buffer);150cndReg->setRegisterFieldBI((uint32_t *)buffer);151*(int32_t *)buffer |= 12;152buffer += PPC_INSTRUCTION_LENGTH;153154opcode.setOpCodeValue(_loadOpCode);155buffer = opcode.copyBinaryToBuffer(buffer);156loadResultReg->setRegisterFieldRT((uint32_t *)buffer);157loadBaseReg->setRegisterFieldRA((uint32_t *)buffer);158*(int32_t *)buffer |= _loadOffset & 0xFFFF;159buffer += PPC_INSTRUCTION_LENGTH;160161opcode.setOpCodeValue(TR::InstOpCode::b);162buffer = opcode.copyBinaryToBuffer(buffer);163*(int32_t *)buffer |= (getRestartLabel()->getCodeLocation()-buffer) & 0x03FFFFFC;164buffer += PPC_INSTRUCTION_LENGTH;165166intptr_t helperAddress = (intptr_t)getMonitorEnterHelper()->getSymbol()->castToMethodSymbol()->getMethodAddress();167if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)buffer))168{169helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(getMonitorEnterHelper()->getReferenceNumber(), (void *)buffer);170TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)buffer), "Helper address is out of range");171}172173opcode.setOpCodeValue(TR::InstOpCode::bl);174buffer = opcode.copyBinaryToBuffer(buffer);175176if (comp->compileRelocatableCode())177{178cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(buffer,(uint8_t *)getMonitorEnterHelper(),TR_HelperAddress, cg()),179__FILE__, __LINE__, getNode());180}181182*(int32_t *)buffer |= (helperAddress - (intptr_t)buffer) & 0x03FFFFFC;183buffer += PPC_INSTRUCTION_LENGTH;184185gcMap().registerStackMap(buffer, cg());186187opcode.setOpCodeValue(_loadOpCode);188buffer = opcode.copyBinaryToBuffer(buffer);189loadResultReg->setRegisterFieldRT((uint32_t *)buffer);190loadBaseReg->setRegisterFieldRA((uint32_t *)buffer);191*(int32_t *)buffer |= _loadOffset & 0xFFFF;192buffer += PPC_INSTRUCTION_LENGTH;193194// this will call jitMonitorExit and return to the restart label195cg()->setBinaryBufferCursor(buffer);196197// Defect 101811198TR_GCStackMap *exitMap = gcMap().getStackMap()->clone(cg()->trMemory());199exitMap->setByteCodeInfo(getNode()->getByteCodeInfo());200if (isResultCollectable)201exitMap->setRegisterBits(cg()->registerBitMask((int)deps->getPostConditions()->getRegisterDependency(3)->getRealRegister()));202203// Throw away entry map204gcMap().setStackMap(exitMap);205buffer = TR::PPCHelperCallSnippet::emitSnippetBody();206207return buffer;208}209210void211TR::PPCReadMonitorSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)212{213TR::Compilation *comp = cg()->comp();214TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());215uint8_t *cursor = getRecurCheckLabel()->getCodeLocation();216217debug->printSnippetLabel(pOutFile, getRecurCheckLabel(), cursor, "Read Monitor Snippet");218219TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();220221TR::Machine *machine = cg()->machine();222TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();223TR::RealRegister *monitorReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());224TR::RealRegister *condReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());225TR::RealRegister *loadResultReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());226TR::RealRegister *loadBaseReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(4)->getRealRegister());227228debug->printPrefix(pOutFile, NULL, cursor, 4);229if (comp->target().is64Bit())230trfprintf(pOutFile, "rldicr \t%s, %s, 0, " INT64_PRINTF_FORMAT_HEX "\t; Get owner thread value", debug->getName(monitorReg), debug->getName(monitorReg), (int64_t) LOCK_THREAD_PTR_MASK);231else232trfprintf(pOutFile, "rlwinm \t%s, %s, 0, 0x%x\t; Get owner thread value", debug->getName(monitorReg), debug->getName(monitorReg), LOCK_THREAD_PTR_MASK);233cursor+= 4;234235debug->printPrefix(pOutFile, NULL, cursor, 4);236if (comp->target().is64Bit())237trfprintf(pOutFile, "cmp8 \t%s, %s, %s\t; Compare VMThread to owner thread", debug->getName(condReg), debug->getName(metaReg), debug->getName(monitorReg));238else239trfprintf(pOutFile, "cmp4 \t%s, %s, %s\t; Compare VMThread to owner thread", debug->getName(condReg), debug->getName(metaReg), debug->getName(monitorReg));240cursor+= 4;241242debug->printPrefix(pOutFile, NULL, cursor, 4);243int32_t distance = *((int32_t *) cursor) & 0x0000fffc;244distance = (distance << 16) >> 16; // sign extend245trfprintf(pOutFile, "bne %s, " POINTER_PRINTF_FORMAT "\t; Use Helpers", debug->getName(condReg), (intptr_t)cursor + distance);246cursor+= 4;247248debug->printPrefix(pOutFile, NULL, cursor, 4);249trfprintf(pOutFile, "%s \t%s, [%s, %d]\t; Load", TR::InstOpCode::metadata[getLoadOpCode()].name, debug->getName(loadResultReg), debug->getName(loadBaseReg), getLoadOffset());250cursor+= 4;251252debug->printPrefix(pOutFile, NULL, cursor, 4);253distance = *((int32_t *) cursor) & 0x03fffffc;254distance = (distance << 6) >> 6; // sign extend255trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; ", (intptr_t)cursor + distance);256debug->print(pOutFile, getRestartLabel());257cursor+= 4;258259debug->printPrefix(pOutFile, NULL, cursor, 4);260distance = *((int32_t *) cursor) & 0x03fffffc;261distance = (distance << 6) >> 6; // sign extend262trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t; %s", (intptr_t)cursor + distance, debug->getName(getMonitorEnterHelper()));263if (debug->isBranchToTrampoline(getMonitorEnterHelper(), cursor, distance))264trfprintf(pOutFile, " Through trampoline");265cursor+= 4;266267debug->printPrefix(pOutFile, NULL, cursor, 4);268trfprintf(pOutFile, "%s \t%s, [%s, %d]\t; Load", TR::InstOpCode::metadata[getLoadOpCode()].name, debug->getName(loadResultReg), debug->getName(loadBaseReg), getLoadOffset());269270debug->print(pOutFile, (TR::PPCHelperCallSnippet *)this);271}272273uint32_t TR::PPCReadMonitorSnippet::getLength(int32_t estimatedSnippetStart)274{275int32_t len = 28;276len += TR::PPCHelperCallSnippet::getLength(estimatedSnippetStart+len);277return len;278}279280int32_t TR::PPCReadMonitorSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)281{282_recurCheckLabel->setEstimatedCodeLocation(estimatedSnippetStart);283getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart+28);284return(estimatedSnippetStart);285}286287TR::PPCAllocPrefetchSnippet::PPCAllocPrefetchSnippet(288TR::CodeGenerator *codeGen,289TR::Node *node,290TR::LabelSymbol *callLabel)291: TR::Snippet(codeGen, node, callLabel, false)292{293}294295uint32_t TR::getCCPreLoadedCodeSize()296{297uint32_t size = 0;298299// XXX: Can't check if processor supports transient at this point because processor type hasn't been determined300// so we have to allocate for the larger of the two scenarios301if (false)302{303const uint32_t linesToPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 8;304size += (linesToPrefetch + 1) / 2 * 4;305}306else307{308static bool l3SkipLines = feGetEnv("TR_l3SkipLines") != NULL;309const uint32_t linesToLdPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 4;310const uint32_t linesToStPrefetch = linesToLdPrefetch * 2;311size += 4 + (linesToLdPrefetch + 1) / 2 * 4 + 1 + (l3SkipLines ? 2 : 0) + (linesToStPrefetch + 1) / 2 * 4;312}313size += 3;314315//if (!TR::CodeGenerator::supportsTransientPrefetch() && !doL1Pref)316// XXX: Can't check if processor supports transient at this point because processor type hasn't been determined317// so we have to allocate for the larger of the two scenarios318if (false)319{320const uint32_t linesToPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 8;321size += (linesToPrefetch + 1) / 2 * 4;322}323else324{325static bool l3SkipLines = feGetEnv("TR_l3SkipLines") != NULL;326const uint32_t linesToLdPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 4;327const uint32_t linesToStPrefetch = linesToLdPrefetch * 2;328size += 4 + (linesToLdPrefetch + 1) / 2 * 4 + 1 + (l3SkipLines ? 2 : 0) + (linesToStPrefetch + 1) / 2 * 4;329}330size += 3;331332//TR_writeBarrier/TR_writeBarrierAndCardMark/TR_cardMark333size += 12;334if (TR::Options::getCmdLineOptions()->getGcCardSize() > 0)335size += 19 + (TR::Compiler->om.writeBarrierType() != gc_modron_wrtbar_cardmark_incremental ? 13 : 10);336337#if defined(TR_TARGET_32BIT)338// If heap base and/or size is constant we can materialize them with 1 or 2 instructions339// Assume 2 instructions, which means we want space for 1 additional instruction340// for both TR_writeBarrier and TR_writeBarrierAndCardMark341if (!TR::Options::getCmdLineOptions()->isVariableHeapBaseForBarrierRange0())342size += 2;343if (!TR::Options::getCmdLineOptions()->isVariableHeapSizeForBarrierRange0())344size += 2;345#endif346347//TR_arrayStoreCHK348size += 25;349350// Add size for other helpers351352// Eyecatchers, one per helper353size += TR_numCCPreLoadedCode;354355return TR::alignAllocationSize<8>(size * PPC_INSTRUCTION_LENGTH);356}357358#ifdef __LITTLE_ENDIAN__359#define CCEYECATCHER(a, b, c, d) (((a) << 0) | ((b) << 8) | ((c) << 16) | ((d) << 24))360#else361#define CCEYECATCHER(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d) << 0))362#endif363364static void performCCPreLoadedBinaryEncoding(uint8_t *buffer, TR::CodeGenerator *cg)365{366cg->setBinaryBufferStart(buffer);367cg->setBinaryBufferCursor(buffer);368for (TR::Instruction *i = cg->getFirstInstruction(); i != NULL; i = i->getNext())369{370i->estimateBinaryLength(cg->getBinaryBufferCursor() - cg->getBinaryBufferStart());371cg->setBinaryBufferCursor(i->generateBinaryEncoding());372}373}374375static uint8_t* initializeCCPreLoadedPrefetch(uint8_t *buffer, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)376{377TR::Compilation *comp = cg->comp();378TR::Node *n = cg->getFirstInstruction()->getNode();379380// Prefetch helper; prefetches a number of lines and returns directly to JIT code381// In:382// r8 = object ptr383// Out:384// r8 = object ptr385// Clobbers:386// r10, r11387// cr0388389cg->setFirstInstruction(NULL);390cg->setAppendInstruction(NULL);391392TR::Instruction *eyecatcher = generateImmInstruction(cg, TR::InstOpCode::dd, n, CCEYECATCHER('C', 'C', 'H', 5));393394TR::LabelSymbol *entryLabel = generateLabelSymbol(cg);395TR::Instruction *entry = generateLabelInstruction(cg, TR::InstOpCode::label, n, entryLabel);396TR::Instruction *cursor = entry;397398TR::Register *metaReg = cg->getMethodMetaDataRegister();399TR::Register *r8 = cg->machine()->getRealRegister(TR::RealRegister::gr8);400TR::Register *r10 = cg->machine()->getRealRegister(TR::RealRegister::gr10);401TR::Register *r11 = cg->machine()->getRealRegister(TR::RealRegister::gr11);402TR::Register *cr0 = cg->machine()->getRealRegister(TR::RealRegister::cr0);403404static bool doL1Pref = feGetEnv("TR_doL1Prefetch") != NULL;405const uint32_t ppcCacheLineSize = getPPCCacheLineSize();406uint32_t helperSize;407408if (!TR::CodeGenerator::supportsTransientPrefetch() && !doL1Pref)409{410const uint32_t linesToPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 8;411const uint32_t restartAfterLines = TR::Options::_TLHPrefetchBoundaryLineCount > 0 ? TR::Options::_TLHPrefetchBoundaryLineCount : 8;412const uint32_t skipLines = TR::Options::_TLHPrefetchStaggeredLineCount > 0 ? TR::Options::_TLHPrefetchStaggeredLineCount : 4;413helperSize = (linesToPrefetch + 1) / 2 * 4;414415TR_ASSERT_FATAL( (skipLines + 1) * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchStaggeredLineCount (%u) is too high. Will cause imm field to overflow.", skipLines);416TR_ASSERT_FATAL( restartAfterLines * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchBoundaryLineCount (%u) is too high. Will cause imm field to overflow.", restartAfterLines);417418cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r8, skipLines * ppcCacheLineSize, cursor);419cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r8, (skipLines + 1) * ppcCacheLineSize, cursor);420cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);421cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);422423for (uint32_t i = 2; i < linesToPrefetch; i += 2)424{425cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * 2, cursor);426cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * 2, cursor);427cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);428cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);429}430431cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, r11, restartAfterLines * ppcCacheLineSize, cursor);432cursor = generateMemSrc1Instruction(cg,TR::InstOpCode::Op_st, n,433TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, tlhPrefetchFTA), TR::Compiler->om.sizeofReferenceAddress()),434r11, cursor);435}436else437{438// Transient version439static const char *s = feGetEnv("TR_l3SkipLines");440static uint32_t l3SkipLines = s ? atoi(s) : 0;441const uint32_t linesToLdPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 4;442const uint32_t linesToStPrefetch = linesToLdPrefetch * 2;443const uint32_t restartAfterLines = TR::Options::_TLHPrefetchBoundaryLineCount > 0 ? TR::Options::_TLHPrefetchBoundaryLineCount : 4;444const uint32_t skipLines = TR::Options::_TLHPrefetchStaggeredLineCount > 0 ? TR::Options::_TLHPrefetchStaggeredLineCount : 4;445helperSize = 4 + (linesToLdPrefetch + 1) / 2 * 4 + 1 + (l3SkipLines ? 2 : 0) + (linesToStPrefetch + 1) / 2 * 4;446447TR_ASSERT_FATAL( (skipLines + 1) * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchStaggeredLineCount (%u) is too high. Will cause imm field to overflow.", skipLines);448TR_ASSERT_FATAL( restartAfterLines * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchBoundaryLineCount (%u) is too high. Will cause imm field to overflow.", restartAfterLines);449450cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r10,451TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, debugEventData3), TR::Compiler->om.sizeofReferenceAddress()),452cursor);453cursor = generateTrg1Src1ImmInstruction(cg,TR::InstOpCode::Op_cmpli, n, cr0, r10, 0, cursor);454cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::xori, n, r10, r10, 1, cursor);455cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, r11, restartAfterLines * ppcCacheLineSize, cursor);456cursor = generateMemSrc1Instruction(cg,TR::InstOpCode::Op_st, n,457TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, tlhPrefetchFTA), TR::Compiler->om.sizeofReferenceAddress()),458r11, cursor);459cursor = generateMemSrc1Instruction(cg,TR::InstOpCode::Op_st, n,460TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, debugEventData3), TR::Compiler->om.sizeofReferenceAddress()),461r10, cursor);462463cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r8, skipLines * ppcCacheLineSize, cursor);464cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r8, (skipLines + 1) * ppcCacheLineSize, cursor);465cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);466cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);467468for (uint32_t i = 2; i < linesToLdPrefetch; i += 2)469{470cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * 2, cursor);471cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * 2, cursor);472cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);473cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);474}475476cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);477478if (l3SkipLines > 0)479{480TR_ASSERT_FATAL( ppcCacheLineSize * l3SkipLines <= UPPER_IMMED, "TR_l3SkipLines (%u) is too high. Will cause imm field to overflow.", l3SkipLines);481cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * l3SkipLines, cursor);482cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * l3SkipLines, cursor);483}484485for (uint32_t i = 0; i < linesToStPrefetch; i += 2)486{487cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * 2, cursor);488cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * 2, cursor);489cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtstt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);490cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtstt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);491}492}493494cursor = generateInstruction(cg, TR::InstOpCode::blr, n, cursor);495496performCCPreLoadedBinaryEncoding(buffer, cg);497498helperSize += 3;499TR_ASSERT(cg->getBinaryBufferCursor() - entryLabel->getCodeLocation() == helperSize * PPC_INSTRUCTION_LENGTH,500"Per-codecache prefetch helper, unexpected size");501502CCPreLoadedCodeTable[TR_AllocPrefetch] = entryLabel->getCodeLocation();503504return cg->getBinaryBufferCursor() - PPC_INSTRUCTION_LENGTH;505}506507static uint8_t* initializeCCPreLoadedNonZeroPrefetch(uint8_t *buffer, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)508{509TR::Compilation *comp = cg->comp();510TR::Node *n = cg->getFirstInstruction()->getNode();511512// NonZero TLH Prefetch helper; prefetches a number of lines and returns directly to JIT code513// In:514// r8 = object ptr515// Out:516// r8 = object ptr517// Clobbers:518// r10, r11519// cr0520521cg->setFirstInstruction(NULL);522cg->setAppendInstruction(NULL);523524TR::Instruction *eyecatcher = generateImmInstruction(cg, TR::InstOpCode::dd, n, CCEYECATCHER('C', 'C', 'H', 6));525526TR::LabelSymbol *entryLabel = generateLabelSymbol(cg);527TR::Instruction *entry = generateLabelInstruction(cg, TR::InstOpCode::label, n, entryLabel);528TR::Instruction *cursor = entry;529530TR::Register *metaReg = cg->getMethodMetaDataRegister();531TR::Register *r8 = cg->machine()->getRealRegister(TR::RealRegister::gr8);532TR::Register *r10 = cg->machine()->getRealRegister(TR::RealRegister::gr10);533TR::Register *r11 = cg->machine()->getRealRegister(TR::RealRegister::gr11);534TR::Register *cr0 = cg->machine()->getRealRegister(TR::RealRegister::cr0);535536static bool doL1Pref = feGetEnv("TR_doL1Prefetch") != NULL;537const uint32_t ppcCacheLineSize = getPPCCacheLineSize();538uint32_t helperSize;539540if (!TR::CodeGenerator::supportsTransientPrefetch() && !doL1Pref)541{542const uint32_t linesToPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 8;543const uint32_t restartAfterLines = TR::Options::_TLHPrefetchBoundaryLineCount > 0 ? TR::Options::_TLHPrefetchBoundaryLineCount : 8;544const uint32_t skipLines = TR::Options::_TLHPrefetchStaggeredLineCount > 0 ? TR::Options::_TLHPrefetchStaggeredLineCount : 4;545helperSize = (linesToPrefetch + 1) / 2 * 4;546547TR_ASSERT_FATAL( (skipLines + 1) * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchStaggeredLineCount (%u) is too high. Will cause imm field to overflow.", skipLines);548TR_ASSERT_FATAL( restartAfterLines * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchBoundaryLineCount (%u) is too high. Will cause imm field to overflow.", restartAfterLines);549550cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r8, skipLines * ppcCacheLineSize, cursor);551cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r8, (skipLines + 1) * ppcCacheLineSize, cursor);552cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);553cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);554555for (uint32_t i = 2; i < linesToPrefetch; i += 2)556{557cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * 2, cursor);558cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * 2, cursor);559cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);560cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtst, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);561}562563cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, r11, restartAfterLines * ppcCacheLineSize, cursor);564cursor = generateMemSrc1Instruction(cg,TR::InstOpCode::Op_st, n,565TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, nonZeroTlhPrefetchFTA), TR::Compiler->om.sizeofReferenceAddress()),566r11, cursor);567}568else569{570// Transient version571static const char *s = feGetEnv("TR_l3SkipLines");572static uint32_t l3SkipLines = s ? atoi(s) : 0;573const uint32_t linesToLdPrefetch = TR::Options::_TLHPrefetchLineCount > 0 ? TR::Options::_TLHPrefetchLineCount : 4;574const uint32_t linesToStPrefetch = linesToLdPrefetch * 2;575const uint32_t restartAfterLines = TR::Options::_TLHPrefetchBoundaryLineCount > 0 ? TR::Options::_TLHPrefetchBoundaryLineCount : 4;576const uint32_t skipLines = TR::Options::_TLHPrefetchStaggeredLineCount > 0 ? TR::Options::_TLHPrefetchStaggeredLineCount : 4;577helperSize = 4 + (linesToLdPrefetch + 1) / 2 * 4 + 1 + (l3SkipLines ? 2 : 0) + (linesToStPrefetch + 1) / 2 * 4;578579TR_ASSERT_FATAL( (skipLines + 1) * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchStaggeredLineCount (%u) is too high. Will cause imm field to overflow.", skipLines);580TR_ASSERT_FATAL( restartAfterLines * ppcCacheLineSize <= UPPER_IMMED, "tlhPrefetchBoundaryLineCount (%u) is too high. Will cause imm field to overflow.", restartAfterLines);581582cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r10,583TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, debugEventData3), TR::Compiler->om.sizeofReferenceAddress()),584cursor);585cursor = generateTrg1Src1ImmInstruction(cg,TR::InstOpCode::Op_cmpli, n, cr0, r10, 0, cursor);586cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::xori, n, r10, r10, 1, cursor);587cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, r11, restartAfterLines * ppcCacheLineSize, cursor);588cursor = generateMemSrc1Instruction(cg,TR::InstOpCode::Op_st, n,589TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, nonZeroTlhPrefetchFTA), TR::Compiler->om.sizeofReferenceAddress()),590r11, cursor);591cursor = generateMemSrc1Instruction(cg,TR::InstOpCode::Op_st, n,592TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(J9VMThread, debugEventData3), TR::Compiler->om.sizeofReferenceAddress()),593r10, cursor);594595cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r8, skipLines * ppcCacheLineSize, cursor);596cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r8, (skipLines + 1) * ppcCacheLineSize, cursor);597cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);598cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);599600for (uint32_t i = 2; i < linesToLdPrefetch; i += 2)601{602cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * 2, cursor);603cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * 2, cursor);604cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg ,NULL, r10, 4), cursor);605cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);606}607608cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);609610if (l3SkipLines > 0)611{612TR_ASSERT_FATAL( ppcCacheLineSize * l3SkipLines <= UPPER_IMMED, "TR_l3SkipLines (%u) is too high. Will cause imm field to overflow.", l3SkipLines);613cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * l3SkipLines, cursor);614cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * l3SkipLines, cursor);615}616617for (uint32_t i = 0; i < linesToStPrefetch; i += 2)618{619cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r10, r10, ppcCacheLineSize * 2, cursor);620cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, r11, r11, ppcCacheLineSize * 2, cursor);621cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtstt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r10, 4), cursor);622cursor = generateMemInstruction(cg, TR::InstOpCode::dcbtstt, n, TR::MemoryReference::createWithIndexReg(cg, NULL, r11, 4), cursor);623}624}625626cursor = generateInstruction(cg, TR::InstOpCode::blr, n, cursor);627628performCCPreLoadedBinaryEncoding(buffer, cg);629630helperSize += 3;631TR_ASSERT(cg->getBinaryBufferCursor() - entryLabel->getCodeLocation() == helperSize * PPC_INSTRUCTION_LENGTH,632"Per-codecache prefetch helper, unexpected size");633634CCPreLoadedCodeTable[TR_NonZeroAllocPrefetch] = entryLabel->getCodeLocation();635636return cg->getBinaryBufferCursor() - PPC_INSTRUCTION_LENGTH;637}638639static TR::Instruction* genZeroInit(TR::CodeGenerator *cg, TR::Node *n, TR::Register *objStartReg, TR::Register *objEndReg, TR::Register *needsZeroInitCondReg,640TR::Register *iterReg, TR::Register *zeroReg, TR::Register *condReg, uint32_t initOffset, TR::Instruction *cursor)641{642TR_ASSERT_FATAL_WITH_NODE(n, initOffset <= UPPER_IMMED, "initOffset (%u) is too big to fit in a signed immediate field.", initOffset);643// Generates 24 instructions (+6 if DEBUG)644#if defined(DEBUG)645// Fill the object with junk to make sure zero-init is working646{647TR::LabelSymbol *loopStartLabel = generateLabelSymbol(cg);648649cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, iterReg, objStartReg, initOffset, cursor);650cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, zeroReg, -1, cursor);651652cursor = generateLabelInstruction(cg, TR::InstOpCode::label, n, loopStartLabel, cursor);653// XXX: This can be improved to use std on 64-bit, but we have to adjust for the size not being 8-byte aligned654cursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, n,655TR::MemoryReference::createWithDisplacement(cg, iterReg, 0, 4),656zeroReg, cursor);657cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, iterReg, iterReg, 4, cursor);658cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, condReg, iterReg, objEndReg, cursor);659cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::blt, n, loopStartLabel, condReg, cursor);660}661#endif662663TR::LabelSymbol *unrolledLoopStartLabel = generateLabelSymbol(cg);664TR::LabelSymbol *residueLoopStartLabel = generateLabelSymbol(cg);665TR::LabelSymbol *doneZeroInitLabel = generateLabelSymbol(cg);666667cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, needsZeroInitCondReg, cursor);668669cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, iterReg, objStartReg, initOffset, cursor);670// Use the zero reg temporarily to calculate unrolled loop iterations, equal to (stop - start) >> 5671cursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, n, zeroReg, iterReg, objEndReg, cursor);672cursor = generateShiftRightLogicalImmediate(cg, n, zeroReg, zeroReg, 5, cursor);673cursor = generateTrg1Src1ImmInstruction(cg,TR::InstOpCode::Op_cmpli, n, condReg, zeroReg, 0, cursor);674cursor = generateSrc1Instruction(cg, TR::InstOpCode::mtctr, n, zeroReg);675cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, zeroReg, 0, cursor);676cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, n, residueLoopStartLabel, condReg, cursor);677678cursor = generateLabelInstruction(cg, TR::InstOpCode::label, n, unrolledLoopStartLabel, cursor);679for (int i = 0; i < 32; i += 4)680cursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, n,681TR::MemoryReference::createWithDisplacement(cg, iterReg, i, 4),682zeroReg, cursor);683cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, iterReg, iterReg, 32, cursor);684cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bdnz, n, unrolledLoopStartLabel, /* Not used */ condReg, cursor);685686cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, condReg, iterReg, objEndReg, cursor);687cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bge, n, doneZeroInitLabel, condReg, cursor);688689// Residue loop690cursor = generateLabelInstruction(cg, TR::InstOpCode::label, n, residueLoopStartLabel, cursor);691cursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, n,692TR::MemoryReference::createWithDisplacement(cg, iterReg, 0, 4),693zeroReg, cursor);694cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, n, iterReg, iterReg, 4, cursor);695cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, condReg, iterReg, objEndReg, cursor);696cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::blt, n, residueLoopStartLabel, condReg, cursor);697698cursor = generateLabelInstruction(cg, TR::InstOpCode::label, n, doneZeroInitLabel, cursor);699700return cursor;701}702703static uint8_t* initializeCCPreLoadedWriteBarrier(uint8_t *buffer, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)704{705TR::Compilation *comp = cg->comp();706TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());707TR::Node *n = cg->getFirstInstruction()->getNode();708709// Write barrier710// In:711// r3 = dst object712// r4 = src object713// Out:714// none715// Clobbers:716// r3-r6, r11717// cr0, cr1718719cg->setFirstInstruction(NULL);720cg->setAppendInstruction(NULL);721722TR::Instruction *eyecatcher = generateImmInstruction(cg, TR::InstOpCode::dd, n, CCEYECATCHER('C', 'C', 'H', 2));723724TR::LabelSymbol *entryLabel = generateLabelSymbol(cg);725TR::LabelSymbol *helperTrampolineLabel = generateLabelSymbol(cg);726helperTrampolineLabel->setCodeLocation((uint8_t *)TR::CodeCacheManager::instance()->findHelperTrampoline(TR_writeBarrierStoreGenerational, buffer));727TR::Instruction *entry = generateLabelInstruction(cg, TR::InstOpCode::label, n, entryLabel);728TR::Instruction *cursor = entry;729TR::InstOpCode::Mnemonic Op_lclass = TR::InstOpCode::Op_load;730if (TR::Compiler->om.compressObjectReferences())731Op_lclass = TR::InstOpCode::lwz;732const TR::InstOpCode::Mnemonic rememberedClassMaskOp = J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST > UPPER_IMMED ||733J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST < LOWER_IMMED ? TR::InstOpCode::andis_r : TR::InstOpCode::andi_r;734const uint32_t rememberedClassMask = rememberedClassMaskOp == TR::InstOpCode::andis_r ?735J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST >> 16 : J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST;736737TR::Register *metaReg = cg->getMethodMetaDataRegister();738TR::Register *r3 = cg->machine()->getRealRegister(TR::RealRegister::gr3);739TR::Register *r4 = cg->machine()->getRealRegister(TR::RealRegister::gr4);740TR::Register *r5 = cg->machine()->getRealRegister(TR::RealRegister::gr5);741TR::Register *r6 = cg->machine()->getRealRegister(TR::RealRegister::gr6);742TR::Register *r11 = cg->machine()->getRealRegister(TR::RealRegister::gr11);743TR::Register *cr0 = cg->machine()->getRealRegister(TR::RealRegister::cr0);744TR::Register *cr1 = cg->machine()->getRealRegister(TR::RealRegister::cr1);745746TR_ASSERT_FATAL((J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST <= UPPER_IMMED && J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST >= LOWER_IMMED) ||747(J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST & 0xffff) == 0, "Expecting J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST to fit in immediate field");748TR_ASSERT_FATAL( rememberedClassMask <= 0xFFFF, "Expecting rememberedClassMask (%u) to fit in an unsigned immediate field.", rememberedClassMask);749750const bool constHeapBase = !comp->getOptions()->isVariableHeapBaseForBarrierRange0();751const bool constHeapSize = !comp->getOptions()->isVariableHeapSizeForBarrierRange0();752intptr_t heapBase;753intptr_t heapSize;754755if (comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapBase)756{757heapBase = comp->getOptions()->getHeapBaseForBarrierRange0();758cursor = loadAddressConstant(cg, false, n, heapBase, r5, cursor);759}760else761cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r5,762TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, heapBaseForBarrierRange0), TR::Compiler->om.sizeofReferenceAddress()),763cursor);764if (comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapSize)765{766heapSize = comp->getOptions()->getHeapSizeForBarrierRange0();767cursor = loadAddressConstant(cg, false, n, heapSize, r6, cursor);768}769else770cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r6,771TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, heapSizeForBarrierRange0), TR::Compiler->om.sizeofReferenceAddress()),772cursor);773cursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, n, r11, r5, r3, cursor);774cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r11, r6, cursor);775cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bgelr, n, NULL, cr0, cursor);776cursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, n, r11, r5, r4, cursor);777cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r11, r6, cursor);778cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bltlr, n, NULL, cr0, cursor);779cursor = generateTrg1MemInstruction(cg,Op_lclass, n, r11,780TR::MemoryReference::createWithDisplacement(cg, r3, TR::Compiler->om.offsetOfObjectVftField(), TR::Compiler->om.sizeofReferenceField()),781cursor);782cursor = generateTrg1Src1ImmInstruction(cg, rememberedClassMaskOp, n, r11, r11, cr0, rememberedClassMask, cursor);783cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bnelr, n, NULL, cr0, cursor);784cursor = generateLabelInstruction(cg, TR::InstOpCode::b, n, helperTrampolineLabel, cursor);785786performCCPreLoadedBinaryEncoding(buffer, cg);787788const uint32_t helperSize = 12 +789(comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapBase && heapBase > UPPER_IMMED && heapBase < LOWER_IMMED ? 1 : 0) +790(comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapSize && heapSize > UPPER_IMMED && heapSize < LOWER_IMMED ? 1 : 0);791TR_ASSERT(cg->getBinaryBufferCursor() - entryLabel->getCodeLocation() == helperSize * PPC_INSTRUCTION_LENGTH,792"Per-codecache write barrier, unexpected size");793794CCPreLoadedCodeTable[TR_writeBarrier] = entryLabel->getCodeLocation();795796return cg->getBinaryBufferCursor() - PPC_INSTRUCTION_LENGTH;797}798799static uint8_t* initializeCCPreLoadedWriteBarrierAndCardMark(uint8_t *buffer, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)800{801TR::Compilation *comp = cg->comp();802TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());803TR::Node *n = cg->getFirstInstruction()->getNode();804805// Write barrier and card mark806// In:807// r3 = dst object808// r4 = src object809// Out:810// none811// Clobbers:812// r3-r6, r11813// cr0, cr1814815cg->setFirstInstruction(NULL);816cg->setAppendInstruction(NULL);817818TR::Instruction *eyecatcher = generateImmInstruction(cg, TR::InstOpCode::dd, n, CCEYECATCHER('C', 'C', 'H', 3));819820TR::LabelSymbol *entryLabel = generateLabelSymbol(cg);821TR::LabelSymbol *doneCardMarkLabel = generateLabelSymbol(cg);822TR::LabelSymbol *helperTrampolineLabel = generateLabelSymbol(cg);823helperTrampolineLabel->setCodeLocation((uint8_t *)TR::CodeCacheManager::instance()->findHelperTrampoline(TR_writeBarrierStoreGenerationalAndConcurrentMark, buffer));824TR::Instruction *entry = generateLabelInstruction(cg, TR::InstOpCode::label, n, entryLabel);825TR::Instruction *cursor = entry;826TR::InstOpCode::Mnemonic Op_lclass = TR::InstOpCode::Op_load;827if (TR::Compiler->om.compressObjectReferences())828Op_lclass = TR::InstOpCode::lwz;829const TR::InstOpCode::Mnemonic cmActiveMaskOp = J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE > UPPER_IMMED ||830J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE < LOWER_IMMED ? TR::InstOpCode::andis_r : TR::InstOpCode::andi_r;831const uint32_t cmActiveMask = cmActiveMaskOp == TR::InstOpCode::andis_r ?832J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE >> 16 : J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;833const TR::InstOpCode::Mnemonic rememberedClassMaskOp = J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST > UPPER_IMMED ||834J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST < LOWER_IMMED ? TR::InstOpCode::andis_r : TR::InstOpCode::andi_r;835const uint32_t rememberedClassMask = rememberedClassMaskOp == TR::InstOpCode::andis_r ?836J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST >> 16 : J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST;837const uintptr_t cardTableShift = comp->target().is64Bit() ?838trailingZeroes((uint64_t)comp->getOptions()->getGcCardSize()) :839trailingZeroes((uint32_t)comp->getOptions()->getGcCardSize());840841TR::Register *metaReg = cg->getMethodMetaDataRegister();842TR::Register *r3 = cg->machine()->getRealRegister(TR::RealRegister::gr3);843TR::Register *r4 = cg->machine()->getRealRegister(TR::RealRegister::gr4);844TR::Register *r5 = cg->machine()->getRealRegister(TR::RealRegister::gr5);845TR::Register *r6 = cg->machine()->getRealRegister(TR::RealRegister::gr6);846TR::Register *r11 = cg->machine()->getRealRegister(TR::RealRegister::gr11);847TR::Register *cr0 = cg->machine()->getRealRegister(TR::RealRegister::cr0);848TR::Register *cr1 = cg->machine()->getRealRegister(TR::RealRegister::cr1);849850TR_ASSERT_FATAL((J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE <= UPPER_IMMED && J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE >= LOWER_IMMED) ||851(J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE & 0xffff) == 0, "Expecting J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE to fit in immediate field");852TR_ASSERT_FATAL((J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST <= UPPER_IMMED && J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST >= LOWER_IMMED) ||853(J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST & 0xffff) == 0, "Expecting J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST to fit in immediate field");854TR_ASSERT_FATAL( cmActiveMask <= 0xFFFF, "Expecting cmActiveMask (%u) to fit in an unsigned immediate field.", cmActiveMask);855TR_ASSERT_FATAL( rememberedClassMask <= 0xFFFF, "Expecting rememberedClassMask (%u) to fit in an unsigned immediate field.", rememberedClassMask);856857const bool constHeapBase = !comp->getOptions()->isVariableHeapBaseForBarrierRange0();858const bool constHeapSize = !comp->getOptions()->isVariableHeapSizeForBarrierRange0();859intptr_t heapBase;860intptr_t heapSize;861862if (comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapBase)863{864heapBase = comp->getOptions()->getHeapBaseForBarrierRange0();865cursor = loadAddressConstant(cg, false, n, heapBase, r5, cursor);866}867else868cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r5,869TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, heapBaseForBarrierRange0), TR::Compiler->om.sizeofReferenceAddress()),870cursor);871if (comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapSize)872{873heapSize = comp->getOptions()->getHeapSizeForBarrierRange0();874cursor = loadAddressConstant(cg, false, n, heapSize, r6, cursor);875}876else877cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r6,878TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, heapSizeForBarrierRange0), TR::Compiler->om.sizeofReferenceAddress()),879cursor);880cursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, n, r11, r5, r3, cursor);881cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r11, r6, cursor);882cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bgelr, n, NULL, cr0, cursor);883cursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, n, r5, r5, r4, cursor);884cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr1, r5, r6, cursor);885cursor = generateTrg1MemInstruction(cg, TR::InstOpCode::lwz, n, r6,886TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, privateFlags), 4),887cursor);888cursor = generateTrg1Src1ImmInstruction(cg, cmActiveMaskOp, n, r6, r6, cr0, cmActiveMask, cursor);889cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, n, doneCardMarkLabel, cr0, cursor);890cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r6,891TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, activeCardTableBase), TR::Compiler->om.sizeofReferenceAddress()),892cursor);893if (comp->target().is64Bit())894cursor = generateShiftRightLogicalImmediateLong(cg, n, r11, r11, cardTableShift, cursor);895else896cursor = generateShiftRightLogicalImmediate(cg, n, r11, r11, cardTableShift, cursor);897cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, r5, 1, cursor);898cursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stbx, n,899TR::MemoryReference::createWithIndexReg(cg, r6, r11, 1),900r5, cursor);901cursor = generateLabelInstruction(cg, TR::InstOpCode::label, n, doneCardMarkLabel, cursor);902cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bltlr, n, NULL, cr1, cursor);903cursor = generateTrg1MemInstruction(cg,Op_lclass, n, r11,904TR::MemoryReference::createWithDisplacement(cg, r3, TR::Compiler->om.offsetOfObjectVftField(), TR::Compiler->om.sizeofReferenceField()),905cursor);906cursor = generateTrg1Src1ImmInstruction(cg, rememberedClassMaskOp, n, r11, r11, cr0, rememberedClassMask, cursor);907cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bnelr, n, NULL, cr0, cursor);908cursor = generateLabelInstruction(cg, TR::InstOpCode::b, n, helperTrampolineLabel, cursor);909910performCCPreLoadedBinaryEncoding(buffer, cg);911912const uint32_t helperSize = 19 +913(comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapBase && heapBase > UPPER_IMMED && heapBase < LOWER_IMMED ? 1 : 0) +914(comp->target().is32Bit() && !comp->compileRelocatableCode() && constHeapSize && heapSize > UPPER_IMMED && heapSize < LOWER_IMMED ? 1 : 0);915TR_ASSERT(cg->getBinaryBufferCursor() - entryLabel->getCodeLocation() == helperSize * PPC_INSTRUCTION_LENGTH,916"Per-codecache write barrier with card mark, unexpected size");917918CCPreLoadedCodeTable[TR_writeBarrierAndCardMark] = entryLabel->getCodeLocation();919920return cg->getBinaryBufferCursor() - PPC_INSTRUCTION_LENGTH;921}922923static uint8_t* initializeCCPreLoadedCardMark(uint8_t *buffer, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)924{925TR::Compilation *comp = cg->comp();926TR::Node *n = cg->getFirstInstruction()->getNode();927928// Card mark929// In:930// r3 = dst object931// Out:932// none933// Clobbers:934// r4-r5, r11935// cr0936937cg->setFirstInstruction(NULL);938cg->setAppendInstruction(NULL);939940TR::Instruction *eyecatcher = generateImmInstruction(cg, TR::InstOpCode::dd, n, CCEYECATCHER('C', 'C', 'H', 4));941942TR::LabelSymbol *entryLabel = generateLabelSymbol(cg);943TR::Instruction *entry = generateLabelInstruction(cg, TR::InstOpCode::label, n, entryLabel);944TR::Instruction *cursor = entry;945const TR::InstOpCode::Mnemonic cmActiveMaskOp = J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE > UPPER_IMMED ||946J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE < LOWER_IMMED ? TR::InstOpCode::andis_r : TR::InstOpCode::andi_r;947const uint32_t cmActiveMask = cmActiveMaskOp == TR::InstOpCode::andis_r ?948J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE >> 16 : J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;949const uintptr_t cardTableShift = comp->target().is64Bit() ?950trailingZeroes((uint64_t)comp->getOptions()->getGcCardSize()) :951trailingZeroes((uint32_t)comp->getOptions()->getGcCardSize());952953TR::Register *metaReg = cg->getMethodMetaDataRegister();954TR::Register *r3 = cg->machine()->getRealRegister(TR::RealRegister::gr3);955TR::Register *r4 = cg->machine()->getRealRegister(TR::RealRegister::gr4);956TR::Register *r5 = cg->machine()->getRealRegister(TR::RealRegister::gr5);957TR::Register *r11 = cg->machine()->getRealRegister(TR::RealRegister::gr11);958TR::Register *cr0 = cg->machine()->getRealRegister(TR::RealRegister::cr0);959960TR_ASSERT_FATAL((J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE <= UPPER_IMMED && J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE >= LOWER_IMMED) ||961(J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE & 0xffff) == 0, "Expecting J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE to fit in immediate field");962TR_ASSERT_FATAL( cmActiveMask <= 0xFFFF, "Expecting cmActiveMask (%u) to fit in an unsigned immediate field.", cmActiveMask);963964cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r5,965TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, heapBaseForBarrierRange0), TR::Compiler->om.sizeofReferenceAddress()),966cursor);967cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r4,968TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, heapSizeForBarrierRange0), TR::Compiler->om.sizeofReferenceAddress()),969cursor);970cursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::subf, n, r5, r5, r3, cursor);971cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r5, r4, cursor);972cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bgelr, n, NULL, cr0, cursor);973// Incremental (i.e. balanced) always dirties the card974if (TR::Compiler->om.writeBarrierType() != gc_modron_wrtbar_cardmark_incremental)975{976cursor = generateTrg1MemInstruction(cg, TR::InstOpCode::lwz, n, r4,977TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, privateFlags), 4),978cursor);979cursor = generateTrg1Src1ImmInstruction(cg, cmActiveMaskOp, n, r4, r4, cr0, cmActiveMask, cursor);980cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);981}982cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r4,983TR::MemoryReference::createWithDisplacement(cg, metaReg, offsetof(struct J9VMThread, activeCardTableBase), TR::Compiler->om.sizeofReferenceAddress()),984cursor);985if (comp->target().is64Bit())986cursor = generateShiftRightLogicalImmediateLong(cg, n, r5, r5, cardTableShift, cursor);987else988cursor = generateShiftRightLogicalImmediate(cg, n, r5, r5, cardTableShift, cursor);989cursor = generateTrg1ImmInstruction(cg, TR::InstOpCode::li, n, r11, 1, cursor);990cursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stbx, n,991TR::MemoryReference::createWithIndexReg(cg, r4, r5, 1),992r11, cursor);993cursor = generateInstruction(cg, TR::InstOpCode::blr, n, cursor);994995performCCPreLoadedBinaryEncoding(buffer, cg);996997const uint32_t helperSize = TR::Compiler->om.writeBarrierType() != gc_modron_wrtbar_cardmark_incremental ? 13 : 10;998TR_ASSERT(cg->getBinaryBufferCursor() - entryLabel->getCodeLocation() == helperSize * PPC_INSTRUCTION_LENGTH,999"Per-codecache card mark, unexpected size");10001001CCPreLoadedCodeTable[TR_cardMark] = entryLabel->getCodeLocation();10021003return cg->getBinaryBufferCursor() - PPC_INSTRUCTION_LENGTH;1004}10051006static uint8_t* initializeCCPreLoadedArrayStoreCHK(uint8_t *buffer, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)1007{1008TR::Compilation *comp = cg->comp();1009TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());1010TR::Node *n = cg->getFirstInstruction()->getNode();10111012// Array store check1013// In:1014// r3 = dst object1015// r4 = src object1016// r11 = root class (j/l/Object)1017// Out:1018// none1019// Clobbers:1020// r5-r7, r111021// cr010221023cg->setFirstInstruction(NULL);1024cg->setAppendInstruction(NULL);10251026TR::Instruction *eyecatcher = generateImmInstruction(cg, TR::InstOpCode::dd, n, CCEYECATCHER('C', 'C', 'H', 7));10271028TR::LabelSymbol *entryLabel = generateLabelSymbol(cg);1029TR::LabelSymbol *skipSuperclassTestLabel = generateLabelSymbol(cg);1030TR::LabelSymbol *helperTrampolineLabel = generateLabelSymbol(cg);1031helperTrampolineLabel->setCodeLocation((uint8_t *)TR::CodeCacheManager::instance()->findHelperTrampoline(TR_typeCheckArrayStore, buffer));1032TR::Instruction *entry = generateLabelInstruction(cg, TR::InstOpCode::label, n, entryLabel);1033TR::Instruction *cursor = entry;1034TR::InstOpCode::Mnemonic Op_lclass = TR::InstOpCode::Op_load;1035if (TR::Compiler->om.compressObjectReferences())1036Op_lclass = TR::InstOpCode::lwz;10371038TR::Register *r3 = cg->machine()->getRealRegister(TR::RealRegister::gr3);1039TR::Register *r4 = cg->machine()->getRealRegister(TR::RealRegister::gr4);1040TR::Register *r5 = cg->machine()->getRealRegister(TR::RealRegister::gr5);1041TR::Register *r6 = cg->machine()->getRealRegister(TR::RealRegister::gr6);1042TR::Register *r7 = cg->machine()->getRealRegister(TR::RealRegister::gr7);1043TR::Register *r11 = cg->machine()->getRealRegister(TR::RealRegister::gr11);1044TR::Register *cr0 = cg->machine()->getRealRegister(TR::RealRegister::cr0);10451046cursor = generateTrg1MemInstruction(cg,Op_lclass, n, r5,1047TR::MemoryReference::createWithDisplacement(cg, r3, TR::Compiler->om.offsetOfObjectVftField(), TR::Compiler->om.sizeofReferenceField()),1048cursor);1049cursor = generateTrg1MemInstruction(cg,Op_lclass, n, r6,1050TR::MemoryReference::createWithDisplacement(cg, r4, TR::Compiler->om.offsetOfObjectVftField(), TR::Compiler->om.sizeofReferenceField()),1051cursor);1052cursor = TR::TreeEvaluator::generateVFTMaskInstruction(cg, n, r5, cursor);1053cursor = TR::TreeEvaluator::generateVFTMaskInstruction(cg, n, r6, cursor);1054cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r5,1055TR::MemoryReference::createWithDisplacement(cg, r5, offsetof(J9ArrayClass, componentType), TR::Compiler->om.sizeofReferenceAddress()),1056cursor);10571058cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r5, r6, cursor);1059cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);1060cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r7,1061TR::MemoryReference::createWithDisplacement(cg, r6, offsetof(J9Class, castClassCache), TR::Compiler->om.sizeofReferenceAddress()),1062cursor);1063cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r5, r7, cursor);1064cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);1065cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r5, r11, cursor);1066cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);10671068cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r7,1069TR::MemoryReference::createWithDisplacement(cg, r5, offsetof(J9Class, romClass), TR::Compiler->om.sizeofReferenceAddress()),1070cursor);1071cursor = generateTrg1MemInstruction(cg, TR::InstOpCode::lwz, n, r7,1072TR::MemoryReference::createWithDisplacement(cg, r7, offsetof(J9ROMClass, modifiers), 4),1073cursor);1074cursor = generateShiftRightLogicalImmediate(cg, n, r7, r7, 1, cursor);1075TR_ASSERT_FATAL(!(((J9AccClassArray | J9AccInterface) >> 1) & ~0xffff),1076"Expecting shifted ROM class modifiers to fit in immediate");1077cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, n, r7, r7, cr0, (J9AccClassArray | J9AccInterface) >> 1, cursor);1078cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bne, n, skipSuperclassTestLabel, cr0, cursor);10791080cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r7,1081TR::MemoryReference::createWithDisplacement(cg, r6, offsetof(J9Class, classDepthAndFlags), TR::Compiler->om.sizeofReferenceAddress()),1082cursor);1083TR_ASSERT_FATAL(!(J9AccClassDepthMask & ~0xffff),1084"Expecting class depth mask to fit in immediate");1085cursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, n, r7, r7, cr0, J9AccClassDepthMask, cursor);1086cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, n, skipSuperclassTestLabel, cr0, cursor);1087cursor = generateTrg1MemInstruction(cg,Op_lclass, n, r7,1088TR::MemoryReference::createWithDisplacement(cg, r6, offsetof(J9Class, superclasses), TR::Compiler->om.sizeofReferenceField()),1089cursor);1090cursor = generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, n, r7,1091TR::MemoryReference::createWithDisplacement(cg, r7, 0, TR::Compiler->om.sizeofReferenceAddress()),1092cursor);1093cursor = generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, n, cr0, r5, r7, cursor);1094cursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::beqlr, n, NULL, cr0, cursor);10951096cursor = generateLabelInstruction(cg, TR::InstOpCode::label, n, skipSuperclassTestLabel, cursor);1097cursor = generateLabelInstruction(cg, TR::InstOpCode::b, n, helperTrampolineLabel, cursor);10981099performCCPreLoadedBinaryEncoding(buffer, cg);11001101const uint32_t helperSize = 25;1102TR_ASSERT(cg->getBinaryBufferCursor() - entryLabel->getCodeLocation() == helperSize * PPC_INSTRUCTION_LENGTH,1103"Per-codecache array store check, unexpected size");11041105CCPreLoadedCodeTable[TR_arrayStoreCHK] = entryLabel->getCodeLocation();11061107return cg->getBinaryBufferCursor() - PPC_INSTRUCTION_LENGTH;1108}11091110void TR::createCCPreLoadedCode(uint8_t *CCPreLoadedCodeBase, uint8_t *CCPreLoadedCodeTop, void **CCPreLoadedCodeTable, TR::CodeGenerator *cg)1111{1112/* If you modify this make sure you update CCPreLoadedCodeSize above as well */11131114// We temporarily clobber the first and append instructions so we can use high level codegen to generate pre-loaded code1115// So save the original values here and restore them when done1116TR::Compilation *comp = cg->comp();1117if (comp->getOptions()->realTimeGC())1118return;11191120TR::Instruction *curFirst = cg->getFirstInstruction();1121TR::Instruction *curAppend = cg->getAppendInstruction();1122uint8_t *curBinaryBufferStart = cg->getBinaryBufferStart();1123uint8_t *curBinaryBufferCursor = cg->getBinaryBufferCursor();11241125uint8_t *buffer = (uint8_t *)CCPreLoadedCodeBase;11261127buffer = initializeCCPreLoadedPrefetch(buffer, CCPreLoadedCodeTable, cg);1128buffer = initializeCCPreLoadedNonZeroPrefetch(buffer + PPC_INSTRUCTION_LENGTH, CCPreLoadedCodeTable, cg);1129buffer = initializeCCPreLoadedWriteBarrier(buffer + PPC_INSTRUCTION_LENGTH, CCPreLoadedCodeTable, cg);1130if (comp->getOptions()->getGcCardSize() > 0)1131{1132buffer = initializeCCPreLoadedWriteBarrierAndCardMark(buffer + PPC_INSTRUCTION_LENGTH, CCPreLoadedCodeTable, cg);1133buffer = initializeCCPreLoadedCardMark(buffer + PPC_INSTRUCTION_LENGTH, CCPreLoadedCodeTable, cg);1134}1135buffer = initializeCCPreLoadedArrayStoreCHK(buffer + PPC_INSTRUCTION_LENGTH, CCPreLoadedCodeTable, cg);11361137// Other Code Cache Helper Initialization will go here11381139TR_ASSERT(buffer <= (uint8_t*)CCPreLoadedCodeTop, "Exceeded CodeCache Helper Area");11401141// Apply all of our relocations now before we sync1142TR::list<TR::Relocation*> &relocs = cg->getRelocationList();1143auto iterator = relocs.begin();1144while (iterator != relocs.end())1145{1146if ((*iterator)->getUpdateLocation() >= CCPreLoadedCodeBase &&1147(*iterator)->getUpdateLocation() <= CCPreLoadedCodeTop)1148{1149(*iterator)->apply(cg);1150iterator = relocs.erase(iterator);1151}1152else1153++iterator;1154}11551156#if defined(TR_HOST_POWER)1157ppcCodeSync((uint8_t *)CCPreLoadedCodeBase, buffer - (uint8_t *)CCPreLoadedCodeBase + 1);1158#endif11591160cg->setFirstInstruction(curFirst);1161cg->setAppendInstruction(curAppend);1162cg->setBinaryBufferStart(curBinaryBufferStart);1163cg->setBinaryBufferCursor(curBinaryBufferCursor);11641165}11661167uint8_t *TR::PPCAllocPrefetchSnippet::emitSnippetBody()1168{1169TR::Compilation *comp = cg()->comp();1170uint8_t *buffer = cg()->getBinaryBufferCursor();1171getSnippetLabel()->setCodeLocation(buffer);1172TR::InstOpCode opcode;11731174if (comp->getOptions()->realTimeGC())1175return NULL;11761177TR_ASSERT((uintptr_t)((cg()->getCodeCache())->getCCPreLoadedCodeAddress(TR_AllocPrefetch, cg())) != 0xDEADBEEF,1178"Invalid addr for code cache helper");1179intptr_t distance = (intptr_t)(cg()->getCodeCache())->getCCPreLoadedCodeAddress(TR_AllocPrefetch, cg())1180- (intptr_t)buffer;1181opcode.setOpCodeValue(TR::InstOpCode::b);1182buffer = opcode.copyBinaryToBuffer(buffer);1183*(int32_t *)buffer |= distance & 0x03FFFFFC;1184return buffer+PPC_INSTRUCTION_LENGTH;1185}11861187void1188TR::PPCAllocPrefetchSnippet::print(TR::FILE *pOutFile, TR_Debug * debug)1189{1190TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());1191uint8_t *cursor = getSnippetLabel()->getCodeLocation();11921193debug->printSnippetLabel(pOutFile, getSnippetLabel(), cursor, "Allocation Prefetch Snippet");11941195int32_t distance;11961197debug->printPrefix(pOutFile, NULL, cursor, 4);1198distance = *((int32_t *) cursor) & 0x03fffffc;1199distance = (distance << 6) >> 6; // sign extend1200trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t", (intptr_t)cursor + distance);1201}12021203uint32_t TR::PPCAllocPrefetchSnippet::getLength(int32_t estimatedCodeStart)1204{12051206if (cg()->comp()->getOptions()->realTimeGC())1207return 0;12081209return PPC_INSTRUCTION_LENGTH;1210}12111212TR::PPCNonZeroAllocPrefetchSnippet::PPCNonZeroAllocPrefetchSnippet(1213TR::CodeGenerator *codeGen,1214TR::Node *node,1215TR::LabelSymbol *callLabel)1216: TR::Snippet(codeGen, node, callLabel, false)1217{1218}12191220uint8_t *TR::PPCNonZeroAllocPrefetchSnippet::emitSnippetBody()1221{1222TR::Compilation *comp = cg()->comp();1223uint8_t *buffer = cg()->getBinaryBufferCursor();1224getSnippetLabel()->setCodeLocation(buffer);1225TR::InstOpCode opcode;12261227if (comp->getOptions()->realTimeGC())1228return NULL;12291230TR_ASSERT((uintptr_t)((cg()->getCodeCache())->getCCPreLoadedCodeAddress(TR_NonZeroAllocPrefetch, cg())) != 0xDEADBEEF,1231"Invalid addr for code cache helper");1232intptr_t distance = (intptr_t)(cg()->getCodeCache())->getCCPreLoadedCodeAddress(TR_NonZeroAllocPrefetch, cg())1233- (intptr_t)buffer;1234opcode.setOpCodeValue(TR::InstOpCode::b);1235buffer = opcode.copyBinaryToBuffer(buffer);1236*(int32_t *)buffer |= distance & 0x03FFFFFC;1237return buffer+PPC_INSTRUCTION_LENGTH;1238}12391240void1241TR::PPCNonZeroAllocPrefetchSnippet::print(TR::FILE *pOutFile, TR_Debug * debug)1242{1243TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());1244uint8_t *cursor = getSnippetLabel()->getCodeLocation();12451246debug->printSnippetLabel(pOutFile, getSnippetLabel(), cursor, "Non Zero TLH Allocation Prefetch Snippet");12471248int32_t distance;12491250debug->printPrefix(pOutFile, NULL, cursor, 4);1251distance = *((int32_t *) cursor) & 0x03fffffc;1252distance = (distance << 6) >> 6; // sign extend1253trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t", (intptr_t)cursor + distance);1254}12551256uint32_t TR::PPCNonZeroAllocPrefetchSnippet::getLength(int32_t estimatedCodeStart)1257{12581259if (cg()->comp()->getOptions()->realTimeGC())1260return 0;12611262return PPC_INSTRUCTION_LENGTH;1263}1264126512661267