blob: fc3f2bdb0b058e4744ad958c2cb0a339a756e757 [file] [log] [blame]
// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.lambda.kotlin;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.optimize.lambda.CaptureSignature;
import com.android.tools.r8.ir.optimize.lambda.CodeProcessor.Strategy;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroup;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroupId;
// Represents a lambda group created to combine several lambda classes generated
// by kotlin compiler for either regular kotlin lambda expressions (k-style lambdas)
// or lambda expressions created to implement java SAM interface.
abstract class KotlinLambdaGroup extends LambdaGroup {
private final Strategy strategy = new KotlinLambdaGroupCodeStrategy(this);
KotlinLambdaGroup(LambdaGroupId id) {
super(id);
}
final KotlinLambdaGroupId id() {
return (KotlinLambdaGroupId) id;
}
final boolean isStateless() {
return id().capture.isEmpty();
}
final boolean hasAnySingletons() {
assert isStateless();
return anyLambda(info -> this.isSingletonLambda(info.clazz.type));
}
final boolean isSingletonLambda(DexType lambda) {
assert isStateless();
return lambdaSingletonField(lambda) != null;
}
// Field referencing singleton instance for a lambda with specified id.
final DexField getSingletonInstanceField(DexItemFactory factory, int id) {
return factory.createField(this.getGroupClassType(),
this.getGroupClassType(), factory.createString("INSTANCE$" + id));
}
@Override
protected String getTypePackage() {
String pkg = id().pkg;
return pkg.isEmpty() ? "" : (pkg + "/");
}
final DexProto createConstructorProto(DexItemFactory factory) {
String capture = id().capture;
DexType[] newParameters = new DexType[capture.length() + 1];
newParameters[0] = factory.intType; // Lambda id.
for (int i = 0; i < capture.length(); i++) {
newParameters[i + 1] = CaptureSignature.fieldType(factory, capture, i);
}
return factory.createProto(factory.voidType, newParameters);
}
final DexField getLambdaIdField(DexItemFactory factory) {
return factory.createField(this.getGroupClassType(), factory.intType, "$id$");
}
final int mapFieldIntoCaptureIndex(DexType lambda, DexField field) {
return CaptureSignature.mapFieldIntoCaptureIndex(
id().capture, lambdaCaptureFields(lambda), field);
}
final DexField getCaptureField(DexItemFactory factory, int index) {
assert index >= 0 && index < id().capture.length();
return factory.createField(this.getGroupClassType(),
CaptureSignature.fieldType(factory, id().capture, index), "$capture$" + index);
}
@Override
public Strategy getCodeStrategy() {
return strategy;
}
}