Optimize visibility for controller field in CoroutineImpl

While it's impossible to declare a property with protected field and public
getter we split these entities

- `_controller` field is used inside coroutines
- `controller` getter is used for accesing controller from noinline lambdas
 (also it can be used to obtain controller from continuation by explicit cast)
This commit is contained in:
Denis Zharkov
2016-11-08 12:23:09 +03:00
parent 020bab1d7c
commit 50a5c08603
4 changed files with 47 additions and 14 deletions
@@ -3044,18 +3044,41 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ClassDescriptor classDescriptor = bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, descriptor);
assert classDescriptor != null : "class descriptor for coroutine " + descriptor + " should not be null";
StackValue coroutineReceiver = StackValue.thisOrOuter(this, classDescriptor, /* isSuper =*/ false, /* castReceiver */ false);
return StackValue.coercion(
StackValue.field(
final StackValue coroutineReceiver = StackValue.thisOrOuter(this, classDescriptor, /* isSuper =*/ false, /* castReceiver */ false);
StackValue controllerValue;
if (InlineUtil.checkNonLocalReturnUsage(
context.getFunctionDescriptor(),
descriptor, DescriptorToSourceUtils.descriptorToDeclaration(descriptor), bindingContext
)) {
// This branch should work for major part of cases and it's needed mostly for optimizations purpose
// else branch must have just the same semantics
controllerValue = StackValue.field(
FieldInfo.createForHiddenField(
AsmTypes.COROUTINE_IMPL,
AsmTypes.OBJECT_TYPE,
CoroutineCodegenUtilKt.COROUTINE_CONTROLLER_FIELD_NAME
),
coroutineReceiver
),
typeMapper.mapType(coroutineControllerType)
);
);
}
else {
controllerValue = StackValue.functionCall(AsmTypes.OBJECT_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter adapter) {
coroutineReceiver.put(AsmTypes.COROUTINE_IMPL, adapter);
adapter.invokevirtual(
AsmTypes.COROUTINE_IMPL.getInternalName(),
CoroutineCodegenUtilKt.COROUTINE_CONTROLLER_GETTER_NAME,
"()" + AsmTypes.OBJECT_TYPE,
false
);
return Unit.INSTANCE;
}
});
}
return StackValue.coercion(controllerValue, typeMapper.mapType(coroutineControllerType));
}
return context.generateReceiver(descriptor, state, false);
@@ -47,7 +47,8 @@ const val AFTER_SUSPENSION_POINT_MARKER_NAME = "afterSuspensionPoint"
const val HANDLE_EXCEPTION_MARKER_NAME = "handleException"
const val HANDLE_EXCEPTION_ARGUMENT_MARKER_NAME = "handleExceptionArgument"
const val COROUTINE_CONTROLLER_FIELD_NAME = "controller"
const val COROUTINE_CONTROLLER_FIELD_NAME = "_controller"
const val COROUTINE_CONTROLLER_GETTER_NAME = "getController"
const val COROUTINE_LABEL_FIELD_NAME = "label"
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeThisExpression: KtExpression)