Change mangling for local functions
This commit is contained in:
committed by
Yan Zhulanow
parent
aca3be12e9
commit
488418d960
@@ -16,6 +16,7 @@ import com.intellij.util.containers.Stack;
|
||||
import kotlin.Pair;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
@@ -1412,11 +1413,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private void addLeaveTaskToRemoveNamedFunctionFromFrameMap(
|
||||
@NotNull KtNamedFunction statement,
|
||||
@NotNull KtNamedFunction localFunction,
|
||||
Label blockEnd,
|
||||
@NotNull List<Function<StackValue, Void>> leaveTasks
|
||||
) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement);
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, localFunction);
|
||||
assert functionDescriptor != null;
|
||||
|
||||
Type type = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
||||
@@ -1427,8 +1428,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
leaveTasks.add(answer -> {
|
||||
int index = myFrameMap.leave(functionDescriptor);
|
||||
|
||||
assert !functionDescriptor.getName().isSpecial() : "Local variable should be generated only for function with name: " + statement.getText();
|
||||
v.visitLocalVariable(functionDescriptor.getName().asString() + "$", type.getDescriptor(), null, scopeStart, blockEnd, index);
|
||||
assert !functionDescriptor.getName().isSpecial()
|
||||
: "Local variable should be generated only for function with name: " + localFunction.getText();
|
||||
|
||||
String functionIndex = StringsKt.substringAfterLast(type.getInternalName(), '$', "");
|
||||
assert !functionIndex.isEmpty();
|
||||
|
||||
String localVariableName = "$fun$"
|
||||
+ VariableAsmNameManglingUtils.mangleNameIfNeeded(functionDescriptor.getName().asString())
|
||||
+ "$" + functionIndex;
|
||||
|
||||
v.visitLocalVariable(localVariableName, type.getDescriptor(), null, scopeStart, blockEnd, index);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// LOCAL_VARIABLE_TABLE
|
||||
|
||||
fun foo() {
|
||||
fun a() {}
|
||||
fun a2() {}
|
||||
fun a2(a: Int) {}
|
||||
fun `b c`() {}
|
||||
fun `c$d`() {}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
final class LocalFunctionsKt$foo$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||
public final static LocalFunctionsKt$foo$1 INSTANCE
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
void <init>()
|
||||
|
||||
public java.lang.Object invoke()
|
||||
|
||||
public final void invoke() {
|
||||
Local variables:
|
||||
0 this: LLocalFunctionsKt$foo$1;
|
||||
}
|
||||
}
|
||||
|
||||
final class LocalFunctionsKt$foo$2 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||
public final static LocalFunctionsKt$foo$2 INSTANCE
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
void <init>()
|
||||
|
||||
public java.lang.Object invoke()
|
||||
|
||||
public final void invoke() {
|
||||
Local variables:
|
||||
0 this: LLocalFunctionsKt$foo$2;
|
||||
}
|
||||
}
|
||||
|
||||
final class LocalFunctionsKt$foo$3 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function1 {
|
||||
public final static LocalFunctionsKt$foo$3 INSTANCE
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
void <init>()
|
||||
|
||||
public java.lang.Object invoke(java.lang.Object p0)
|
||||
|
||||
public final void invoke(int a) {
|
||||
Local variables:
|
||||
0 this: LLocalFunctionsKt$foo$3;
|
||||
1 a: I
|
||||
}
|
||||
}
|
||||
|
||||
final class LocalFunctionsKt$foo$4 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||
public final static LocalFunctionsKt$foo$4 INSTANCE
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
void <init>()
|
||||
|
||||
public java.lang.Object invoke()
|
||||
|
||||
public final void invoke() {
|
||||
Local variables:
|
||||
0 this: LLocalFunctionsKt$foo$4;
|
||||
}
|
||||
}
|
||||
|
||||
final class LocalFunctionsKt$foo$5 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||
public final static LocalFunctionsKt$foo$5 INSTANCE
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
void <init>()
|
||||
|
||||
public java.lang.Object invoke()
|
||||
|
||||
public final void invoke() {
|
||||
Local variables:
|
||||
0 this: LLocalFunctionsKt$foo$5;
|
||||
}
|
||||
}
|
||||
|
||||
public final class LocalFunctionsKt : java/lang/Object {
|
||||
public final static void foo() {
|
||||
Local variables:
|
||||
4 $fun$c-0024d$5: LLocalFunctionsKt$foo$5;
|
||||
3 $fun$b-0020c$4: LLocalFunctionsKt$foo$4;
|
||||
2 $fun$a2$3: LLocalFunctionsKt$foo$3;
|
||||
1 $fun$a2$2: LLocalFunctionsKt$foo$2;
|
||||
0 $fun$a$1: LLocalFunctionsKt$foo$1;
|
||||
}
|
||||
}
|
||||
+5
@@ -86,6 +86,11 @@ public class AsmLikeInstructionListingTestGenerated extends AbstractAsmLikeInstr
|
||||
runTest("compiler/testData/codegen/asmLike/receiverMangling/innerClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localFunctions.kt")
|
||||
public void testLocalFunctions() throws Exception {
|
||||
runTest("compiler/testData/codegen/asmLike/receiverMangling/localFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledNames.kt")
|
||||
public void testMangledNames() throws Exception {
|
||||
runTest("compiler/testData/codegen/asmLike/receiverMangling/mangledNames.kt");
|
||||
|
||||
@@ -265,9 +265,8 @@ class VariableFinder private constructor(private val context: EvaluationContextI
|
||||
val canBeLocalFunction = kind is VariableKind.Ordinary
|
||||
|
||||
if (canBeLocalFunction && kind.type?.isFunctionType() == true) {
|
||||
@Suppress("ConvertToStringTemplate")
|
||||
variables.namedEntitySequence()
|
||||
.filter { it.name == name + "$" && kind.typeMatches(it.type) }
|
||||
.filter { isLocalFunctionName(it.name, name) && kind.typeMatches(it.type) }
|
||||
.firstOrNull()
|
||||
?.let { return Result(it.value()) }
|
||||
}
|
||||
@@ -291,6 +290,11 @@ class VariableFinder private constructor(private val context: EvaluationContextI
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isLocalFunctionName(name: String, functionName: String): Boolean {
|
||||
@Suppress("ConvertToStringTemplate")
|
||||
return name == functionName + "$" || name.startsWith(AsmUtil.LOCAL_FUNCTION_VARIABLE_PREFIX + name + "$")
|
||||
}
|
||||
|
||||
private fun findCoroutineContext(): ObjectReference? {
|
||||
val method = frameProxy.location().safeMethod() ?: return null
|
||||
return findCoroutineContextForLambda(method) ?: findCoroutineContextForMethod(method)
|
||||
|
||||
Reference in New Issue
Block a user