Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 36 additions & 12 deletions runtime/compiler/p/codegen/CallSnippet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "il/Node_inlines.hpp"
#include "p/codegen/PPCAOTRelocation.hpp"
#include "p/codegen/PPCTableOfConstants.hpp"
#include "p/codegen/PPCJ9HelperCallSnippet.hpp"
#include "runtime/CodeCacheManager.hpp"

uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
Expand All @@ -47,8 +48,13 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
TR::Linkage* linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());
const TR::PPCLinkageProperties &linkageProperties = linkage->getProperties();
int32_t argStart = callNode->getFirstArgumentIndex();
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp);
if (isJitDispatchJ9Method) {
argStart += 1;
}

if (linkageProperties.getRightToLeft())
bool rightToLeft = linkageProperties.getRightToLeft() && !isJitDispatchJ9Method;
if (rightToLeft)
offset = linkage->getOffsetToFirstParm();
else
offset = argSize+linkage->getOffsetToFirstParm();
Expand All @@ -61,29 +67,29 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
case TR::Int8:
case TR::Int16:
case TR::Int32:
if (!linkageProperties.getRightToLeft())
if (!rightToLeft)
offset -= TR::Compiler->om.sizeofReferenceAddress();
if (intArgNum < linkageProperties.getNumIntArgRegs())
{
buffer = storeArgumentItem(TR::InstOpCode::stw, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
}
intArgNum++;
if (linkageProperties.getRightToLeft())
if (rightToLeft)
offset += TR::Compiler->om.sizeofReferenceAddress();
break;
case TR::Address:
if (!linkageProperties.getRightToLeft())
if (!rightToLeft)
offset -= TR::Compiler->om.sizeofReferenceAddress();
if (intArgNum < linkageProperties.getNumIntArgRegs())
{
buffer = storeArgumentItem(storeGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
}
intArgNum++;
if (linkageProperties.getRightToLeft())
if (rightToLeft)
offset += TR::Compiler->om.sizeofReferenceAddress();
break;
case TR::Int64:
if (!linkageProperties.getRightToLeft())
if (!rightToLeft)
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
if (intArgNum < linkageProperties.getNumIntArgRegs())
{
Expand All @@ -97,29 +103,29 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
}
}
intArgNum += comp->target().is64Bit() ? 1 : 2;
if (linkageProperties.getRightToLeft())
if (rightToLeft)
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
break;
case TR::Float:
if (!linkageProperties.getRightToLeft())
if (!rightToLeft)
offset -= TR::Compiler->om.sizeofReferenceAddress();
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
{
buffer = storeArgumentItem(TR::InstOpCode::stfs, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
}
floatArgNum++;
if (linkageProperties.getRightToLeft())
if (rightToLeft)
offset += TR::Compiler->om.sizeofReferenceAddress();
break;
case TR::Double:
if (!linkageProperties.getRightToLeft())
if (!rightToLeft)
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
{
buffer = storeArgumentItem(TR::InstOpCode::stfd, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
}
floatArgNum++;
if (linkageProperties.getRightToLeft())
if (rightToLeft)
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
break;
}
Expand Down Expand Up @@ -328,6 +334,25 @@ TR_RuntimeHelper TR::PPCCallSnippet::getInterpretedDispatchHelper(
}
}

uint8_t *TR::PPCJ9HelperCallSnippet::emitSnippetBody() {
uint8_t *buffer = cg()->getBinaryBufferCursor();
uint8_t *gtrmpln, *trmpln;

getSnippetLabel()->setCodeLocation(buffer);
buffer = flushArgumentsToStack(buffer, this->getNode(), this->getSizeOfArguments(), cg());

if (this->getNode()->isJitDispatchJ9MethodCall(cg()->comp()))
{
// move value in r11 to r3 for the interpreter
// or r11 r3 r11 444 0
// 011111 01011 00011 01011 0110111100 0
*(int32_t *)buffer = 0x7D635B78;
buffer += 4;
}

return this->genHelperCall(buffer);
}

uint8_t *TR::PPCCallSnippet::emitSnippetBody()
{

Expand Down Expand Up @@ -1642,4 +1667,3 @@ TR_Debug::print(TR::FILE *pOutFile, TR::PPCInterfaceCallSnippet * snippet)
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; J2I thunk address for private", *(intptr_t *)cursor);
}

10 changes: 10 additions & 0 deletions runtime/compiler/p/codegen/J9CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,3 +832,13 @@ J9::Power::CodeGenerator::deriveCallingLinkage(TR::Node *node, bool isIndirect)

return self()->getLinkage(callee->getLinkageConvention());
}

bool
J9::Power::CodeGenerator::supportsNonHelper(TR::SymbolReferenceTable::CommonNonhelperSymbol symbol)
{
if (symbol == TR::SymbolReferenceTable::jitDispatchJ9MethodSymbol)
{
return true;
}
return J9::CodeGenerator::supportsNonHelper(symbol);
}
2 changes: 2 additions & 0 deletions runtime/compiler/p/codegen/J9CodeGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ class OMR_EXTENSIBLE CodeGenerator : public J9::CodeGenerator

bool canEmitDataForExternallyRelocatableInstructions();

bool supportsNonHelper(TR::SymbolReferenceTable::CommonNonhelperSymbol symbol);

#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION
bool suppressInliningOfCryptoMethod(TR::RecognizedMethod method);
bool inlineCryptoMethod(TR::Node *node, TR::Register *&resultReg);
Expand Down
51 changes: 51 additions & 0 deletions runtime/compiler/p/codegen/PPCJ9HelperCallSnippet.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*******************************************************************************
* Copyright IBM Corp. and others 2000
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/

#ifndef PPCJ9HELPERCALLSNIPPET_INCL
#define PPCJ9HELPERCALLSNIPPET_INCL

#include "codegen/Snippet.hpp"
#include "codegen/PPCHelperCallSnippet.hpp"
#include "env/VMJ9.h"
#include "infra/Annotations.hpp"
#include "p/codegen/PPCInstruction.hpp"

namespace TR { class CodeGenerator; }

namespace TR {

class PPCJ9HelperCallSnippet : public TR::PPCHelperCallSnippet {
int32_t _argSize;

public:
PPCJ9HelperCallSnippet(TR::CodeGenerator *cg, TR::Node *node, TR::LabelSymbol *snippetlab,
TR::SymbolReference *helper, TR::LabelSymbol *restartLabel = NULL, int32_t argSize = -1)
: TR::PPCHelperCallSnippet(cg, node, snippetlab, helper, restartLabel)
, _argSize(argSize)
{}

int32_t getSizeOfArguments() { return _argSize; }
virtual uint8_t *emitSnippetBody();
};
}

#endif
107 changes: 101 additions & 6 deletions runtime/compiler/p/codegen/PPCPrivateLinkage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "il/TreeTop.hpp"
#include "il/TreeTop_inlines.hpp"
#include "p/codegen/CallSnippet.hpp"
#include "p/codegen/PPCJ9HelperCallSnippet.hpp"
#include "p/codegen/GenerateInstructions.hpp"
#include "p/codegen/PPCEvaluator.hpp"
#include "p/codegen/PPCHelperCallSnippet.hpp"
Expand Down Expand Up @@ -372,7 +373,7 @@ J9::Power::PrivateLinkage::PrivateLinkage(TR::CodeGenerator *cg)
}
_properties._computedCallTargetRegister = TR::RealRegister::gr0; // gr11 = interface, gr12 = virtual, so we need something else for computed
_properties._vtableIndexArgumentRegister = TR::RealRegister::gr12;
_properties._j9methodArgumentRegister = TR::RealRegister::gr3; // TODO:JSR292: Confirm
_properties._j9methodArgumentRegister = TR::RealRegister::gr11; // TODO:JSR292: Confirm
}

const TR::PPCLinkageProperties& J9::Power::PrivateLinkage::getProperties()
Expand Down Expand Up @@ -1466,10 +1467,11 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
TR_Array<TR::Register *>& tempLongRegisters = cg()->getTransientLongRegisters();
TR::MethodSymbol *callSymbol = callNode->getSymbol()->castToMethodSymbol();

bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp());
bool isHelperCall = linkage == TR_Helper || linkage == TR_CHelper;
bool rightToLeft = isHelperCall &&
//we want the arguments for induceOSR to be passed from left to right as in any other non-helper call
!callNode->getSymbolReference()->isOSRInductionHelper();
!callNode->getSymbolReference()->isOSRInductionHelper() && !isJitDispatchJ9Method;

if (rightToLeft)
{
Expand Down Expand Up @@ -1511,6 +1513,11 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
break;
}

if (isJitDispatchJ9Method)
{
specialArgReg = getProperties().getJ9MethodArgumentRegister();
}

if (specialArgReg != TR::RealRegister::NoReg)
{
if (comp()->getOption(TR_TraceCG))
Expand All @@ -1531,6 +1538,7 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
totalSize += TR::Compiler->om.sizeofReferenceAddress();
}

// will not process special args
for (int32_t i = from; (rightToLeft && i >= to) || (!rightToLeft && i <= to); i += step)
{
child = callNode->getChild(i);
Expand Down Expand Up @@ -1585,8 +1593,20 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
pushToMemory = new (trStackMemory()) TR::PPCMemoryArgument[memArgs];
}

if (specialArgReg)
if (specialArgReg && !isJitDispatchJ9Method)
{
from -= step; // we do want to process special args in the following loop
}
else if (specialArgReg && isJitDispatchJ9Method)
{
TR::Register *targetReg = cg()->evaluate(callNode->getChild(0));
dependencies->addPreCondition(targetReg, specialArgReg);
}

if (isJitDispatchJ9Method)
{
TR_ASSERT_FATAL(from == step, "should skip first child for jitDispatchJ9Method\n");
}

numIntegerArgs = 0;
numFloatArgs = 0;
Expand All @@ -1611,7 +1631,7 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
TR::MemoryReference *mref = NULL;
TR::Register *argRegister;
child = callNode->getChild(i);
bool isSpecialArg = (i == from && specialArgReg != TR::RealRegister::NoReg);
bool isSpecialArg = (i == from && specialArgReg != TR::RealRegister::NoReg) && !isJitDispatchJ9Method;
switch (child->getDataType())
{
case TR::Int8:
Expand Down Expand Up @@ -2868,20 +2888,95 @@ void J9::Power::PrivateLinkage::buildDirectCall(TR::Node *callNode,
TR::ResolvedMethodSymbol *sym = callSymbol->getResolvedMethodSymbol();
TR_ResolvedMethod *vmm = (sym==NULL)?NULL:sym->getResolvedMethod();
bool myself = comp()->isRecursiveMethodTarget(vmm);
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp());

TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp()->fe());

if (callSymRef->getReferenceNumber() >= TR_PPCnumRuntimeHelpers)
if ((callSymRef->getReferenceNumber() >= TR_PPCnumRuntimeHelpers) && !isJitDispatchJ9Method)
fej9->reserveTrampolineIfNecessary(comp(), callSymRef, false);

bool forceUnresolvedDispatch = !fej9->isResolvedDirectDispatchGuaranteed(comp());
if ((callSymbol->isJITInternalNative() ||
if (!isJitDispatchJ9Method && (callSymbol->isJITInternalNative() ||
(!callSymRef->isUnresolved() && !callSymbol->isInterpreted() && ((forceUnresolvedDispatch && callSymbol->isHelper()) || !forceUnresolvedDispatch))))
{
gcPoint = generateDepImmSymInstruction(cg(), TR::InstOpCode::bl, callNode,
myself?0:(uintptr_t)callSymbol->getMethodAddress(),
dependencies, callSymRef?callSymRef:callNode->getSymbolReference());
}
else if (isJitDispatchJ9Method)
{
auto flags = pp.getPreservedRegisterMapForGC();
// we do not want gr11 in the gc map since this will not contain any object reference
flags ^= 1 << pp.getJ9MethodArgumentRegister();

TR::Register *scratchReg = dependencies->searchPostConditionRegister(pp.getVTableIndexArgumentRegister());
TR::Register *scratchReg2 = cg()->allocateRegister();
TR::Register *cndReg = dependencies->searchPreConditionRegister(TR::RealRegister::cr0);
TR::Register *j9MethodReg = callNode->getChild(0)->getRegister();

TR::LabelSymbol *startICFLabel = generateLabelSymbol(cg());
TR::LabelSymbol *doneLabel = generateLabelSymbol(cg());
TR::LabelSymbol *oolLabel = generateLabelSymbol(cg());
startICFLabel->setStartInternalControlFlow();
doneLabel->setEndInternalControlFlow();

TR::RegisterDependencyConditions *preDeps = dependencies->clone(cg());
preDeps->setNumPostConditions(0, trMemory());
preDeps->setAddCursorForPost(0);

TR::RegisterDependencyConditions *newPostDeps = new (trHeapMemory()) TR::RegisterDependencyConditions(0, 2, trMemory());
newPostDeps->addPostCondition(j9MethodReg, TR::RealRegister::NoReg);
newPostDeps->addPostCondition(scratchReg2,TR::RealRegister::NoReg);

TR::RegisterDependencyConditions *postDeps = dependencies->clone(cg(), newPostDeps);
postDeps->setNumPreConditions(0, trMemory());
postDeps->setAddCursorForPre(0);

TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg());
TR::SymbolReference *helperRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_j2iTransition);
TR::Snippet *interpCallSnippet = new (cg()->trHeapMemory()) TR::PPCJ9HelperCallSnippet(cg(), callNode, snippetLabel, helperRef, doneLabel, argSize);
interpCallSnippet->gcMap().setGCRegisterMask(flags);
cg()->addSnippet(interpCallSnippet);

TR_PPCOutOfLineCodeSection *snippetCall = new (cg()->trHeapMemory()) TR_PPCOutOfLineCodeSection(oolLabel, doneLabel, cg());
cg()->getPPCOutOfLineCodeSectionList().push_front(snippetCall);
snippetCall->swapInstructionListsWithCompilation();
TR::Instruction *OOLLabelInstr = generateLabelInstruction(cg(), TR::InstOpCode::label, callNode, oolLabel);
gcPoint = generateDepLabelInstruction(cg(), TR::InstOpCode::bl, callNode, snippetLabel, dependencies);
gcPoint->PPCNeedsGCMap(flags);
generateLabelInstruction(cg(), TR::InstOpCode::b, callNode, doneLabel);
// helper snippet sets up jump back to doneLabel
snippetCall->swapInstructionListsWithCompilation();

generateDepLabelInstruction(cg(), TR::InstOpCode::label, callNode, startICFLabel, preDeps);

// test if compiled
generateTrg1MemInstruction(cg(), TR::InstOpCode::Op_load, callNode, scratchReg,
TR::MemoryReference::createWithDisplacement(cg(), j9MethodReg, offsetof(J9Method, extra), TR::Compiler->om.sizeofReferenceAddress()));
generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::andi_r, callNode, scratchReg2, scratchReg, 1);
// branch to ool if J9_STARTPC_NOT_TRANSLATED is set
gcPoint = generateConditionalBranchInstruction(cg(), TR::InstOpCode::bne, callNode, oolLabel, cndReg);
gcPoint->PPCNeedsGCMap(flags);

// compiled - jump to jit entry point
generateTrg1MemInstruction(cg(), TR::InstOpCode::Op_load, callNode, j9MethodReg,
TR::MemoryReference::createWithDisplacement(cg(), scratchReg, -4, TR::Compiler->om.sizeofReferenceAddress()));
generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::srawi, callNode, j9MethodReg, j9MethodReg, 16);
if (comp()->target().is64Bit())
{
generateTrg1Src1Instruction(cg(), TR::InstOpCode::extsw, callNode, j9MethodReg, j9MethodReg);
}
generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, callNode, scratchReg, j9MethodReg, scratchReg);
generateSrc1Instruction(cg(), TR::InstOpCode::mtctr, callNode, scratchReg);
gcPoint = generateInstruction(cg(), TR::InstOpCode::bctrl, callNode);
gcPoint->PPCNeedsGCMap(flags);

cg()->stopUsingRegister(scratchReg);
cg()->stopUsingRegister(scratchReg2);
cg()->stopUsingRegister(cndReg);
generateDepLabelInstruction(cg(), TR::InstOpCode::label, callNode, doneLabel, postDeps);
return;
}
else
{
TR::LabelSymbol *label = generateLabelSymbol(cg());
Expand Down