Skip to content

Commit

Permalink
Merge pull request #42505 from gabilang/fix-type-cast-err-interop
Browse files Browse the repository at this point in the history
Fix checkcast generation for bundled function args
  • Loading branch information
warunalakshitha committed Apr 25, 2024
2 parents f4626c3 + 7248446 commit 95baf7c
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1430,16 +1430,17 @@ private void storeToVar(BIRNode.BIRVariableDcl varDcl) {
private void genResourcePathArgs(List<BIROperand> pathArgs) {
int pathVarArrayIndex = this.indexMap.addIfNotExists("$pathVarArray", symbolTable.anyType);
int bundledArrayIndex = this.indexMap.addIfNotExists("$pathArrayArgs", symbolTable.anyType);
genBundledArgs(pathArgs, pathVarArrayIndex, bundledArrayIndex, TYPE_ANYDATA_ARRAY);
genBundledArgs(pathArgs, pathVarArrayIndex, bundledArrayIndex, TYPE_ANYDATA_ARRAY, true);
}

private void genBundledFunctionArgs(List<BIROperand> args) {
int functionArgArrayIndex = this.indexMap.addIfNotExists("$functionArgArray", symbolTable.anyType);
int bundledArrayIndex = this.indexMap.addIfNotExists("$functionArrayArgs", symbolTable.anyType);
genBundledArgs(args, functionArgArrayIndex, bundledArrayIndex, TYPE_ANY_ARRAY);
genBundledArgs(args, functionArgArrayIndex, bundledArrayIndex, TYPE_ANY_ARRAY, false);
}

private void genBundledArgs(List<BIROperand> args, int argsArrayIndex, int bundledArrayIndex, String fieldName) {
private void genBundledArgs(List<BIROperand> args, int argsArrayIndex, int bundledArrayIndex, String fieldName,
boolean isFromPathArgs) {
mv.visitLdcInsn((long) args.size());
mv.visitInsn(L2I);
mv.visitTypeInsn(ANEWARRAY, OBJECT);
Expand All @@ -1451,7 +1452,13 @@ private void genBundledArgs(List<BIROperand> args, int argsArrayIndex, int bundl
mv.visitLdcInsn((long) i);
mv.visitInsn(L2I);
this.loadVar(arg.variableDcl);
jvmCastGen.generateCheckCastToAnyData(mv, arg.variableDcl.type);
if (isFromPathArgs) {
// Add CheckCast instruction for path args.
jvmCastGen.generateCheckCastToAnyData(mv, arg.variableDcl.type);
} else {
// Add Box instruction if the type is a value type.
jvmCastGen.addBoxInsn(mv, arg.variableDcl.type);
}
mv.visitInsn(AASTORE);
i++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@
import org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil;
import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable;
import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol;
import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols;
import org.wso2.ballerinalang.compiler.semantics.model.types.BArrayType;
import org.wso2.ballerinalang.compiler.semantics.model.types.BFiniteType;
import org.wso2.ballerinalang.compiler.semantics.model.types.BType;
import org.wso2.ballerinalang.compiler.semantics.model.types.BTypeReferenceType;
import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression;
import org.wso2.ballerinalang.compiler.util.TypeTags;
import org.wso2.ballerinalang.util.Flags;

import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
Expand Down Expand Up @@ -194,7 +196,7 @@ private boolean hasEquivalentPathAndFunctionParamCount(JMethodRequest jMethodReq
}
if (!isParamAssignableToBArray(paramTypes[count - 1]) || !isParamAssignableToBArray(paramTypes[count - 2])
|| isFirstPathParamARestParam(jMethodRequest, jMethod)
|| isFirstFunctionParamARestParam(jMethodRequest, jMethod)) {
|| isFunctionParamARestParam(jMethodRequest, jMethod)) {
return false;
}
if (count == 3) {
Expand Down Expand Up @@ -238,23 +240,21 @@ private boolean hasEquivalentPathParamCount(JMethodRequest jMethodRequest, JMeth
}

private boolean hasEquivalentFunctionParamCount(JMethodRequest jMethodRequest, JMethod jMethod) {
// Currently, this is only applicable for resource and remote methods which have empty path parameters.
// If path parameters are present, this will be handled by 'hasEquivalentPathAndFunctionParamCount' method
// by bundling both.
if (jMethodRequest.receiverType == null || jMethodRequest.pathParamCount != 0
|| jMethodRequest.bParamTypes.length == 0) {
return false;
}
// This is only applicable for resource and remote methods which have at least one function
// parameter other than path parameters and the bundling of path parameters is not required.
Class<?>[] paramTypes = jMethod.getParamTypes();
boolean isFirstParamServiceObject = jMethodRequest.bParamTypes[0].tag == TypeTags.SERVICE;
// Get the count of parameters of the resource/remote methods by excluding the receiver type.
int count = isFirstParamServiceObject ? paramTypes.length - 1 : paramTypes.length;
int reducedParamCount = isFirstParamServiceObject ? 2 : 1;
if (count < reducedParamCount || count > reducedParamCount + 2) {
int count = paramTypes.length;
int reducedParamCount = jMethodRequest.pathParamCount + 1;
int functionParamCount = getBFuncParamCount(jMethodRequest, jMethod) - jMethodRequest.pathParamCount;
// TODO: Remove 'Symbols.isFlagOn(jMethodRequest.bParamTypes[0].flags, Flags.SERVICE)' check after fixing
// https://github.com/ballerina-platform/ballerina-lang/issues/42456.
if (jMethodRequest.receiverType == null || functionParamCount < 1
|| count < reducedParamCount || count > reducedParamCount + 2
|| Symbols.isFlagOn(jMethodRequest.bParamTypes[0].flags, Flags.SERVICE)) {
return false;
}
if (!isParamAssignableToBArray(paramTypes[count - 1])
|| isFirstFunctionParamARestParam(jMethodRequest, jMethod)) {
|| isFunctionParamARestParam(jMethodRequest, jMethod)) {
return false;
}
if (count == reducedParamCount) {
Expand All @@ -263,10 +263,12 @@ private boolean hasEquivalentFunctionParamCount(JMethodRequest jMethodRequest, J
// This is for object interop functions when self is passed as a parameter
jMethod.setReceiverType(jMethodRequest.receiverType);
return true;
} else if (count == (reducedParamCount + 2)) {
// This is for object interop functions when both BalEnv and self is passed as parameters.
jMethod.setReceiverType(jMethodRequest.receiverType);
return jMethod.isBalEnvAcceptingMethod();
}
// This is for object interop functions when both BalEnv and self is passed as parameters.
jMethod.setReceiverType(jMethodRequest.receiverType);
return jMethod.isBalEnvAcceptingMethod();
return false;
}

private boolean isParamAssignableToBArray(Class<?> paramType) {
Expand Down Expand Up @@ -1045,10 +1047,11 @@ private boolean isFirstPathParamARestParam(JMethodRequest jMethodRequest, JMetho
jMethodRequest.bParamTypes[0].tag == TypeTags.HANDLE;
}

private boolean isFirstFunctionParamARestParam(JMethodRequest jMethodRequest, JMethod jMethod) {
return jMethod.isStatic() ? jMethodRequest.bParamTypes[jMethodRequest.pathParamCount].tag == TypeTags.ARRAY :
private boolean isFunctionParamARestParam(JMethodRequest jMethodRequest, JMethod jMethod) {
int funcParamCount = getBFuncParamCount(jMethodRequest, jMethod) - jMethodRequest.pathParamCount;
return (jMethod.isStatic() ? jMethodRequest.bParamTypes[jMethodRequest.pathParamCount].tag == TypeTags.ARRAY :
jMethodRequest.bParamTypes[jMethodRequest.pathParamCount + 1].tag == TypeTags.ARRAY &&
jMethodRequest.bParamTypes[0].tag == TypeTags.HANDLE;
jMethodRequest.bParamTypes[0].tag == TypeTags.HANDLE) && funcParamCount == 1;
}

private String getParamTypesAsString(ParamTypeConstraint[] constraints) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,38 @@ public isolated client class ClientObj {
isolated function getResourceMethod(service object {} serviceObject, string[] path) returns anydata = @java:Method {
'class: "org/ballerinalang/nativeimpl/jvm/tests/StaticMethods"
} external;

resource isolated function get albums/[int id](Person person, string s, typedesc<any> targetType = <>) returns
targetType|error = @java:Method {
'class: "org/ballerinalang/nativeimpl/jvm/tests/StaticMethods",
name: "getResource",
paramTypes: ["io.ballerina.runtime.api.Environment", "io.ballerina.runtime.api.values.BObject",
"io.ballerina.runtime.api.values.BArray", "io.ballerina.runtime.api.values.BArray"]
} external;

resource isolated function get albums(Person person, anydata[] a, string s, typedesc<any> targetType = <>) returns
targetType|error = @java:Method {
'class: "org/ballerinalang/nativeimpl/jvm/tests/StaticMethods",
name: "getResource",
paramTypes: ["io.ballerina.runtime.api.Environment", "io.ballerina.runtime.api.values.BObject",
"io.ballerina.runtime.api.values.BArray"]
} external;

resource isolated function get albums\-all\-2/[string version](A[] a, Person person, string? query = (), typedesc<any> targetType = <>) returns
targetType|error = @java:Method {
'class: "org/ballerinalang/nativeimpl/jvm/tests/StaticMethods",
name: "getResource",
paramTypes: ["io.ballerina.runtime.api.Environment", "io.ballerina.runtime.api.values.BObject",
"io.ballerina.runtime.api.values.BArray", "io.ballerina.runtime.api.values.BArray"]
} external;

resource isolated function get albums\-all\-3(Person person, A[] a, string? query = (), typedesc<any> targetType = <>) returns
targetType|error = @java:Method {
'class: "org/ballerinalang/nativeimpl/jvm/tests/StaticMethods",
name: "getResource",
paramTypes: ["io.ballerina.runtime.api.Environment", "io.ballerina.runtime.api.values.BObject",
"io.ballerina.runtime.api.values.BArray"]
} external;
}

public function testBundleFuncArgsToBArray() returns error? {
Expand All @@ -527,4 +559,12 @@ public function testBundleFuncArgsToBArray() returns error? {
test:assertEquals(res, 5);
res = cl.getResourceMethod(isolated service object {}, ["orderitem", "1234", "abcd"]);
test:assertEquals(res, 1000);
res = check cl->/albums/[1](new Person(29), "123");
test:assertEquals(res, 5);
res = check cl->/albums(new Person(29), [1, "abc"], "123");
test:assertEquals(res, 10);
res = check cl->/albums\-all\-2/["2.0"]([{id: 1, name: "John"}, {id: 2, name: "Josh"}], new Person(29));
test:assertEquals(res, 5);
res = check cl->/albums\-all\-3(new Person(29), [{id: 1, name: "John"}, {id: 2, name: "Josh"}]);
test:assertEquals(res, 10);
}

0 comments on commit 95baf7c

Please sign in to comment.