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.Pair;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
|
import kotlin.text.StringsKt;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||||
@@ -1412,11 +1413,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addLeaveTaskToRemoveNamedFunctionFromFrameMap(
|
private void addLeaveTaskToRemoveNamedFunctionFromFrameMap(
|
||||||
@NotNull KtNamedFunction statement,
|
@NotNull KtNamedFunction localFunction,
|
||||||
Label blockEnd,
|
Label blockEnd,
|
||||||
@NotNull List<Function<StackValue, Void>> leaveTasks
|
@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;
|
assert functionDescriptor != null;
|
||||||
|
|
||||||
Type type = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
Type type = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
||||||
@@ -1427,8 +1428,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
leaveTasks.add(answer -> {
|
leaveTasks.add(answer -> {
|
||||||
int index = myFrameMap.leave(functionDescriptor);
|
int index = myFrameMap.leave(functionDescriptor);
|
||||||
|
|
||||||
assert !functionDescriptor.getName().isSpecial() : "Local variable should be generated only for function with name: " + statement.getText();
|
assert !functionDescriptor.getName().isSpecial()
|
||||||
v.visitLocalVariable(functionDescriptor.getName().asString() + "$", type.getDescriptor(), null, scopeStart, blockEnd, index);
|
: "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;
|
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");
|
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")
|
@TestMetadata("mangledNames.kt")
|
||||||
public void testMangledNames() throws Exception {
|
public void testMangledNames() throws Exception {
|
||||||
runTest("compiler/testData/codegen/asmLike/receiverMangling/mangledNames.kt");
|
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
|
val canBeLocalFunction = kind is VariableKind.Ordinary
|
||||||
|
|
||||||
if (canBeLocalFunction && kind.type?.isFunctionType() == true) {
|
if (canBeLocalFunction && kind.type?.isFunctionType() == true) {
|
||||||
@Suppress("ConvertToStringTemplate")
|
|
||||||
variables.namedEntitySequence()
|
variables.namedEntitySequence()
|
||||||
.filter { it.name == name + "$" && kind.typeMatches(it.type) }
|
.filter { isLocalFunctionName(it.name, name) && kind.typeMatches(it.type) }
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
?.let { return Result(it.value()) }
|
?.let { return Result(it.value()) }
|
||||||
}
|
}
|
||||||
@@ -291,6 +290,11 @@ class VariableFinder private constructor(private val context: EvaluationContextI
|
|||||||
return null
|
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? {
|
private fun findCoroutineContext(): ObjectReference? {
|
||||||
val method = frameProxy.location().safeMethod() ?: return null
|
val method = frameProxy.location().safeMethod() ?: return null
|
||||||
return findCoroutineContextForLambda(method) ?: findCoroutineContextForMethod(method)
|
return findCoroutineContextForLambda(method) ?: findCoroutineContextForMethod(method)
|
||||||
|
|||||||
Reference in New Issue
Block a user