Minor. Reformat

This commit is contained in:
Mikhael Bogdanov
2018-06-14 11:04:22 +02:00
parent 3dff3d61f5
commit 7c615eb7ab
9 changed files with 201 additions and 175 deletions
@@ -37,14 +37,14 @@ interface InnerClassConsumer {
if (defaultImpls) { if (defaultImpls) {
if (DescriptorUtils.isLocal(descriptor)) return null if (DescriptorUtils.isLocal(descriptor)) return null
val classDescriptorImpl = ClassDescriptorImpl( val classDescriptorImpl = ClassDescriptorImpl(
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME), descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE, Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
/* isExternal = */ false, LockBasedStorageManager.NO_LOCKS) /* isExternal = */ false, LockBasedStorageManager.NO_LOCKS
)
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null) classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
return classDescriptorImpl return classDescriptorImpl
} } else {
else {
return if (DescriptorUtils.isTopLevelDeclaration(descriptor)) null else descriptor return if (DescriptorUtils.isTopLevelDeclaration(descriptor)) null else descriptor
} }
} }
@@ -19,19 +19,19 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineCodegenForDefaultBody( class InlineCodegenForDefaultBody(
function: FunctionDescriptor, function: FunctionDescriptor,
codegen: ExpressionCodegen, codegen: ExpressionCodegen,
val state: GenerationState, val state: GenerationState,
private val sourceCompilerForInline: SourceCompilerForInline private val sourceCompilerForInline: SourceCompilerForInline
) : CallGenerator { ) : CallGenerator {
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
private val functionDescriptor = private val functionDescriptor =
if (InlineUtil.isArrayConstructorWithLambda(function)) if (InlineUtil.isArrayConstructorWithLambda(function))
FictitiousArrayConstructor.create(function as ConstructorDescriptor) FictitiousArrayConstructor.create(function as ConstructorDescriptor)
else else
function.original function.original
init { init {
@@ -45,7 +45,7 @@ class InlineCodegenForDefaultBody(
init { init {
assert(InlineUtil.isInline(function)) { assert(InlineUtil.isInline(function)) {
"InlineCodegen can inline only inline functions and array constructors: " + function "InlineCodegen can inline only inline functions and array constructors: $function"
} }
sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor) sourceCompilerForInline.initializeInlineFunctionContext(functionDescriptor)
jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompilerForInline.contextKind) jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompilerForInline.contextKind)
@@ -55,18 +55,21 @@ class InlineCodegenForDefaultBody(
} }
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) { override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
val nodeAndSmap = InlineCodegen.createInlineMethodNode(functionDescriptor, jvmSignature, callDefault, null, state, sourceCompilerForInline) val nodeAndSmap =
InlineCodegen.createInlineMethodNode(functionDescriptor, jvmSignature, callDefault, null, state, sourceCompilerForInline)
val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper) val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper)
val node = nodeAndSmap.node val node = nodeAndSmap.node
val transformedMethod = MethodNode( val transformedMethod = MethodNode(
node.access, node.access,
node.name, node.name,
node.desc, node.desc,
node.signature, node.signature,
node.exceptions.toTypedArray()) node.exceptions.toTypedArray()
)
val argsSize = (Type.getArgumentsAndReturnSizes(jvmSignature.asmMethod.descriptor) ushr 2) - if (callableMethod.isStaticCall()) 1 else 0 val argsSize =
(Type.getArgumentsAndReturnSizes(jvmSignature.asmMethod.descriptor) ushr 2) - if (callableMethod.isStaticCall()) 1 else 0
node.accept(object : InlineAdapter(transformedMethod, 0, childSourceMapper) { node.accept(object : InlineAdapter(transformedMethod, 0, childSourceMapper) {
override fun visitLocalVariable(name: String, desc: String, signature: String?, start: Label, end: Label, index: Int) { override fun visitLocalVariable(name: String, desc: String, signature: String?, start: Label, end: Label, index: Int) {
val startLabel = if (index < argsSize) methodStartLabel else start val startLabel = if (index < argsSize) methodStartLabel else start
@@ -77,7 +80,12 @@ class InlineCodegenForDefaultBody(
transformedMethod.accept(MethodBodyVisitor(codegen.visitor)) transformedMethod.accept(MethodBodyVisitor(codegen.visitor))
} }
override fun genValueAndPut(valueParameterDescriptor: ValueParameterDescriptor, argumentExpression: KtExpression, parameterType: Type, parameterIndex: Int) { override fun genValueAndPut(
valueParameterDescriptor: ValueParameterDescriptor,
argumentExpression: KtExpression,
parameterType: Type,
parameterIndex: Int
) {
throw UnsupportedOperationException("Shouldn't be called") throw UnsupportedOperationException("Shouldn't be called")
} }
@@ -52,8 +52,8 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this) val builder = ParametersBuilder.initializeBuilderFrom(AsmTypes.OBJECT_TYPE, invokeMethod.descriptor, this)
for (info in capturedVars) { for (info in capturedVars) {
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, "")) ?: val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName) ?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName)
builder.addCapturedParam(field, info.fieldName) builder.addCapturedParam(field, info.fieldName)
} }
@@ -74,11 +74,11 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : LabelOwner {
class DefaultLambda( class DefaultLambda(
override val lambdaClassType: Type, override val lambdaClassType: Type,
private val capturedArgs: Array<Type>, private val capturedArgs: Array<Type>,
val parameterDescriptor: ValueParameterDescriptor, val parameterDescriptor: ValueParameterDescriptor,
val offset: Int, val offset: Int,
val needReification: Boolean val needReification: Boolean
) : LambdaInfo(parameterDescriptor.isCrossinline) { ) : LambdaInfo(parameterDescriptor.isCrossinline) {
override var isBoundCallableReference by Delegates.notNull<Boolean>() override var isBoundCallableReference by Delegates.notNull<Boolean>()
@@ -103,8 +103,15 @@ class DefaultLambda(
val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName) val classReader = buildClassReaderByInternalName(sourceCompiler.state, lambdaClassType.internalName)
var isPropertyReference = false var isPropertyReference = false
var isFunctionReference = false var isFunctionReference = false
classReader.accept(object: ClassVisitor(API){ classReader.accept(object : ClassVisitor(API) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<out String>?) { override fun visit(
version: Int,
access: Int,
name: String,
signature: String?,
superName: String?,
interfaces: Array<out String>?
) {
isPropertyReference = superName?.startsWith("kotlin/jvm/internal/PropertyReference") ?: false isPropertyReference = superName?.startsWith("kotlin/jvm/internal/PropertyReference") ?: false
isFunctionReference = "kotlin/jvm/internal/FunctionReference" == superName isFunctionReference = "kotlin/jvm/internal/FunctionReference" == superName
@@ -114,19 +121,20 @@ class DefaultLambda(
invokeMethodDescriptor = invokeMethodDescriptor =
parameterDescriptor.type.memberScope parameterDescriptor.type.memberScope
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
.single() .single()
.let { .let {
//property reference generates erased 'get' method //property reference generates erased 'get' method
if (isPropertyReference) it.original else it if (isPropertyReference) it.original else it
} }
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs) val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
val constructor = getMethodNode( val constructor = getMethodNode(
classReader.b, classReader.b,
"<init>", "<init>",
descriptor, descriptor,
lambdaClassType)?.node lambdaClassType
)?.node
assert(constructor != null || capturedArgs.isEmpty()) { assert(constructor != null || capturedArgs.isEmpty()) {
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType" "Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
@@ -139,23 +147,23 @@ class DefaultLambda(
listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it.boxReceiverForBoundReference())) listOf(capturedParamDesc(AsmUtil.RECEIVER_NAME, it.boxReceiverForBoundReference()))
} ?: emptyList() } ?: emptyList()
else else
constructor?.findCapturedFieldAssignmentInstructions()?.map { constructor?.findCapturedFieldAssignmentInstructions()?.map { fieldNode ->
fieldNode ->
capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc)) capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc))
}?.toList() ?: emptyList() }?.toList() ?: emptyList()
isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty() isBoundCallableReference = (isFunctionReference || isPropertyReference) && capturedVars.isNotEmpty()
invokeMethod = Method( invokeMethod = Method(
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(), (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
) )
node = getMethodNode( node = getMethodNode(
classReader.b, classReader.b,
invokeMethod.name, invokeMethod.name,
invokeMethod.descriptor, invokeMethod.descriptor,
lambdaClassType) ?: error("Can't find method '${invokeMethod.name}${invokeMethod.descriptor}' in '${classReader.className}'") lambdaClassType
) ?: error("Can't find method '${invokeMethod.name}${invokeMethod.descriptor}' in '${classReader.className}'")
if (needReification) { if (needReification) {
//nested classes could also require reification //nested classes could also require reification
@@ -166,19 +174,19 @@ class DefaultLambda(
fun Type.boxReceiverForBoundReference() = AsmUtil.boxType(this) fun Type.boxReceiverForBoundReference() = AsmUtil.boxType(this)
abstract class ExpressionLambda(protected val typeMapper: KotlinTypeMapper, isCrossInline: Boolean): LambdaInfo(isCrossInline) { abstract class ExpressionLambda(protected val typeMapper: KotlinTypeMapper, isCrossInline: Boolean) : LambdaInfo(isCrossInline) {
override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) { override fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner) {
val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor) val jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor)
val asmMethod = jvmMethodSignature.asmMethod val asmMethod = jvmMethodSignature.asmMethod
val methodNode = MethodNode( val methodNode = MethodNode(
API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, sourceCompiler.state), API, AsmUtil.getMethodAsmFlags(invokeMethodDescriptor, OwnerKind.IMPLEMENTATION, sourceCompiler.state),
asmMethod.name, asmMethod.descriptor, null, null asmMethod.name, asmMethod.descriptor, null, null
) )
node = wrapWithMaxLocalCalc(methodNode).let { adapter -> node = wrapWithMaxLocalCalc(methodNode).let { adapter ->
val smap = sourceCompiler.generateLambdaBody( val smap = sourceCompiler.generateLambdaBody(
adapter, jvmMethodSignature, this adapter, jvmMethodSignature, this
) )
adapter.visitMaxs(-1, -1) adapter.visitMaxs(-1, -1)
SMAPAndMethodNode(methodNode, smap) SMAPAndMethodNode(methodNode, smap)
@@ -187,10 +195,10 @@ abstract class ExpressionLambda(protected val typeMapper: KotlinTypeMapper, isCr
} }
class PsiExpressionLambda( class PsiExpressionLambda(
expression: KtExpression, expression: KtExpression,
typeMapper: KotlinTypeMapper, typeMapper: KotlinTypeMapper,
isCrossInline: Boolean, isCrossInline: Boolean,
override val isBoundCallableReference: Boolean override val isBoundCallableReference: Boolean
) : ExpressionLambda(typeMapper, isCrossInline) { ) : ExpressionLambda(typeMapper, isCrossInline) {
override val lambdaClassType: Type override val lambdaClassType: Type
@@ -211,21 +219,21 @@ class PsiExpressionLambda(
init { init {
val bindingContext = typeMapper.bindingContext val bindingContext = typeMapper.bindingContext
val function = bindingContext.get<PsiElement, SimpleFunctionDescriptor>(BindingContext.FUNCTION, functionWithBodyOrCallableReference) val function =
bindingContext.get<PsiElement, SimpleFunctionDescriptor>(BindingContext.FUNCTION, functionWithBodyOrCallableReference)
if (function == null && expression is KtCallableReferenceExpression) { if (function == null && expression is KtCallableReferenceExpression) {
val variableDescriptor = val variableDescriptor =
bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors ?: bindingContext.get(BindingContext.VARIABLE, functionWithBodyOrCallableReference) as? VariableDescriptorWithAccessors
throw AssertionError("""Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}""") ?: throw AssertionError("""Reference expression not resolved to variable descriptor with accessors: ${expression.getText()}""")
classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor) classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor)
lambdaClassType = typeMapper.mapClass(classDescriptor) lambdaClassType = typeMapper.mapClass(classDescriptor)
val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor) val getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor)
invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor) invokeMethodDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor)
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(bindingContext) val resolvedCall = expression.callableReference.getResolvedCallWithAssert(bindingContext)
propertyReferenceInfo = PropertyReferenceInfo( propertyReferenceInfo = PropertyReferenceInfo(
resolvedCall.resultingDescriptor as VariableDescriptor, getFunction resolvedCall.resultingDescriptor as VariableDescriptor, getFunction
) )
} } else {
else {
propertyReferenceInfo = null propertyReferenceInfo = null
invokeMethodDescriptor = function ?: throw AssertionError("Function is not resolved to descriptor: " + expression.text) invokeMethodDescriptor = function ?: throw AssertionError("Function is not resolved to descriptor: " + expression.text)
classDescriptor = anonymousClassForCallable(bindingContext, invokeMethodDescriptor) classDescriptor = anonymousClassForCallable(bindingContext, invokeMethodDescriptor)
@@ -246,9 +254,9 @@ class PsiExpressionLambda(
if (closure.captureThis != null) { if (closure.captureThis != null) {
val type = typeMapper.mapType(closure.captureThis!!) val type = typeMapper.mapType(closure.captureThis!!)
val descriptor = EnclosedValueDescriptor( val descriptor = EnclosedValueDescriptor(
AsmUtil.CAPTURED_THIS_FIELD, null, AsmUtil.CAPTURED_THIS_FIELD, null,
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0), StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0),
type type
) )
add(getCapturedParamInfo(descriptor)) add(getCapturedParamInfo(descriptor))
} }
@@ -258,15 +266,14 @@ class PsiExpressionLambda(
if (isBoundCallableReference) it.boxReceiverForBoundReference() else it if (isBoundCallableReference) it.boxReceiverForBoundReference() else it
} }
val descriptor = EnclosedValueDescriptor( val descriptor = EnclosedValueDescriptor(
AsmUtil.CAPTURED_RECEIVER_FIELD, null, AsmUtil.CAPTURED_RECEIVER_FIELD, null,
StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0), StackValue.field(type, lambdaClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0),
type type
) )
add(getCapturedParamInfo(descriptor)) add(getCapturedParamInfo(descriptor))
} }
closure.captureVariables.values.forEach { closure.captureVariables.values.forEach { descriptor ->
descriptor ->
add(getCapturedParamInfo(descriptor)) add(getCapturedParamInfo(descriptor))
} }
} }
@@ -35,14 +35,14 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val trans
protected fun createRemappingClassBuilderViaFactory(inliningContext: InliningContext): ClassBuilder { protected fun createRemappingClassBuilderViaFactory(inliningContext: InliningContext): ClassBuilder {
val classBuilder = state.factory.newVisitor( val classBuilder = state.factory.newVisitor(
JvmDeclarationOrigin.NO_ORIGIN, JvmDeclarationOrigin.NO_ORIGIN,
Type.getObjectType(transformationInfo.newClassName), Type.getObjectType(transformationInfo.newClassName),
inliningContext.root.sourceCompilerForInline.callsiteFile!! inliningContext.root.sourceCompilerForInline.callsiteFile!!
) )
return RemappingClassBuilder( return RemappingClassBuilder(
classBuilder, classBuilder,
AsmTypeRemapper(inliningContext.typeRemapper, transformationResult) AsmTypeRemapper(inliningContext.typeRemapper, transformationResult)
) )
} }
@@ -52,8 +52,8 @@ abstract class ObjectTransformer<out T : TransformationInfo>(@JvmField val trans
} }
class WhenMappingTransformer( class WhenMappingTransformer(
whenObjectRegenerationInfo: WhenMappingTransformationInfo, whenObjectRegenerationInfo: WhenMappingTransformationInfo,
private val inliningContext: InliningContext private val inliningContext: InliningContext
) : ObjectTransformer<WhenMappingTransformationInfo>(whenObjectRegenerationInfo, inliningContext.state) { ) : ObjectTransformer<WhenMappingTransformationInfo>(whenObjectRegenerationInfo, inliningContext.state) {
override fun doTransform(parentRemapper: FieldRemapper): InlineResult { override fun doTransform(parentRemapper: FieldRemapper): InlineResult {
@@ -72,14 +72,13 @@ class WhenMappingTransformer(
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? { override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
return if (name == fieldNode.name) { return if (name == fieldNode.name) {
classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value) classBuilder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, name, desc, signature, value)
} } else {
else {
null null
} }
} }
override fun visitMethod( override fun visitMethod(
access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>? access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?
): MethodVisitor? { ): MethodVisitor? {
return MethodNode(access, name, desc, signature, exceptions).apply { return MethodNode(access, name, desc, signature, exceptions).apply {
methodNodes.add(this) methodNodes.add(this)
@@ -91,12 +90,12 @@ class WhenMappingTransformer(
"When mapping ${fieldNode.owner} class should contain only one method but: " + methodNodes.joinToString { it.name } "When mapping ${fieldNode.owner} class should contain only one method but: " + methodNodes.joinToString { it.name }
} }
val clinit = methodNodes.first() val clinit = methodNodes.first()
assert(clinit.name == "<clinit>", { "When mapping should contains only <clinit> method, but contains '${clinit.name}'" }) assert(clinit.name == "<clinit>") { "When mapping should contains only <clinit> method, but contains '${clinit.name}'" }
val transformedClinit = cutOtherMappings(clinit) val transformedClinit = cutOtherMappings(clinit)
val result = classBuilder.newMethod( val result = classBuilder.newMethod(
JvmDeclarationOrigin.NO_ORIGIN, transformedClinit.access, transformedClinit.name, transformedClinit.desc, JvmDeclarationOrigin.NO_ORIGIN, transformedClinit.access, transformedClinit.name, transformedClinit.desc,
transformedClinit.signature, transformedClinit.exceptions.toTypedArray() transformedClinit.signature, transformedClinit.exceptions.toTypedArray()
) )
transformedClinit.accept(result) transformedClinit.accept(result)
classBuilder.done() classBuilder.done()
@@ -106,7 +105,7 @@ class WhenMappingTransformer(
private fun cutOtherMappings(node: MethodNode): MethodNode { private fun cutOtherMappings(node: MethodNode): MethodNode {
val myArrayAccess = InsnSequence(node.instructions).first { val myArrayAccess = InsnSequence(node.instructions).first {
it is FieldInsnNode && it.name.equals(transformationInfo.fieldNode.name) it is FieldInsnNode && it.name == transformationInfo.fieldNode.name
} }
val myValuesAccess = generateSequence(myArrayAccess) { it.previous }.first { val myValuesAccess = generateSequence(myArrayAccess) { it.previous }.first {
@@ -125,8 +124,8 @@ class WhenMappingTransformer(
} }
private fun isValues(node: AbstractInsnNode) = private fun isValues(node: AbstractInsnNode) =
node is MethodInsnNode && node is MethodInsnNode &&
node.opcode == Opcodes.INVOKESTATIC && node.opcode == Opcodes.INVOKESTATIC &&
node.name == "values" && node.name == "values" &&
node.desc == "()[" + Type.getObjectType(node.owner).descriptor node.desc == "()[" + Type.getObjectType(node.owner).descriptor
} }
@@ -26,9 +26,9 @@ val KOTLIN_DEBUG_STRATA_NAME = "KotlinDebug"
//TODO join parameter //TODO join parameter
class SMAPBuilder( class SMAPBuilder(
val source: String, val source: String,
val path: String, val path: String,
private val fileMappings: List<FileMapping> private val fileMappings: List<FileMapping>
) { ) {
private val header = "SMAP\n$source\nKotlin" private val header = "SMAP\n$source\nKotlin"
@@ -58,9 +58,11 @@ class SMAPBuilder(
val combinedMapping = FileMapping(source, path) val combinedMapping = FileMapping(source, path)
realMappings.forEach { fileMapping -> realMappings.forEach { fileMapping ->
fileMapping.lineMappings.filter { it.callSiteMarker != null }.forEach { (_, dest, range, callSiteMarker) -> fileMapping.lineMappings.filter { it.callSiteMarker != null }.forEach { (_, dest, range, callSiteMarker) ->
combinedMapping.addRangeMapping(RangeMapping( combinedMapping.addRangeMapping(
RangeMapping(
callSiteMarker!!.lineNumber, dest, range callSiteMarker!!.lineNumber, dest, range
)) )
)
} }
} }
@@ -88,7 +90,7 @@ class SMAPBuilder(
} }
open class NestedSourceMapper( open class NestedSourceMapper(
override val parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo override val parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo
) : DefaultSourceMapper(sourceInfo) { ) : DefaultSourceMapper(sourceInfo) {
private val visitedLines = TIntIntHashMap() private val visitedLines = TIntIntHashMap()
@@ -100,11 +102,10 @@ open class NestedSourceMapper(
return if (mappedLineNumber > 0) { return if (mappedLineNumber > 0) {
mappedLineNumber mappedLineNumber
} } else {
else {
val rangeForMapping = val rangeForMapping =
(if (lastVisitedRange?.contains(lineNumber) ?: false) lastVisitedRange!! else findMappingIfExists(lineNumber)) (if (lastVisitedRange?.contains(lineNumber) ?: false) lastVisitedRange!! else findMappingIfExists(lineNumber))
?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}") ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}")
val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber) val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber)
val newLineNumber = parent.mapLineNumber(sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path) val newLineNumber = parent.mapLineNumber(sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path)
if (newLineNumber > 0) { if (newLineNumber > 0) {
@@ -116,8 +117,7 @@ open class NestedSourceMapper(
} }
private fun findMappingIfExists(lineNumber: Int): RangeMapping? { private fun findMappingIfExists(lineNumber: Int): RangeMapping? {
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator { val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator { value, key ->
value, key ->
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
}) })
return if (index < 0) null else ranges[index] return if (index < 0) null else ranges[index]
@@ -125,7 +125,7 @@ open class NestedSourceMapper(
} }
open class InlineLambdaSourceMapper( open class InlineLambdaSourceMapper(
parent: SourceMapper, smap: SMAPAndMethodNode parent: SourceMapper, smap: SMAPAndMethodNode
) : NestedSourceMapper(parent, smap.sortedRanges, smap.classSMAP.sourceInfo) { ) : NestedSourceMapper(parent, smap.sortedRanges, smap.classSMAP.sourceInfo) {
init { init {
@@ -208,14 +208,14 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper {
constructor(sourceInfo: SourceInfo, fileMappings: List<FileMapping>) : this(sourceInfo) { constructor(sourceInfo: SourceInfo, fileMappings: List<FileMapping>) : this(sourceInfo) {
fileMappings.asSequence().drop(1) fileMappings.asSequence().drop(1)
//default one mapped through sourceInfo //default one mapped through sourceInfo
.forEach { fileMapping -> .forEach { fileMapping ->
val newFileMapping = getOrRegisterNewSource(fileMapping.name, fileMapping.path) val newFileMapping = getOrRegisterNewSource(fileMapping.name, fileMapping.path)
fileMapping.lineMappings.forEach { fileMapping.lineMappings.forEach {
newFileMapping.mapNewInterval(it.source, it.dest, it.range) newFileMapping.mapNewInterval(it.source, it.dest, it.range)
maxUsedValue = Math.max(it.maxDest, maxUsedValue) maxUsedValue = Math.max(it.maxDest, maxUsedValue)
}
} }
}
} }
private fun createKey(name: String, path: String) = "$name#$path" private fun createKey(name: String, path: String) = "$name#$path"
@@ -282,11 +282,11 @@ class RawFileMapping(val name: String, val path: String) {
private var lastMappedWithNewIndex = -1000 private var lastMappedWithNewIndex = -1000
fun toFileMapping() = fun toFileMapping() =
FileMapping(name, path).apply { FileMapping(name, path).apply {
for (range in rangeMappings) { for (range in rangeMappings) {
addRangeMapping(range) addRangeMapping(range)
}
} }
}
fun initRange(start: Int, end: Int) { fun initRange(start: Int, end: Int) {
assert(rangeMappings.isEmpty()) { "initRange should only be called for empty mapping" } assert(rangeMappings.isEmpty()) { "initRange should only be called for empty mapping" }
@@ -301,8 +301,7 @@ class RawFileMapping(val name: String, val path: String) {
rangeMapping = rangeMappings.last() rangeMapping = rangeMappings.last()
rangeMapping.range += source - lastMappedWithNewIndex rangeMapping.range += source - lastMappedWithNewIndex
dest = rangeMapping.mapSourceToDest(source) dest = rangeMapping.mapSourceToDest(source)
} } else {
else {
dest = currentIndex + 1 dest = currentIndex + 1
rangeMapping = RangeMapping(source, dest, callSiteMarker = callSiteMarker) rangeMapping = RangeMapping(source, dest, callSiteMarker = callSiteMarker)
rangeMappings.add(rangeMapping) rangeMappings.add(rangeMapping)
@@ -93,7 +93,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
override val lookupLocation = KotlinLookupLocation(callElement) override val lookupLocation = KotlinLookupLocation(callElement)
override val callElementText by lazy { override val callElementText: String by lazy {
callElement.text callElement.text
} }
@@ -203,7 +203,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
mappings: List<FileMapping> mappings: List<FileMapping>
): SMAP { ): SMAP {
val containingFile = declaration.containingFile val containingFile = declaration.containingFile
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in " + containingFile) CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in $containingFile")
return SMAP(mappings) return SMAP(mappings)
} }
@@ -261,7 +261,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor) val element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor)
if (!(element is KtNamedFunction || element is KtPropertyAccessor)) { if (!(element is KtNamedFunction || element is KtPropertyAccessor)) {
throw IllegalStateException("Couldn't find declaration for function " + callableDescriptor) throw IllegalStateException("Couldn't find declaration for function $callableDescriptor")
} }
val inliningFunction = element as KtDeclarationWithBody? val inliningFunction = element as KtDeclarationWithBody?
@@ -274,7 +274,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
//for maxLocals calculation //for maxLocals calculation
val maxCalcAdapter = wrapWithMaxLocalCalc(node) val maxCalcAdapter = wrapWithMaxLocalCalc(node)
val parentContext = context.parentContext ?: error("Context has no parent: " + context) val parentContext = context.parentContext ?: error("Context has no parent: $context")
val methodContext = parentContext.intoFunction(callableDescriptor) val methodContext = parentContext.intoFunction(callableDescriptor)
val smap = if (callDefault) { val smap = if (callDefault) {
@@ -286,7 +286,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
false false
) )
if (element !is KtNamedFunction) { if (element !is KtNamedFunction) {
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor) throw IllegalStateException("Property accessors with default parameters not supported $callableDescriptor")
} }
FunctionCodegen.generateDefaultImplBody( FunctionCodegen.generateDefaultImplBody(
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
@@ -416,7 +416,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
return PackageContext(descriptor, state.rootContext, null, sourceFile) return PackageContext(descriptor, state.rootContext, null, sourceFile)
} }
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor) val container = descriptor.containingDeclaration ?: error("No container for descriptor: $descriptor")
val parent = getContext( val parent = getContext(
container, container,
descriptor, descriptor,
@@ -454,7 +454,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
parent.intoFunction(descriptor) parent.intoFunction(descriptor)
} }
else -> { else -> {
throw IllegalStateException("Couldn't build context for " + descriptor) throw IllegalStateException("Couldn't build context for $descriptor")
} }
} }
@@ -23,11 +23,10 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
//This method was moved to separate class cause of LightClass generation problem: KT-18419 //This method was moved to separate class cause of LightClass generation problem: KT-18419
//Move it back to inlineCodegenUtil after fix //Move it back to inlineCodegenUtil after fix
fun initDefaultSourceMappingIfNeeded( fun initDefaultSourceMappingIfNeeded(
context: CodegenContext<*>, codegen: MemberCodegen<*>, state: GenerationState context: CodegenContext<*>, codegen: MemberCodegen<*>, state: GenerationState
) { ) {
if (state.isInlineDisabled) return if (state.isInlineDisabled) return
var parentContext: CodegenContext<*>? = context.parentContext var parentContext: CodegenContext<*>? = context.parentContext
while (parentContext != null) { while (parentContext != null) {
if (parentContext.isInlineMethodContext) { if (parentContext.isInlineMethodContext) {
@@ -35,52 +35,62 @@ enum class JvmDeclarationOriginKind {
} }
class JvmDeclarationOrigin( class JvmDeclarationOrigin(
val originKind: JvmDeclarationOriginKind, val originKind: JvmDeclarationOriginKind,
val element: PsiElement?, val element: PsiElement?,
val descriptor: DeclarationDescriptor? val descriptor: DeclarationDescriptor?
) { ) {
companion object { companion object {
@JvmField val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null) @JvmField
val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null)
} }
} }
@JvmOverloads @JvmOverloads
fun OtherOrigin(element: PsiElement?, descriptor: DeclarationDescriptor? = null) = fun OtherOrigin(element: PsiElement?, descriptor: DeclarationDescriptor? = null) =
if (element == null && descriptor == null) if (element == null && descriptor == null)
JvmDeclarationOrigin.NO_ORIGIN JvmDeclarationOrigin.NO_ORIGIN
else else
JvmDeclarationOrigin(OTHER, element, descriptor) JvmDeclarationOrigin(OTHER, element, descriptor)
@JvmOverloads @JvmOverloads
fun OtherOriginFromPure(element: KtPureElement?, descriptor: DeclarationDescriptor? = null) = fun OtherOriginFromPure(element: KtPureElement?, descriptor: DeclarationDescriptor? = null) =
OtherOrigin(element?.psiOrParent, descriptor) OtherOrigin(element?.psiOrParent, descriptor)
fun OtherOrigin(descriptor: DeclarationDescriptor) = JvmDeclarationOrigin(OTHER, null, descriptor) fun OtherOrigin(descriptor: DeclarationDescriptor) = JvmDeclarationOrigin(OTHER, null, descriptor)
fun Bridge(descriptor: DeclarationDescriptor, element: PsiElement? = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)): JvmDeclarationOrigin = fun Bridge(
JvmDeclarationOrigin(BRIDGE, element, descriptor) descriptor: DeclarationDescriptor,
element: PsiElement? = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
): JvmDeclarationOrigin =
JvmDeclarationOrigin(BRIDGE, element, descriptor)
fun PackagePart(file: KtFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(PACKAGE_PART, file, descriptor) fun PackagePart(file: KtFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(PACKAGE_PART, file, descriptor)
/** /**
* @param representativeFile one of the files representing this multifile class (will be used for diagnostics) * @param representativeFile one of the files representing this multifile class (will be used for diagnostics)
*/ */
fun MultifileClass(representativeFile: KtFile?, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = fun MultifileClass(representativeFile: KtFile?, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS, representativeFile, descriptor) JvmDeclarationOrigin(MULTIFILE_CLASS, representativeFile, descriptor)
fun MultifileClassPart(file: KtFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = fun MultifileClassPart(file: KtFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS_PART, file, descriptor) JvmDeclarationOrigin(MULTIFILE_CLASS_PART, file, descriptor)
fun DefaultImpls(element: PsiElement?, descriptor: ClassDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(INTERFACE_DEFAULT_IMPL, element, descriptor) fun DefaultImpls(element: PsiElement?, descriptor: ClassDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(INTERFACE_DEFAULT_IMPL, element, descriptor)
fun Delegation(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(DELEGATION, element, descriptor) fun Delegation(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(DELEGATION, element, descriptor)
fun SamDelegation(descriptor: FunctionDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SAM_DELEGATION, null, descriptor) fun SamDelegation(descriptor: FunctionDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SAM_DELEGATION, null, descriptor)
fun Synthetic(element: PsiElement?, descriptor: CallableMemberDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(SYNTHETIC, element, descriptor) fun Synthetic(element: PsiElement?, descriptor: CallableMemberDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(SYNTHETIC, element, descriptor)
val CollectionStub = JvmDeclarationOrigin(COLLECTION_STUB, null, null) val CollectionStub = JvmDeclarationOrigin(COLLECTION_STUB, null, null)
fun AugmentedBuiltInApi(descriptor: CallableDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(AUGMENTED_BUILTIN_API, null, descriptor) fun AugmentedBuiltInApi(descriptor: CallableDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(AUGMENTED_BUILTIN_API, null, descriptor)
fun ErasedInlineClassOrigin(element: PsiElement?, descriptor: ClassDescriptor): JvmDeclarationOrigin = fun ErasedInlineClassOrigin(element: PsiElement?, descriptor: ClassDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(ERASED_INLINE_CLASS, element, descriptor) JvmDeclarationOrigin(ERASED_INLINE_CLASS, element, descriptor)
@@ -25,9 +25,9 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.* import java.util.*
private class IrEmptyVarargExpression( private class IrEmptyVarargExpression(
override val type: KotlinType, override val type: KotlinType,
override val startOffset: Int, override val startOffset: Int,
override val endOffset: Int override val endOffset: Int
) : IrExpression { ) : IrExpression {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R { override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
TODO("not implemented") TODO("not implemented")
@@ -43,10 +43,10 @@ private class IrEmptyVarargExpression(
} }
open class IrIntrinsicFunction( open class IrIntrinsicFunction(
val expression: IrMemberAccessExpression, val expression: IrMemberAccessExpression,
val signature: JvmMethodSignature, val signature: JvmMethodSignature,
val context: JvmBackendContext, val context: JvmBackendContext,
val argsTypes: List<Type> = expression.argTypes(context) val argsTypes: List<Type> = expression.argTypes(context)
) : Callable { ) : Callable {
override val owner: Type override val owner: Type
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
@@ -84,12 +84,11 @@ open class IrIntrinsicFunction(
open fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue { open fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
val args = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver) + val args = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver) +
expression.descriptor.valueParameters.mapIndexed { i, descriptor -> expression.descriptor.valueParameters.mapIndexed { i, descriptor ->
expression.getValueArgument(i) ?: expression.getValueArgument(i) ?: if (descriptor.isVararg)
if (descriptor.isVararg) IrEmptyVarargExpression(descriptor.type, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
IrEmptyVarargExpression(descriptor.type, UNDEFINED_OFFSET, UNDEFINED_OFFSET) else error("Unknown parameter: $descriptor in $expression")
else error("Unknown parameter: $descriptor in $expression") }
}
args.forEachIndexed { i, irExpression -> args.forEachIndexed { i, irExpression ->
if (irExpression is IrEmptyVarargExpression) { if (irExpression is IrEmptyVarargExpression) {
@@ -98,8 +97,7 @@ open class IrIntrinsicFunction(
it.aconst(0) it.aconst(0)
it.newarray(AsmUtil.correctElementType(parameterType)) it.newarray(AsmUtil.correctElementType(parameterType))
}.put(parameterType, codegen.mv) }.put(parameterType, codegen.mv)
} } else {
else {
genArg(irExpression, codegen, i, data) genArg(irExpression, codegen, i, data)
} }
} }
@@ -111,33 +109,39 @@ open class IrIntrinsicFunction(
} }
companion object { companion object {
fun create(expression: IrMemberAccessExpression, fun create(
signature: JvmMethodSignature, expression: IrMemberAccessExpression,
context: JvmBackendContext, signature: JvmMethodSignature,
argsTypes: List<Type> = expression.argTypes(context), context: JvmBackendContext,
invokeInstuction: IrIntrinsicFunction.(InstructionAdapter) -> Unit): IrIntrinsicFunction { argsTypes: List<Type> = expression.argTypes(context),
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Unit
): IrIntrinsicFunction {
return object : IrIntrinsicFunction(expression, signature, context, argsTypes) { return object : IrIntrinsicFunction(expression, signature, context, argsTypes) {
override fun genInvokeInstruction(v: InstructionAdapter) = invokeInstuction(v) override fun genInvokeInstruction(v: InstructionAdapter) = invokeInstruction(v)
} }
} }
fun createWithResult(expression: IrMemberAccessExpression, fun createWithResult(
signature: JvmMethodSignature, expression: IrMemberAccessExpression,
context: JvmBackendContext, signature: JvmMethodSignature,
argsTypes: List<Type> = expression.argTypes(context), context: JvmBackendContext,
invokeInstuction: IrIntrinsicFunction.(InstructionAdapter) -> Type): IrIntrinsicFunction { argsTypes: List<Type> = expression.argTypes(context),
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Type
): IrIntrinsicFunction {
return object : IrIntrinsicFunction(expression, signature, context, argsTypes) { return object : IrIntrinsicFunction(expression, signature, context, argsTypes) {
override fun genInvokeInstructionWithResult(v: InstructionAdapter) = invokeInstuction(v) override fun genInvokeInstructionWithResult(v: InstructionAdapter) = invokeInstruction(v)
} }
} }
fun create(expression: IrMemberAccessExpression, fun create(
signature: JvmMethodSignature, expression: IrMemberAccessExpression,
context: JvmBackendContext, signature: JvmMethodSignature,
type: Type, context: JvmBackendContext,
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Unit): IrIntrinsicFunction { type: Type,
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Unit
): IrIntrinsicFunction {
return create(expression, signature, context, listOf(type), invokeInstruction) return create(expression, signature, context, listOf(type), invokeInstruction)
} }
} }
@@ -153,7 +157,7 @@ fun IrMemberAccessExpression.argTypes(context: JvmBackendContext): ArrayList<Typ
fun IrMemberAccessExpression.receiverAndArgs(): List<IrExpression> { fun IrMemberAccessExpression.receiverAndArgs(): List<IrExpression> {
return (arrayListOf(this.dispatchReceiver, this.extensionReceiver) + return (arrayListOf(this.dispatchReceiver, this.extensionReceiver) +
descriptor.valueParameters.mapIndexed { i, _ ->getValueArgument(i)}).filterNotNull() descriptor.valueParameters.mapIndexed { i, _ -> getValueArgument(i) }).filterNotNull()
} }
fun List<IrExpression>.asmTypes(context: JvmBackendContext): List<Type> { fun List<IrExpression>.asmTypes(context: JvmBackendContext): List<Type> {