Convert LambdaInfo.java to Kotlin
This commit is contained in:
@@ -575,7 +575,8 @@ public class InlineCodegen extends CallGenerator {
|
||||
Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
|
||||
PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
|
||||
strategy = new PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
||||
true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state, true);
|
||||
true, info.getGetFunction(), info.getTarget(), asmType, receiverType,
|
||||
lambdaInfo.getFunctionWithBodyOrCallableReference(), state, true);
|
||||
}
|
||||
else {
|
||||
strategy = new FunctionReferenceGenerationStrategy(
|
||||
|
||||
@@ -14,191 +14,128 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline;
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil;
|
||||
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.*
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
class LambdaInfo(
|
||||
expression: KtExpression,
|
||||
private val typeMapper: KotlinTypeMapper,
|
||||
@JvmField val isCrossInline: Boolean,
|
||||
val isBoundCallableReference: Boolean
|
||||
) : LabelOwner {
|
||||
val functionWithBodyOrCallableReference: KtExpression = (expression as? KtLambdaExpression)?.functionLiteral ?: expression
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
val labels: Set<String>
|
||||
private lateinit var closure: CalculatedClosure
|
||||
val functionDescriptor: FunctionDescriptor
|
||||
val classDescriptor: ClassDescriptor
|
||||
val lambdaClassType: Type
|
||||
|
||||
public class LambdaInfo implements LabelOwner {
|
||||
public final KtExpression expression;
|
||||
private final KotlinTypeMapper typeMapper;
|
||||
public final Set<String> labels;
|
||||
private final CalculatedClosure closure;
|
||||
public final boolean isCrossInline;
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
private final ClassDescriptor classDescriptor;
|
||||
private final Type closureClassType;
|
||||
var node: SMAPAndMethodNode? = null
|
||||
val propertyReferenceInfo: PropertyReferenceInfo?
|
||||
|
||||
private SMAPAndMethodNode node;
|
||||
private List<CapturedParamDesc> capturedVars;
|
||||
private final boolean isBoundCallableReference;
|
||||
private final PropertyReferenceInfo propertyReferenceInfo;
|
||||
|
||||
public LambdaInfo(@NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline, boolean isBoundCallableReference) {
|
||||
this.isCrossInline = isCrossInline;
|
||||
this.expression = expression instanceof KtLambdaExpression ?
|
||||
((KtLambdaExpression) expression).getFunctionLiteral() : expression;
|
||||
|
||||
this.typeMapper = typeMapper;
|
||||
this.isBoundCallableReference = isBoundCallableReference;
|
||||
BindingContext bindingContext = typeMapper.getBindingContext();
|
||||
FunctionDescriptor function = bindingContext.get(BindingContext.FUNCTION, this.expression);
|
||||
if (function == null && expression instanceof KtCallableReferenceExpression) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, this.expression);
|
||||
assert variableDescriptor instanceof VariableDescriptorWithAccessors :
|
||||
"Reference expression not resolved to variable descriptor with accessors: " + expression.getText();
|
||||
classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||
closureClassType = typeMapper.mapClass(classDescriptor);
|
||||
SimpleFunctionDescriptor getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor);
|
||||
functionDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor);
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(((KtCallableReferenceExpression) expression).getCallableReference(), bindingContext);
|
||||
propertyReferenceInfo = new PropertyReferenceInfo(
|
||||
(VariableDescriptor) resolvedCall.getResultingDescriptor(), getFunction
|
||||
);
|
||||
init {
|
||||
val bindingContext = typeMapper.bindingContext
|
||||
val function = bindingContext.get<PsiElement, SimpleFunctionDescriptor>(BindingContext.FUNCTION, this.functionWithBodyOrCallableReference)
|
||||
if (function == null && expression is KtCallableReferenceExpression) {
|
||||
val variableDescriptor = bindingContext.get<PsiElement, VariableDescriptor>(BindingContext.VARIABLE, this.functionWithBodyOrCallableReference)
|
||||
assert(variableDescriptor is VariableDescriptorWithAccessors) { "Reference expression not resolved to variable descriptor with accessors: " + expression.getText() }
|
||||
classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor!!)
|
||||
lambdaClassType = typeMapper.mapClass(classDescriptor)
|
||||
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
|
||||
functionDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
|
||||
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(bindingContext)
|
||||
propertyReferenceInfo = PropertyReferenceInfo(
|
||||
resolvedCall.resultingDescriptor as VariableDescriptor, getFunction
|
||||
)
|
||||
}
|
||||
else {
|
||||
propertyReferenceInfo = null;
|
||||
functionDescriptor = function;
|
||||
assert functionDescriptor != null : "Function is not resolved to descriptor: " + expression.getText();
|
||||
classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor);
|
||||
closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
||||
propertyReferenceInfo = null
|
||||
assert(function != null) { "Function is not resolved to descriptor: " + expression.text }
|
||||
functionDescriptor = function!!
|
||||
classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor)
|
||||
lambdaClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor)
|
||||
}
|
||||
|
||||
|
||||
closure = bindingContext.get(CLOSURE, classDescriptor);
|
||||
assert closure != null : "Closure for lambda should be not null " + expression.getText();
|
||||
|
||||
labels = InlineCodegen.getDeclarationLabels(expression, functionDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SMAPAndMethodNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setNode(@NotNull SMAPAndMethodNode node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FunctionDescriptor getFunctionDescriptor() {
|
||||
return functionDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KtExpression getFunctionWithBodyOrCallableReference() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getClassDescriptor() {
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type getLambdaClassType() {
|
||||
return closureClassType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<CapturedParamDesc> getCapturedVars() {
|
||||
//lazy initialization cause it would be calculated after object creation
|
||||
if (capturedVars == null) {
|
||||
capturedVars = new ArrayList<>();
|
||||
|
||||
if (closure.getCaptureThis() != null) {
|
||||
Type type = typeMapper.mapType(closure.getCaptureThis());
|
||||
EnclosedValueDescriptor descriptor =
|
||||
new EnclosedValueDescriptor(
|
||||
AsmUtil.CAPTURED_THIS_FIELD,
|
||||
/* descriptor = */ null,
|
||||
StackValue.field(type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0),
|
||||
type
|
||||
);
|
||||
capturedVars.add(getCapturedParamInfo(descriptor));
|
||||
}
|
||||
|
||||
if (closure.getCaptureReceiverType() != null) {
|
||||
Type type = typeMapper.mapType(closure.getCaptureReceiverType());
|
||||
EnclosedValueDescriptor descriptor =
|
||||
new EnclosedValueDescriptor(
|
||||
AsmUtil.CAPTURED_RECEIVER_FIELD,
|
||||
/* descriptor = */ null,
|
||||
StackValue.field(type, closureClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0),
|
||||
type
|
||||
);
|
||||
capturedVars.add(getCapturedParamInfo(descriptor));
|
||||
}
|
||||
|
||||
for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) {
|
||||
capturedVars.add(getCapturedParamInfo(descriptor));
|
||||
}
|
||||
}
|
||||
return capturedVars;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CapturedParamDesc getCapturedParamInfo(@NotNull EnclosedValueDescriptor descriptor) {
|
||||
return new CapturedParamDesc(closureClassType, descriptor.getFieldName(), descriptor.getType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Type> getInvokeParamsWithoutCaptured() {
|
||||
return Arrays.asList(typeMapper.mapAsmMethod(functionDescriptor).getArgumentTypes());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Parameters addAllParameters(@NotNull FieldRemapper remapper) {
|
||||
Method asmMethod = typeMapper.mapAsmMethod(getFunctionDescriptor());
|
||||
ParametersBuilder builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, asmMethod.getDescriptor(), this);
|
||||
|
||||
for (CapturedParamDesc info : getCapturedVars()) {
|
||||
CapturedParamInfo field = remapper.findField(new FieldInsnNode(0, info.getContainingLambdaName(), info.getFieldName(), ""));
|
||||
assert field != null : "Captured field not found: " + info.getContainingLambdaName() + "." + info.getFieldName();
|
||||
builder.addCapturedParam(field, info.getFieldName());
|
||||
bindingContext.get<ClassDescriptor, MutableClosure>(CLOSURE, classDescriptor).let {
|
||||
assert(it != null) { "Closure for lambda should be not null " + expression.text }
|
||||
closure = it!!
|
||||
}
|
||||
|
||||
return builder.buildParameters();
|
||||
labels = InlineCodegen.getDeclarationLabels(expression, functionDescriptor)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMyLabel(@NotNull String name) {
|
||||
return labels.contains(name);
|
||||
val capturedVars: List<CapturedParamDesc> by lazy {
|
||||
arrayListOf<CapturedParamDesc>().apply {
|
||||
if (closure.captureThis != null) {
|
||||
val type = typeMapper.mapType(closure.captureThis!!)
|
||||
val descriptor = EnclosedValueDescriptor(
|
||||
AsmUtil.CAPTURED_THIS_FIELD, null,
|
||||
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0),
|
||||
type
|
||||
)
|
||||
add(getCapturedParamInfo(descriptor))
|
||||
}
|
||||
|
||||
if (closure.captureReceiverType != null) {
|
||||
val type = typeMapper.mapType(closure.captureReceiverType!!)
|
||||
val descriptor = EnclosedValueDescriptor(
|
||||
AsmUtil.CAPTURED_RECEIVER_FIELD, null,
|
||||
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0),
|
||||
type
|
||||
)
|
||||
add(getCapturedParamInfo(descriptor))
|
||||
}
|
||||
|
||||
closure.captureVariables.values.forEach {
|
||||
descriptor -> add(getCapturedParamInfo(descriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBoundCallableReference() {
|
||||
return isBoundCallableReference;
|
||||
private fun getCapturedParamInfo(descriptor: EnclosedValueDescriptor): CapturedParamDesc {
|
||||
return CapturedParamDesc(lambdaClassType, descriptor.fieldName, descriptor.type)
|
||||
}
|
||||
|
||||
public boolean isPropertyReference() {
|
||||
return propertyReferenceInfo != null;
|
||||
val invokeParamsWithoutCaptured: List<Type>
|
||||
get() = Arrays.asList(*typeMapper.mapAsmMethod(functionDescriptor).argumentTypes)
|
||||
|
||||
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
||||
val asmMethod = typeMapper.mapAsmMethod(functionDescriptor)
|
||||
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, asmMethod.descriptor, this)
|
||||
|
||||
for (info in capturedVars) {
|
||||
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, "")) ?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName)
|
||||
builder.addCapturedParam(field, info.fieldName)
|
||||
}
|
||||
|
||||
return builder.buildParameters()
|
||||
}
|
||||
|
||||
public PropertyReferenceInfo getPropertyReferenceInfo() {
|
||||
return propertyReferenceInfo;
|
||||
override fun isMyLabel(name: String): Boolean {
|
||||
return labels.contains(name)
|
||||
}
|
||||
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
internal class Parameters(val parameters: List<ParameterInfo>) : Iterable<ParameterInfo> {
|
||||
class Parameters(val parameters: List<ParameterInfo>) : Iterable<ParameterInfo> {
|
||||
|
||||
private val actualDeclShifts: Array<ParameterInfo?>
|
||||
private val paramToDeclByteCodeIndex: HashMap<ParameterInfo, Int> = hashMapOf()
|
||||
|
||||
Reference in New Issue
Block a user