use of io.quarkus.qute.EvaluatedParams in project quarkus by quarkusio.
the class MessageBundleProcessor method implementResolve.
private void implementResolve(String defaultBundleImpl, ClassCreator bundleCreator, Map<String, MethodInfo> keyMap) {
MethodCreator resolve = bundleCreator.getMethodCreator("resolve", CompletionStage.class, EvalContext.class);
String resolveMethodPrefix = bundleCreator.getClassName().contains("/") ? bundleCreator.getClassName().substring(bundleCreator.getClassName().lastIndexOf('/') + 1) : bundleCreator.getClassName();
ResultHandle evalContext = resolve.getMethodParam(0);
ResultHandle name = resolve.invokeInterfaceMethod(Descriptors.GET_NAME, evalContext);
ResultHandle ret = resolve.newInstance(MethodDescriptor.ofConstructor(CompletableFuture.class));
// First handle dynamic messages, i.e. the "message" virtual method
BytecodeCreator dynamicMessage = resolve.ifTrue(resolve.invokeVirtualMethod(Descriptors.EQUALS, resolve.load(MESSAGE), name)).trueBranch();
ResultHandle evaluatedMessageKey = dynamicMessage.invokeStaticMethod(Descriptors.EVALUATED_PARAMS_EVALUATE_MESSAGE_KEY, evalContext);
ResultHandle paramsReady = dynamicMessage.readInstanceField(Descriptors.EVALUATED_PARAMS_STAGE, evaluatedMessageKey);
// Define function called when the message key is ready
FunctionCreator whenCompleteFun = dynamicMessage.createFunction(BiConsumer.class);
dynamicMessage.invokeInterfaceMethod(Descriptors.CF_WHEN_COMPLETE, paramsReady, whenCompleteFun.getInstance());
BytecodeCreator whenComplete = whenCompleteFun.getBytecode();
AssignableResultHandle whenThis = whenComplete.createVariable(DescriptorUtils.extToInt(bundleCreator.getClassName()));
whenComplete.assign(whenThis, dynamicMessage.getThis());
AssignableResultHandle whenRet = whenComplete.createVariable(CompletableFuture.class);
whenComplete.assign(whenRet, ret);
AssignableResultHandle whenEvalContext = whenComplete.createVariable(EvalContext.class);
whenComplete.assign(whenEvalContext, evalContext);
BranchResult throwableIsNull = whenComplete.ifNull(whenComplete.getMethodParam(1));
BytecodeCreator success = throwableIsNull.trueBranch();
// Return if the name is null or NOT_FOUND
ResultHandle resultNotFound = success.invokeStaticMethod(Descriptors.NOT_FOUND_FROM_EC, whenEvalContext);
BytecodeCreator nameIsNull = success.ifNull(whenComplete.getMethodParam(0)).trueBranch();
nameIsNull.invokeVirtualMethod(Descriptors.COMPLETABLE_FUTURE_COMPLETE, whenRet, resultNotFound);
nameIsNull.returnValue(null);
BytecodeCreator nameNotFound = success.ifTrue(success.invokeVirtualMethod(Descriptors.EQUALS, whenComplete.getMethodParam(0), resultNotFound)).trueBranch();
nameNotFound.invokeVirtualMethod(Descriptors.COMPLETABLE_FUTURE_COMPLETE, whenRet, resultNotFound);
nameNotFound.returnValue(null);
// Evaluate the rest of the params
ResultHandle evaluatedMessageParams = success.invokeStaticMethod(Descriptors.EVALUATED_PARAMS_EVALUATE_MESSAGE_PARAMS, whenEvalContext);
// Delegate to BundleClassName_resolve_0 (the first group of messages)
ResultHandle res0Ret = success.invokeVirtualMethod(MethodDescriptor.ofMethod(bundleCreator.getClassName(), resolveMethodPrefix + "_resolve_0", CompletableFuture.class, String.class, EvaluatedParams.class, CompletableFuture.class), whenThis, whenComplete.getMethodParam(0), evaluatedMessageParams, whenRet);
BytecodeCreator ret0Null = success.ifNull(res0Ret).trueBranch();
ret0Null.invokeVirtualMethod(Descriptors.COMPLETABLE_FUTURE_COMPLETE, whenRet, resultNotFound);
BytecodeCreator failure = throwableIsNull.falseBranch();
failure.invokeVirtualMethod(Descriptors.COMPLETABLE_FUTURE_COMPLETE_EXCEPTIONALLY, whenRet, whenComplete.getMethodParam(1));
whenComplete.returnValue(null);
// Return from the resolve method
dynamicMessage.returnValue(ret);
// Proceed with generated messages
// We do group messages to workaround limits of a JVM method body
ResultHandle evaluatedParams = resolve.invokeStaticMethod(Descriptors.EVALUATED_PARAMS_EVALUATE, evalContext);
final int groupLimit = 300;
int groupIndex = 0;
int resolveIndex = 0;
MethodCreator resolveGroup = null;
for (Entry<String, MethodInfo> entry : keyMap.entrySet()) {
if (resolveGroup == null || groupIndex++ >= groupLimit) {
groupIndex = 0;
String resolveMethodName = resolveMethodPrefix + "_resolve_" + resolveIndex++;
if (resolveGroup != null) {
// Delegate to the next "resolve_x" method
resolveGroup.returnValue(resolveGroup.invokeVirtualMethod(MethodDescriptor.ofMethod(bundleCreator.getClassName(), resolveMethodName, CompletableFuture.class, String.class, EvaluatedParams.class, CompletableFuture.class), resolveGroup.getThis(), resolveGroup.getMethodParam(0), resolveGroup.getMethodParam(1), resolveGroup.getMethodParam(2)));
}
resolveGroup = bundleCreator.getMethodCreator(resolveMethodName, CompletableFuture.class, String.class, EvaluatedParams.class, CompletableFuture.class).setModifiers(0);
if (resolveIndex == 1) {
ResultHandle resRet = resolve.invokeVirtualMethod(MethodDescriptor.ofMethod(bundleCreator.getClassName(), resolveMethodName, CompletableFuture.class, String.class, EvaluatedParams.class, CompletableFuture.class), resolve.getThis(), name, evaluatedParams, ret);
resolve.ifNotNull(resRet).trueBranch().returnValue(resRet);
}
}
addMessageMethod(resolveGroup, entry.getKey(), entry.getValue(), resolveGroup.getMethodParam(0), resolveGroup.getMethodParam(1), resolveGroup.getMethodParam(2), bundleCreator.getClassName());
}
if (resolveGroup != null) {
// Last group - return null
resolveGroup.returnValue(resolveGroup.loadNull());
}
if (defaultBundleImpl != null) {
resolve.returnValue(resolve.invokeSpecialMethod(MethodDescriptor.ofMethod(defaultBundleImpl, "resolve", CompletionStage.class, EvalContext.class), resolve.getThis(), evalContext));
} else {
resolve.returnValue(resolve.invokeStaticMethod(Descriptors.RESULTS_NOT_FOUND_EC, evalContext));
}
}
Aggregations