Added InliningLambdaContext

This commit is contained in:
Michael Bogdanov
2015-12-16 18:36:25 +03:00
parent ebbc68dfae
commit 7a1d789e9a
7 changed files with 54 additions and 32 deletions
@@ -375,7 +375,7 @@ public class FunctionCodegen {
functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE); functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
} }
if (context.isInliningLambda()) { if (context instanceof InlineLambdaContext) {
lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE); lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
} }
@@ -404,7 +404,7 @@ public class FunctionCodegen {
functionFakeIndex); functionFakeIndex);
} }
if (context.isInliningLambda() && thisType != null && lambdaFakeIndex != -1) { if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
String name = thisType.getClassName(); String name = thisType.getClassName();
int indexOfLambdaOrdinal = name.lastIndexOf("$"); int indexOfLambdaOrdinal = name.lastIndexOf("$");
if (indexOfLambdaOrdinal > 0) { if (indexOfLambdaOrdinal > 0) {
@@ -279,7 +279,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
protected void writeOuterClassAndEnclosingMethod() { protected void writeOuterClassAndEnclosingMethod() {
CodegenContext context = this.context.getParentContext(); CodegenContext context = this.context.getParentContext();
while (context instanceof MethodContext && ((MethodContext) context).isInliningLambda()) {
while (context instanceof InlineLambdaContext) {
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext // If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
//noinspection ConstantConditions //noinspection ConstantConditions
context = context.getParentContext().getParentContext(); context = context.getParentContext().getParentContext();
@@ -298,12 +298,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
@NotNull @NotNull
public MethodContext intoFunction(FunctionDescriptor descriptor) { public MethodContext intoFunction(FunctionDescriptor descriptor) {
return new MethodContext(descriptor, getContextKind(), this, null, false, false); return new MethodContext(descriptor, getContextKind(), this, null);
} }
@NotNull @NotNull
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) { public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) {
return new MethodContext(descriptor, getContextKind(), this, null, true, isCrossInline); return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline);
} }
@NotNull @NotNull
@@ -654,19 +654,6 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
@NotNull @NotNull
public CodegenContext getFirstCrossInlineOrNonInlineContext() { public CodegenContext getFirstCrossInlineOrNonInlineContext() {
if (!(this instanceof MethodContext)) { return this;
return this;
}
MethodContext context = (MethodContext) this;
if (!context.isInliningLambda() || context.isCrossInline) {
return this;
}
CodegenContext parent = context.getParentContext();
assert parent instanceof ClosureContext : "Parent of inlining lambda body should be ClosureContext, but: " + parent;
parent = parent.getParentContext();
assert parent != null : "Parent context of lambda class context should exist: " + this.contextDescriptor;
return parent.getFirstCrossInlineOrNonInlineContext();
} }
} }
@@ -34,7 +34,7 @@ public class ConstructorContext extends MethodContext {
@NotNull CodegenContext parent, @NotNull CodegenContext parent,
@Nullable MutableClosure closure @Nullable MutableClosure closure
) { ) {
super(contextDescriptor, kind, parent, closure, false, false); super(contextDescriptor, kind, parent, closure);
} }
@Override @Override
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.context
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.binding.MutableClosure
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
class InlineLambdaContext(
functionDescriptor: FunctionDescriptor,
contextKind: OwnerKind,
parentContext: CodegenContext<*>,
closure: MutableClosure?,
val isCrossInline: Boolean
) : MethodContext(functionDescriptor, contextKind, parentContext, closure) {
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
if (isCrossInline) return this
val parent = parentContext as? ClosureContext ?:
throw AssertionError("Parent of inlining lambda body should be ClosureContext, but: $parentContext")
val grandParent = parent.parentContext ?:
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
return grandParent.firstCrossInlineOrNonInlineContext
}
}
@@ -32,28 +32,22 @@ import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
public class MethodContext extends CodegenContext<CallableMemberDescriptor> { public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
private final boolean isInliningLambda;
private Label methodStartLabel; private Label methodStartLabel;
private Label methodEndLabel; private Label methodEndLabel;
// Note: in case of code inside property accessors, functionDescriptor will be that accessor, // Note: in case of code inside property accessors, functionDescriptor will be that accessor,
// but CodegenContext#contextDescriptor will be the corresponding property // but CodegenContext#contextDescriptor will be the corresponding property
private final FunctionDescriptor functionDescriptor; private final FunctionDescriptor functionDescriptor;
public final boolean isCrossInline;
protected MethodContext( protected MethodContext(
@NotNull FunctionDescriptor functionDescriptor, @NotNull FunctionDescriptor functionDescriptor,
@NotNull OwnerKind contextKind, @NotNull OwnerKind contextKind,
@NotNull CodegenContext parentContext, @NotNull CodegenContext parentContext,
@Nullable MutableClosure closure, @Nullable MutableClosure closure
boolean isInliningLambda,
boolean isCrossInline
) { ) {
super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure, super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure,
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null); parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
this.isInliningLambda = isInliningLambda;
this.functionDescriptor = functionDescriptor; this.functionDescriptor = functionDescriptor;
this.isCrossInline = isCrossInline;
} }
@NotNull @NotNull
@@ -124,10 +118,6 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
return InlineUtil.isInline(getContextDescriptor()); return InlineUtil.isInline(getContextDescriptor());
} }
public boolean isInliningLambda() {
return isInliningLambda;
}
@NotNull @NotNull
public FunctionDescriptor getFunctionDescriptor() { public FunctionDescriptor getFunctionDescriptor() {
return functionDescriptor; return functionDescriptor;
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.codegen.MemberCodegen;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil; import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
import org.jetbrains.kotlin.codegen.context.MethodContext; import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt; import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -398,7 +399,7 @@ public class InlineCodegenUtil {
} }
public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) { public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) {
return context.isInlineMethodContext() || context.isInliningLambda(); return context.isInlineMethodContext() || context instanceof InlineLambdaContext;
} }
public static int getConstant(AbstractInsnNode ins) { public static int getConstant(AbstractInsnNode ins) {