Optimization for const closures: access it via GETSTATIC
This commit is contained in:
@@ -1195,7 +1195,7 @@ public abstract class StackValue {
|
||||
|
||||
public abstract static class StackValueWithSimpleReceiver extends StackValue {
|
||||
|
||||
protected final boolean isStatic;
|
||||
public final boolean isStatic;
|
||||
|
||||
public StackValueWithSimpleReceiver(@NotNull Type type, boolean isStatic) {
|
||||
super(type);
|
||||
|
||||
@@ -333,7 +333,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
return result == null ? innerValue : StackValue.composed(result, innerValue);
|
||||
return result == null ? innerValue : composedOrStatic(result, innerValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -349,7 +349,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
resultValue = parentContext != null ? parentContext.lookupInContext(d, result, state, ignoreNoOuter) : null;
|
||||
}
|
||||
|
||||
if (myOuter != null && resultValue != null) {
|
||||
if (myOuter != null && resultValue != null && !isStaticField(resultValue)) {
|
||||
closure.setCaptureThis();
|
||||
}
|
||||
return resultValue;
|
||||
@@ -464,4 +464,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
public CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
||||
return childContexts == null ? null : childContexts.get(child);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static StackValue composedOrStatic(@NotNull StackValue prefix, @NotNull StackValue suffix) {
|
||||
if (isStaticField(suffix)) {
|
||||
return suffix;
|
||||
}
|
||||
return StackValue.composed(prefix, suffix);
|
||||
}
|
||||
|
||||
private static boolean isStaticField(@NotNull StackValue value) {
|
||||
return value instanceof StackValue.Field && ((StackValue.Field) value).isStatic;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,18 @@
|
||||
package org.jetbrains.jet.codegen.context;
|
||||
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.codegen.CodegenUtil;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_RECEIVER_FIELD;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||
|
||||
public interface LocalLookup {
|
||||
boolean lookupLocal(DeclarationDescriptor descriptor);
|
||||
@@ -86,7 +88,15 @@ public interface LocalLookup {
|
||||
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
||||
if (!idx) return null;
|
||||
|
||||
Type localType = asmTypeForAnonymousClass(state.getBindingContext(), vd);
|
||||
BindingContext bindingContext = state.getBindingContext();
|
||||
Type localType = asmTypeForAnonymousClass(bindingContext, vd);
|
||||
|
||||
MutableClosure localFunClosure = bindingContext.get(CLOSURE, bindingContext.get(CLASS_FOR_FUNCTION, vd));
|
||||
if (localFunClosure != null && CodegenUtil.isConst(localFunClosure)) {
|
||||
// This is an optimization: we can obtain an instance of a const closure simply by GETSTATIC ...$instance
|
||||
// (instead of passing this instance to the constructor and storing as a field)
|
||||
return StackValue.field(localType, localType, JvmAbi.INSTANCE_FIELD, true);
|
||||
}
|
||||
|
||||
String fieldName = "$" + vd.getName();
|
||||
StackValue innerValue = StackValue.field(localType, classType, fieldName, false);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
fun test() {
|
||||
|
||||
fun local(){
|
||||
{
|
||||
//static instance access
|
||||
local()
|
||||
}()
|
||||
}
|
||||
|
||||
//static instance access
|
||||
{
|
||||
//static instance access
|
||||
local()
|
||||
}()
|
||||
|
||||
//static instance access
|
||||
(::local)()
|
||||
}
|
||||
|
||||
// 3 GETSTATIC _DefaultPackage\$test\$1\.instance\$
|
||||
// 1 GETSTATIC _DefaultPackage\$test\$2\.instance\$
|
||||
// 1 GETSTATIC _DefaultPackage\$test\$3\.instance\$
|
||||
@@ -57,6 +57,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest("compiler/testData/codegen/bytecodeText/componentEvaluatesOnlyOnce.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("constClosureOptimization.kt")
|
||||
public void testConstClosureOptimization() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/constClosureOptimization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("intConstantNotNull.kt")
|
||||
public void testIntConstantNotNull() throws Exception {
|
||||
doTest("compiler/testData/codegen/bytecodeText/intConstantNotNull.kt");
|
||||
|
||||
Reference in New Issue
Block a user