Skip to content

Commit

Permalink
Merge pull request #4086 from hzongaro/jni-bool
Browse files Browse the repository at this point in the history
Ensure boolean JNI methods on x86 produce a result of zero or one
  • Loading branch information
andrewcraik committed Jan 9, 2019
2 parents a7c7fb8 + e714ff7 commit dabbfd6
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 2 deletions.
17 changes: 17 additions & 0 deletions runtime/compiler/compile/J9SymbolReferenceTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,13 @@ static bool isSignatureTypeBool(const char *fieldSignature, int32_t len)
return len == 1 && fieldSignature[0] == 'Z';
}

static bool isSignatureReturnTypeBool(const char *methodSignature, int32_t len)
{
TR_ASSERT(len > 1, "Method signature is unexpectedly short %d", len);
// Method signature must end with ")Z" to have a boolean result type
return len > 1 && (')' == methodSignature[len-2]) && ('Z' == methodSignature[len-1]);
}

bool
J9::SymbolReferenceTable::isFieldTypeBool(TR::SymbolReference *symRef)
{
Expand All @@ -1309,6 +1316,16 @@ J9::SymbolReferenceTable::isStaticTypeBool(TR::SymbolReference *symRef)
return isSignatureTypeBool(fieldSignature, len);
}

bool
J9::SymbolReferenceTable::isReturnTypeBool(TR::SymbolReference *symRef)
{
TR_Method *method = symRef->getSymbol()->castToResolvedMethodSymbol()->getMethod();
char *methodSignature = method->signatureChars();
const int32_t len = method->signatureLength();
dumpOptDetails(comp(), "got method signature as %.*s\n", len, methodSignature);
return isSignatureReturnTypeBool(methodSignature, len);
}

static bool parmSlotCameFromExpandingAnArchetypeArgPlaceholder(int32_t slot, TR::ResolvedMethodSymbol *sym, TR_Memory *mem)
{
TR_ResolvedMethod *meth = sym->getResolvedMethod();
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/compile/J9SymbolReferenceTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ class SymbolReferenceTable : public OMR::SymbolReferenceTableConnector
bool isFieldClassObject(TR::SymbolReference *symRef);
bool isFieldTypeBool(TR::SymbolReference *symRef);
bool isStaticTypeBool(TR::SymbolReference *symRef);
bool isReturnTypeBool(TR::SymbolReference *symRef);
void addParameters(TR::ResolvedMethodSymbol * owningMethodSymbol);

// NO LONGER NEEDED? Disabled since inception (2009)
Expand Down
13 changes: 12 additions & 1 deletion runtime/compiler/x/amd64/codegen/AMD64JNILinkage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,14 +1181,25 @@ void TR::AMD64JNILinkage::cleanupReturnValue(
// type so that we sign and zero extend the narrower integer return types properly.
//
TR_X86OpCodes op;
TR::SymbolReference *callSymRef = callNode->getSymbolReference();
TR::ResolvedMethodSymbol *callSymbol = callNode->getSymbol()->castToResolvedMethodSymbol();
TR_ResolvedMethod *resolvedMethod = callSymbol->getResolvedMethod();

bool isUnsigned = resolvedMethod->returnTypeIsUnsigned();

switch (resolvedMethod->returnType())
{
case TR::Int8:
if (isUnsigned)
if (comp()->getSymRefTab()->isReturnTypeBool(callSymRef))
{
// For bool return type, must check whether value returned by
// JNI is zero (false) or non-zero (true) to yield Java result
generateRegRegInstruction(TEST1RegReg, callNode,
linkageReturnReg, linkageReturnReg, cg());
generateRegInstruction(SETNE1Reg, callNode, linkageReturnReg, cg());
op = TR::Compiler->target.is64Bit() ? MOVZXReg8Reg1 : MOVZXReg4Reg1;
}
else if (isUnsigned)
{
op = TR::Compiler->target.is64Bit() ? MOVZXReg8Reg1 : MOVZXReg4Reg1;
}
Expand Down
12 changes: 11 additions & 1 deletion runtime/compiler/x/i386/codegen/IA32JNILinkage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,20 @@ TR::Register *TR::IA32JNILinkage::buildJNIDispatch(TR::Node *callNode)
// type so that we sign and zero extend the narrower integer return types properly.
//
bool isUnsigned = resolvedMethod->returnTypeIsUnsigned();
bool isBoolean;
switch (resolvedMethod->returnType())
{
case TR::Int8:
generateRegRegInstruction(isUnsigned ? MOVZXReg4Reg1 : MOVSXReg4Reg1,
isBoolean = comp()->getSymRefTab()->isReturnTypeBool(callSymRef);
if (isBoolean)
{
// For bool return type, must check whether value returned by
// JNI is zero (false) or non-zero (true) to yield Java result
generateRegRegInstruction(TEST1RegReg, callNode, eaxReal, eaxReal, cg());
generateRegInstruction(SETNE1Reg, callNode, eaxReal, cg());
}
generateRegRegInstruction((isUnsigned || isBoolean)
? MOVZXReg4Reg1 : MOVSXReg4Reg1,
callNode, ecxReal, eaxReal, cg());
break;
case TR::Int16:
Expand Down

0 comments on commit dabbfd6

Please sign in to comment.