org.jetbrains.kotlin.codegen.context.LocalLookup Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* 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.annotations.NotNull;
import org.jetbrains.kotlin.codegen.ExpressionCodegen;
import org.jetbrains.kotlin.codegen.JvmCodegenUtil;
import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.Type;
import static org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_RECEIVER_FIELD;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isLocalFunction;
public interface LocalLookup {
boolean lookupLocal(DeclarationDescriptor descriptor);
enum LocalLookupCase {
VAR {
@Override
public boolean isCase(DeclarationDescriptor d) {
return d instanceof VariableDescriptor && !(d instanceof PropertyDescriptor);
}
@Override
public StackValue.StackValueWithSimpleReceiver innerValue(
DeclarationDescriptor d,
LocalLookup localLookup,
GenerationState state,
MutableClosure closure,
Type classType
) {
VariableDescriptor vd = (VariableDescriptor) d;
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
if (!idx) return null;
VariableDescriptor delegateVariableDescriptor = state.getBindingContext().get(LOCAL_VARIABLE_DELEGATE, vd);
Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
Type localType = state.getTypeMapper().mapType(delegateVariableDescriptor != null ? delegateVariableDescriptor : vd);
Type type = sharedVarType != null ? sharedVarType : localType;
String fieldName = "$" + vd.getName();
StackValue.Local thiz = StackValue.LOCAL_0;
StackValue.StackValueWithSimpleReceiver innerValue;
EnclosedValueDescriptor enclosedValueDescriptor;
if (sharedVarType != null) {
StackValue.Field wrapperValue = StackValue.receiverWithRefWrapper(localType, classType, fieldName, thiz, vd);
innerValue = StackValue.fieldForSharedVar(localType, classType, fieldName, wrapperValue);
enclosedValueDescriptor = new EnclosedValueDescriptor(fieldName, d, innerValue, wrapperValue, type);
}
else {
innerValue = StackValue.field(type, classType, fieldName, false, thiz, vd);
enclosedValueDescriptor = new EnclosedValueDescriptor(fieldName, d, innerValue, type);
}
closure.recordField(fieldName, type);
closure.captureVariable(enclosedValueDescriptor);
return innerValue;
}
},
LOCAL_NAMED_FUNCTION {
@Override
public boolean isCase(DeclarationDescriptor d) {
return isLocalFunction(d);
}
@Override
public StackValue.StackValueWithSimpleReceiver innerValue(
DeclarationDescriptor d,
LocalLookup localLookup,
GenerationState state,
MutableClosure closure,
Type classType
) {
FunctionDescriptor vd = (FunctionDescriptor) d;
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
if (!idx) return null;
BindingContext bindingContext = state.getBindingContext();
Type localType = asmTypeForAnonymousClass(bindingContext, vd);
MutableClosure localFunClosure = bindingContext.get(CLOSURE, bindingContext.get(CLASS_FOR_CALLABLE, vd));
if (localFunClosure != null && JvmCodegenUtil.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, StackValue.LOCAL_0, vd);
}
String fieldName = "$" + vd.getName();
StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field(localType, classType, fieldName, false,
StackValue.LOCAL_0, vd);
closure.recordField(fieldName, localType);
closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, localType));
return innerValue;
}
},
RECEIVER {
@Override
public boolean isCase(DeclarationDescriptor d) {
return d instanceof ReceiverParameterDescriptor;
}
@Override
public StackValue.StackValueWithSimpleReceiver innerValue(
DeclarationDescriptor d,
LocalLookup enclosingLocalLookup,
GenerationState state,
MutableClosure closure,
Type classType
) {
if (closure.getEnclosingReceiverDescriptor() != d) {
return null;
}
KotlinType receiverType = closure.getEnclosingReceiverDescriptor().getType();
Type type = state.getTypeMapper().mapType(receiverType);
StackValue.StackValueWithSimpleReceiver innerValue = StackValue.field(type, classType, CAPTURED_RECEIVER_FIELD, false,
StackValue.LOCAL_0, d);
closure.setCaptureReceiver();
return innerValue;
}
@NotNull
@Override
public StackValue outerValue(@NotNull EnclosedValueDescriptor d, @NotNull ExpressionCodegen codegen) {
CallableDescriptor descriptor = (CallableDescriptor) d.getDescriptor();
return StackValue.local(descriptor.getDispatchReceiverParameter() != null ? 1 : 0, d.getType());
}
};
public abstract boolean isCase(DeclarationDescriptor d);
public abstract StackValue.StackValueWithSimpleReceiver innerValue(
DeclarationDescriptor d,
LocalLookup localLookup,
GenerationState state,
MutableClosure closure,
Type classType
);
@NotNull
public StackValue outerValue(@NotNull EnclosedValueDescriptor d, @NotNull ExpressionCodegen codegen) {
DeclarationDescriptor declarationDescriptor = d.getDescriptor();
int idx = codegen.lookupLocalIndex(declarationDescriptor);
if (idx >= 0) {
return StackValue.local(idx, d.getType());
}
else {
assert declarationDescriptor != null : "No declaration descriptor for " + d;
StackValue capturedValue = codegen.findCapturedValue(declarationDescriptor);
assert capturedValue != null : "Unresolved captured value for " + d;
return capturedValue;
}
}
}
}