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);
}
if (context.isInliningLambda()) {
if (context instanceof InlineLambdaContext) {
lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
}
@@ -404,7 +404,7 @@ public class FunctionCodegen {
functionFakeIndex);
}
if (context.isInliningLambda() && thisType != null && lambdaFakeIndex != -1) {
if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
String name = thisType.getClassName();
int indexOfLambdaOrdinal = name.lastIndexOf("$");
if (indexOfLambdaOrdinal > 0) {
@@ -279,7 +279,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
protected void writeOuterClassAndEnclosingMethod() {
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
//noinspection ConstantConditions
context = context.getParentContext().getParentContext();
@@ -298,12 +298,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
@NotNull
public MethodContext intoFunction(FunctionDescriptor descriptor) {
return new MethodContext(descriptor, getContextKind(), this, null, false, false);
return new MethodContext(descriptor, getContextKind(), this, null);
}
@NotNull
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
@@ -654,19 +654,6 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
@NotNull
public CodegenContext getFirstCrossInlineOrNonInlineContext() {
if (!(this instanceof MethodContext)) {
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();
return this;
}
}
@@ -34,7 +34,7 @@ public class ConstructorContext extends MethodContext {
@NotNull CodegenContext parent,
@Nullable MutableClosure closure
) {
super(contextDescriptor, kind, parent, closure, false, false);
super(contextDescriptor, kind, parent, closure);
}
@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;
public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
private final boolean isInliningLambda;
private Label methodStartLabel;
private Label methodEndLabel;
// Note: in case of code inside property accessors, functionDescriptor will be that accessor,
// but CodegenContext#contextDescriptor will be the corresponding property
private final FunctionDescriptor functionDescriptor;
public final boolean isCrossInline;
protected MethodContext(
@NotNull FunctionDescriptor functionDescriptor,
@NotNull OwnerKind contextKind,
@NotNull CodegenContext parentContext,
@Nullable MutableClosure closure,
boolean isInliningLambda,
boolean isCrossInline
@Nullable MutableClosure closure
) {
super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure,
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
this.isInliningLambda = isInliningLambda;
this.functionDescriptor = functionDescriptor;
this.isCrossInline = isCrossInline;
}
@NotNull
@@ -124,10 +118,6 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
return InlineUtil.isInline(getContextDescriptor());
}
public boolean isInliningLambda() {
return isInliningLambda;
}
@NotNull
public FunctionDescriptor getFunctionDescriptor() {
return functionDescriptor;
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.codegen.MemberCodegen;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.context.CodegenContext;
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.optimization.common.UtilKt;
import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -398,7 +399,7 @@ public class InlineCodegenUtil {
}
public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) {
return context.isInlineMethodContext() || context.isInliningLambda();
return context.isInlineMethodContext() || context instanceof InlineLambdaContext;
}
public static int getConstant(AbstractInsnNode ins) {