diff --git a/runtime/compiler/compile/J9SymbolReferenceTable.cpp b/runtime/compiler/compile/J9SymbolReferenceTable.cpp index 1942fefa04f..0ea5033ac50 100644 --- a/runtime/compiler/compile/J9SymbolReferenceTable.cpp +++ b/runtime/compiler/compile/J9SymbolReferenceTable.cpp @@ -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) { @@ -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(); diff --git a/runtime/compiler/compile/J9SymbolReferenceTable.hpp b/runtime/compiler/compile/J9SymbolReferenceTable.hpp index ca3d11abe08..a23d79253ab 100644 --- a/runtime/compiler/compile/J9SymbolReferenceTable.hpp +++ b/runtime/compiler/compile/J9SymbolReferenceTable.hpp @@ -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) diff --git a/runtime/compiler/x/amd64/codegen/AMD64JNILinkage.cpp b/runtime/compiler/x/amd64/codegen/AMD64JNILinkage.cpp index eb120896ab8..4d5d391db67 100644 --- a/runtime/compiler/x/amd64/codegen/AMD64JNILinkage.cpp +++ b/runtime/compiler/x/amd64/codegen/AMD64JNILinkage.cpp @@ -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; } diff --git a/runtime/compiler/x/i386/codegen/IA32JNILinkage.cpp b/runtime/compiler/x/i386/codegen/IA32JNILinkage.cpp index 9280f95b1c6..17249f91c74 100644 --- a/runtime/compiler/x/i386/codegen/IA32JNILinkage.cpp +++ b/runtime/compiler/x/i386/codegen/IA32JNILinkage.cpp @@ -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: