Review feedback, part 1

This commit is contained in:
Svyatoslav Scherbina
2016-12-13 12:32:06 +07:00
committed by SvyatoslavScherbina
parent 4dec392880
commit 7d4074a1a4
5 changed files with 61 additions and 32 deletions
@@ -1588,13 +1588,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
// Note: the whole function code below is written in the assumption that // Note: the whole function code below is written in the assumption that
// `invoke` method receiver is passed as first argument. // `invoke` method receiver is passed as first argument.
val functionImpl = args[0] val functionImpl = args[0] // Instance of `konan.internal.FunctionImpl`.
// `functionImpl.unboundRef` is the pointer to (static) function of type
// `(FunctionImpl, Arg_1, ..., Arg_n): Ret`. See [CallableReferenceLowering] for details.
// LLVM type for such function is equal to type for `FunctionImpl.invoke(Arg_1, ..., Arg_n): Ret`.
// So we can use the latter for simplicity:
val unboundRefType = codegen.getLlvmFunctionType(descriptor) val unboundRefType = codegen.getLlvmFunctionType(descriptor)
// Get `functionImpl.unboundRef`:
val unboundRef = evaluateSimpleFunctionCall(codegen.newVar(), val unboundRef = evaluateSimpleFunctionCall(codegen.newVar(),
functionImplUnboundRefGetter, listOf(functionImpl)) functionImplUnboundRefGetter, listOf(functionImpl))
// Cast `functionImpl.unboundRef` to pointer to function:
val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry") val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry")
return call(descriptor, entryPtr, args, tmpVariableName) return call(descriptor, entryPtr, args, tmpVariableName)
@@ -25,10 +25,13 @@ import org.jetbrains.kotlin.utils.addToStdlib.singletonList
* This lowering pass lowers all [IrCallableReference]s to unbound ones. * This lowering pass lowers all [IrCallableReference]s to unbound ones.
*/ */
internal class CallableReferenceLowering(val context: KonanBackendContext) : DeclarationContainerLoweringPass { internal class CallableReferenceLowering(val context: KonanBackendContext) : DeclarationContainerLoweringPass {
var callableReferenceCount = 0
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { memberDeclaration -> irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
if (memberDeclaration is IrFunction) if (memberDeclaration is IrFunction)
lowerCallableReferences(context, memberDeclaration) lowerCallableReferences(this, memberDeclaration)
else else
null null
} }
@@ -39,31 +42,43 @@ internal class CallableReferenceLowering(val context: KonanBackendContext) : Dec
* Replaces all callable references in the function body to unbound ones. * Replaces all callable references in the function body to unbound ones.
* Returns the list of this function and all created ones. * Returns the list of this function and all created ones.
*/ */
private fun lowerCallableReferences(context: KonanBackendContext, function: IrFunction): List<IrFunction> { private fun lowerCallableReferences(lower: CallableReferenceLowering, function: IrFunction): List<IrFunction> {
val transformer = CallableReferencesUnbinder(context, function) val transformer = CallableReferencesUnbinder(lower, function)
function.transformChildrenVoid(transformer) function.transformChildrenVoid(transformer)
return function.singletonList() + transformer.createdFunctions return function.singletonList() + transformer.createdFunctions
} }
private object DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE :
IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE")
/** /**
* Replaces all callable references in the function body to unbound ones. * Replaces all callable references in the function body to unbound ones.
* Adds all created functions to [createdFunctions]. * Adds all created functions to [createdFunctions].
*/ */
private class CallableReferencesUnbinder(val context: KonanBackendContext, private class CallableReferencesUnbinder(val lower: CallableReferenceLowering,
val function: IrFunction) : IrElementTransformerVoid() { val function: IrFunction) : IrElementTransformerVoid() {
val createdFunctions = mutableListOf<IrFunction>() val createdFunctions = mutableListOf<IrFunction>()
private val builtIns = lower.context.builtIns
override fun visitElement(element: IrElement): IrElement { override fun visitElement(element: IrElement): IrElement {
return super.visitElement(element) return super.visitElement(element)
} }
private val unboundCallableReferenceType by lazy { private val unboundCallableReferenceType by lazy {
context.builtIns.getKonanInternalClass("UnboundCallableReference").defaultType builtIns.getKonanInternalClass("UnboundCallableReference").defaultType
} }
private val simpleFunctionImplClass by lazy { private val simpleFunctionImplClass by lazy {
context.builtIns.getKonanInternalClass("SimpleFunctionImpl") builtIns.getKonanInternalClass("SimpleFunctionImpl")
}
private val simpleFunctionImplBoundArgsGetter by lazy {
simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors()
.filterIsInstance<PropertyDescriptor>()
.single { it.name.asString() == "boundArgs" }
.getter!!
} }
override fun visitCallableReference(expression: IrCallableReference): IrExpression { override fun visitCallableReference(expression: IrCallableReference): IrExpression {
@@ -77,8 +92,8 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
val startOffset = expression.startOffset val startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
// The code below creates a call to `SimpleFunctionImpl` constructor which creates the value to be used // The code below creates a call to `SimpleFunctionImpl` constructor which creates the object implementing
// as required callable reference. // the function type.
// Create the function to be used as `unboundRef` of `SimpleFunctionImpl`: // Create the function to be used as `unboundRef` of `SimpleFunctionImpl`:
val newFunction = createSimpleFunctionImplTarget(descriptor, unboundParams, boundParams, startOffset, endOffset) val newFunction = createSimpleFunctionImplTarget(descriptor, unboundParams, boundParams, startOffset, endOffset)
@@ -119,20 +134,13 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
// Create new function declaration: // Create new function declaration:
val origin = object : IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE") {}
val simpleFunctionImplBoundArgsGetter =
simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors()
.filterIsInstance<PropertyDescriptor>().filter { it.name.asString() == "boundArgs" }
.single().getter!!
val boundArgsArray = IrCallImpl(startOffset, endOffset, simpleFunctionImplBoundArgsGetter, null).apply { val boundArgsArray = IrCallImpl(startOffset, endOffset, simpleFunctionImplBoundArgsGetter, null).apply {
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, newDescriptor.valueParameters[0]) dispatchReceiver = IrGetValueImpl(startOffset, endOffset, newDescriptor.valueParameters[0])
} }
// TODO: do not call boundArgs getter for each bound argument. // TODO: do not call boundArgs getter for each bound argument.
val arrayGet = boundArgsArray.type.memberScope.getContributedDescriptors() val arrayGet = boundArgsArray.type.memberScope.getContributedDescriptors()
.filterIsInstance<FunctionDescriptor>().filter { it.name.asString() == "get" }.single() .filterIsInstance<FunctionDescriptor>().single { it.name.asString() == "get" }
// TODO: some handling for type parameters is probably required here. // TODO: some handling for type parameters is probably required here.
@@ -150,14 +158,14 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
call.addArguments(boundParams.mapIndexed { index, param -> call.addArguments(boundParams.mapIndexed { index, param ->
param to IrCallImpl(startOffset, endOffset, arrayGet).apply { param to IrCallImpl(startOffset, endOffset, arrayGet).apply {
dispatchReceiver = boundArgsArray dispatchReceiver = boundArgsArray
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, index)) putValueArgument(0, IrConstImpl.int(startOffset, endOffset, builtIns.intType, index))
} }
}) })
val ret = IrReturnImpl(startOffset, endOffset, newDescriptor, call) val ret = IrReturnImpl(startOffset, endOffset, newDescriptor, call)
val newFunction = IrFunctionImpl( val newFunction = IrFunctionImpl(
startOffset, endOffset, origin, startOffset, endOffset, DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE,
newDescriptor, newDescriptor,
IrBlockBodyImpl(startOffset, endOffset, listOf(ret)) IrBlockBodyImpl(startOffset, endOffset, listOf(ret))
) )
@@ -171,7 +179,7 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
private fun createSimpleFunctionImplTargetDescriptor(descriptor: CallableDescriptor, private fun createSimpleFunctionImplTargetDescriptor(descriptor: CallableDescriptor,
unboundParams: List<ParameterDescriptor>): FunctionDescriptor { unboundParams: List<ParameterDescriptor>): FunctionDescriptor {
val newName = Name.identifier(descriptor.hashCode().toString()) // FIXME val newName = Name.identifier("${descriptor.name}\$bound-${lower.callableReferenceCount++}")
val newDescriptor = SimpleFunctionDescriptorImpl.create( val newDescriptor = SimpleFunctionDescriptorImpl.create(
function.descriptor.containingDeclaration, Annotations.EMPTY, function.descriptor.containingDeclaration, Annotations.EMPTY,
@@ -179,19 +187,34 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
val simpleFunctionImplType = simpleFunctionImplClass.defaultType val simpleFunctionImplType = simpleFunctionImplClass.defaultType
// Maps each unbound param of original function to parameter of new function // Map each unbound param of original function to parameter of new function.
val newUnboundParams = unboundParams.mapIndexed { index, param -> val newUnboundParams = unboundParams.mapIndexed { index, param ->
ValueParameterDescriptorImpl(newDescriptor, null, index + 1, ValueParameterDescriptorImpl(
Annotations.EMPTY, param.name, param.type, containingDeclaration = newDescriptor,
false, false, false, false, original = null,
(param as? ValueParameterDescriptor)?.varargElementType, index = index + 1,
SourceElement.NO_SOURCE) annotations = Annotations.EMPTY,
name = param.name,
outType = param.type,
declaresDefaultValue = false,
isCrossinline = false, isNoinline = false,
isCoroutine = false,
varargElementType = (param as? ValueParameterDescriptor)?.varargElementType,
source = SourceElement.NO_SOURCE)
} }
// `<func>: SimpleFunctionImpl` // `<func>: SimpleFunctionImpl`
val functionParameter = ValueParameterDescriptorImpl(newDescriptor, null, 0, Annotations.EMPTY, val functionParameter = ValueParameterDescriptorImpl(
Name.special("<func>"), containingDeclaration = newDescriptor,
simpleFunctionImplType, false, false, false, false, null, SourceElement.NO_SOURCE) original = null,
index = 0,
annotations = Annotations.EMPTY,
name = Name.special("<func>"),
outType = simpleFunctionImplType,
declaresDefaultValue = false,
isCrossinline = false, isNoinline = false,
isCoroutine = false, varargElementType = null,
source = SourceElement.NO_SOURCE)
val newValueParameters = listOf(functionParameter) + newUnboundParams val newValueParameters = listOf(functionParameter) + newUnboundParams
+1 -1
View File
@@ -185,7 +185,7 @@ KConstRef Kotlin_getCurrentStackTrace() {
} }
// TODO: consider handling it with compiler magic instead. // TODO: consider handling it with compiler magic instead.
KRef Kotlin_internal_undefined() { KRef Kotlin_konan_internal_undefined() {
return nullptr; return nullptr;
} }
+1 -1
View File
@@ -100,7 +100,7 @@ KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex);
KConstRef Kotlin_getCurrentStackTrace(); KConstRef Kotlin_getCurrentStackTrace();
KRef Kotlin_internal_undefined(); KRef Kotlin_konan_internal_undefined();
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -4,5 +4,5 @@ package konan.internal
* Returns undefined value of type `T`. * Returns undefined value of type `T`.
* This method is unsafe and should be used with care. * This method is unsafe and should be used with care.
*/ */
@SymbolName("Kotlin_internal_undefined") @SymbolName("Kotlin_konan_internal_undefined")
internal external fun <T> undefined(): T internal external fun <T> undefined(): T