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 {
|
public abstract static class StackValueWithSimpleReceiver extends StackValue {
|
||||||
|
|
||||||
protected final boolean isStatic;
|
public final boolean isStatic;
|
||||||
|
|
||||||
public StackValueWithSimpleReceiver(@NotNull Type type, boolean isStatic) {
|
public StackValueWithSimpleReceiver(@NotNull Type type, boolean isStatic) {
|
||||||
super(type);
|
super(type);
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
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;
|
resultValue = parentContext != null ? parentContext.lookupInContext(d, result, state, ignoreNoOuter) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myOuter != null && resultValue != null) {
|
if (myOuter != null && resultValue != null && !isStaticField(resultValue)) {
|
||||||
closure.setCaptureThis();
|
closure.setCaptureThis();
|
||||||
}
|
}
|
||||||
return resultValue;
|
return resultValue;
|
||||||
@@ -464,4 +464,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
public CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
public CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
||||||
return childContexts == null ? null : childContexts.get(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;
|
package org.jetbrains.jet.codegen.context;
|
||||||
|
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
|
import org.jetbrains.jet.codegen.CodegenUtil;
|
||||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||||
import org.jetbrains.jet.codegen.StackValue;
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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 org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_RECEIVER_FIELD;
|
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.*;
|
||||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
|
|
||||||
|
|
||||||
public interface LocalLookup {
|
public interface LocalLookup {
|
||||||
boolean lookupLocal(DeclarationDescriptor descriptor);
|
boolean lookupLocal(DeclarationDescriptor descriptor);
|
||||||
@@ -86,7 +88,15 @@ public interface LocalLookup {
|
|||||||
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
||||||
if (!idx) return null;
|
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();
|
String fieldName = "$" + vd.getName();
|
||||||
StackValue innerValue = StackValue.field(localType, classType, fieldName, false);
|
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");
|
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")
|
@TestMetadata("intConstantNotNull.kt")
|
||||||
public void testIntConstantNotNull() throws Exception {
|
public void testIntConstantNotNull() throws Exception {
|
||||||
doTest("compiler/testData/codegen/bytecodeText/intConstantNotNull.kt");
|
doTest("compiler/testData/codegen/bytecodeText/intConstantNotNull.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user