From 077092d619bbaba52f77a2e18246cd5bc2be59d1 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 13 Jun 2019 12:49:47 +0200 Subject: [PATCH] Convert TailRecursionCodegen.java to Kotlin --- .../kotlin/codegen/TailRecursionCodegen.kt | 185 ++++++++---------- 1 file changed, 81 insertions(+), 104 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt index 8538efa9e12..8d44ef0bc1f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt @@ -14,145 +14,122 @@ * limitations under the License. */ -package org.jetbrains.kotlin.codegen; +package org.jetbrains.kotlin.codegen -import com.google.common.collect.Lists; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.cfg.TailRecursionKind; -import org.jetbrains.kotlin.codegen.context.MethodContext; -import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt; -import org.jetbrains.kotlin.codegen.state.GenerationState; -import org.jetbrains.kotlin.descriptors.CallableDescriptor; -import org.jetbrains.kotlin.descriptors.FunctionDescriptor; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; -import org.jetbrains.kotlin.psi.KtExpression; -import org.jetbrains.kotlin.psi.KtSimpleNameExpression; -import org.jetbrains.kotlin.psi.ValueArgument; -import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; -import org.jetbrains.kotlin.resolve.calls.model.*; -import org.jetbrains.org.objectweb.asm.Type; -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; +import com.google.common.collect.Lists +import org.jetbrains.kotlin.cfg.TailRecursionKind +import org.jetbrains.kotlin.codegen.context.MethodContext +import org.jetbrains.kotlin.codegen.coroutines.* +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.psi.ValueArgument +import org.jetbrains.kotlin.resolve.calls.callUtil.* +import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter -import java.util.List; +import org.jetbrains.kotlin.resolve.BindingContext.TAIL_RECURSION_CALL -import static org.jetbrains.kotlin.resolve.BindingContext.TAIL_RECURSION_CALL; +class TailRecursionCodegen( + private val context: MethodContext, + private val codegen: ExpressionCodegen, + private val v: InstructionAdapter, + private val state: GenerationState +) { -public class TailRecursionCodegen { - - @NotNull - private final MethodContext context; - @NotNull - private final ExpressionCodegen codegen; - @NotNull - private final InstructionAdapter v; - @NotNull - private final GenerationState state; - - public TailRecursionCodegen( - @NotNull MethodContext context, - @NotNull ExpressionCodegen codegen, - @NotNull InstructionAdapter v, - @NotNull GenerationState state - ) { - this.context = context; - this.codegen = codegen; - this.v = v; - this.state = state; + fun isTailRecursion(resolvedCall: ResolvedCall<*>): Boolean { + val status = state.bindingContext.get(TAIL_RECURSION_CALL, resolvedCall.call) + return status != null && status.isDoGenerateTailRecursion } - public boolean isTailRecursion(@NotNull ResolvedCall resolvedCall) { - TailRecursionKind status = state.getBindingContext().get(TAIL_RECURSION_CALL, resolvedCall.getCall()); - return status != null && status.isDoGenerateTailRecursion(); - } + fun generateTailRecursion(resolvedCall: ResolvedCall<*>) { + val fd = resolvedCall.resultingDescriptor.unwrapInitialDescriptorForSuspendFunction().let { + it as? FunctionDescriptor + ?: error("Resolved call doesn't refer to the function descriptor: $it") + } + val callable = codegen.resolveToCallable(fd, false, resolvedCall) as CallableMethod - public void generateTailRecursion(ResolvedCall resolvedCall) { - CallableDescriptor fd = CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(resolvedCall.getResultingDescriptor()); - assert fd instanceof FunctionDescriptor : "Resolved call doesn't refer to the function descriptor: " + fd; - CallableMethod callable = (CallableMethod) codegen.resolveToCallable((FunctionDescriptor) fd, false, resolvedCall); + val arguments = resolvedCall.valueArgumentsByIndex ?: throw IllegalStateException("Failed to arrange value arguments by index: $fd") - List arguments = resolvedCall.getValueArgumentsByIndex(); - if (arguments == null) { - throw new IllegalStateException("Failed to arrange value arguments by index: " + fd); + if (fd.isSuspend) { + AsmUtil.pop(v, callable.getValueParameters()[callable.getValueParameters().size - 1].asmType) } - if (((FunctionDescriptor) fd).isSuspend()) { - AsmUtil.pop(v, callable.getValueParameters().get(callable.getValueParameters().size() - 1).getAsmType()); - } - - assignParameterValues(fd, callable, arguments); - if (callable.getExtensionReceiverType() != null) { - if (resolvedCall.getExtensionReceiver() != fd.getExtensionReceiverParameter().getValue()) { - StackValue expression = context.getReceiverExpression(codegen.typeMapper); - expression.store(StackValue.onStack(callable.getExtensionReceiverType()), v, true); - } - else { - AsmUtil.pop(v, callable.getExtensionReceiverType()); + assignParameterValues(fd, callable, arguments) + if (callable.extensionReceiverType != null) { + if (resolvedCall.extensionReceiver != fd.extensionReceiverParameter!!.value) { + val expression = context.getReceiverExpression(codegen.typeMapper) + expression.store(StackValue.onStack(callable.extensionReceiverType), v, true) + } else { + AsmUtil.pop(v, callable.extensionReceiverType) } } - if (callable.getDispatchReceiverType() != null) { - AsmUtil.pop(v, callable.getDispatchReceiverType()); + if (callable.dispatchReceiverType != null) { + AsmUtil.pop(v, callable.dispatchReceiverType) } - v.goTo(context.getMethodStartLabel()); + v.goTo(context.methodStartLabel) } - private void assignParameterValues( - CallableDescriptor fd, - CallableMethod callableMethod, - List valueArguments + private fun assignParameterValues( + fd: CallableDescriptor, + callableMethod: CallableMethod, + valueArguments: List ) { - List types = callableMethod.getValueParameterTypes(); - for (ValueParameterDescriptor parameterDescriptor : Lists.reverse(fd.getValueParameters())) { - ResolvedValueArgument arg = valueArguments.get(parameterDescriptor.getIndex()); - Type type = types.get(parameterDescriptor.getIndex()); + val types = callableMethod.valueParameterTypes + loop@ for (parameterDescriptor in fd.valueParameters.asReversed()) { + val arg = valueArguments[parameterDescriptor.index] + val type = types[parameterDescriptor.index] - if (arg instanceof ExpressionValueArgument) { - ExpressionValueArgument ev = (ExpressionValueArgument) arg; - ValueArgument argument = ev.getValueArgument(); - KtExpression argumentExpression = argument == null ? null : argument.getArgumentExpression(); + when (arg) { + is ExpressionValueArgument -> { + val argumentExpression = arg.valueArgument?.getArgumentExpression() - if (argumentExpression instanceof KtSimpleNameExpression) { - ResolvedCall resolvedCall = CallUtilKt.getResolvedCall(argumentExpression, state.getBindingContext()); - if (resolvedCall != null && resolvedCall.getResultingDescriptor().equals(parameterDescriptor.getOriginal())) { - // do nothing: we shouldn't store argument to itself again - AsmUtil.pop(v, type); - continue; + if (argumentExpression is KtSimpleNameExpression) { + val resolvedCall = argumentExpression.getResolvedCall(state.bindingContext) + if (resolvedCall?.resultingDescriptor == parameterDescriptor.original) { + // do nothing: we shouldn't store argument to itself again + AsmUtil.pop(v, type) + continue@loop + } } + //assign the parameter below } - //assign the parameter below - } - else if (arg instanceof DefaultValueArgument) { - AsmUtil.pop(v, type); - DefaultParameterValueLoader.DEFAULT.genValue(parameterDescriptor, codegen).put(type, v); - } - else if (arg instanceof VarargValueArgument) { - // assign the parameter below - } - else { - throw new UnsupportedOperationException("Unknown argument type: " + arg + " in " + fd); + is DefaultValueArgument -> { + AsmUtil.pop(v, type) + DefaultParameterValueLoader.DEFAULT.genValue(parameterDescriptor, codegen).put(type, v) + } + is VarargValueArgument -> { + // assign the parameter below + } + else -> throw UnsupportedOperationException("Unknown argument type: $arg in $fd") } - store(parameterDescriptor, type); + store(parameterDescriptor, type) } } - private void store(ValueParameterDescriptor parameterDescriptor, Type type) { - int index = getParameterVariableIndex(parameterDescriptor); - v.store(index, type); + private fun store(parameterDescriptor: ValueParameterDescriptor, type: Type) { + val index = getParameterVariableIndex(parameterDescriptor) + v.store(index, type) } - private int getParameterVariableIndex(ValueParameterDescriptor parameterDescriptor) { - int index = codegen.lookupLocalIndex(parameterDescriptor); + private fun getParameterVariableIndex(parameterDescriptor: ValueParameterDescriptor): Int { + var index = codegen.lookupLocalIndex(parameterDescriptor) if (index == -1) { // in the case of a generic function recursively calling itself, the parameters on the call site are substituted - index = codegen.lookupLocalIndex(parameterDescriptor.getOriginal()); + index = codegen.lookupLocalIndex(parameterDescriptor.original) } if (index == -1) { - throw new IllegalStateException("Failed to obtain parameter index: " + parameterDescriptor); + throw IllegalStateException("Failed to obtain parameter index: $parameterDescriptor") } - return index; + return index } }