compiler: cleanup 'public', property access syntax
This commit is contained in:
@@ -27,15 +27,14 @@ import org.jetbrains.kotlin.types.isDynamic
|
|||||||
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
||||||
import java.util.Comparator
|
import java.util.Comparator
|
||||||
|
|
||||||
public object CodegenUtilKt {
|
object CodegenUtilKt {
|
||||||
|
|
||||||
// class Foo : Bar by baz
|
// class Foo : Bar by baz
|
||||||
// descriptor = Foo
|
// descriptor = Foo
|
||||||
// toInterface = Bar
|
// toInterface = Bar
|
||||||
// delegateExpressionType = typeof(baz)
|
// delegateExpressionType = typeof(baz)
|
||||||
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
||||||
@JvmStatic
|
@JvmStatic fun getDelegates(
|
||||||
public fun getDelegates(
|
|
||||||
descriptor: ClassDescriptor,
|
descriptor: ClassDescriptor,
|
||||||
toInterface: ClassDescriptor,
|
toInterface: ClassDescriptor,
|
||||||
delegateExpressionType: KotlinType? = null
|
delegateExpressionType: KotlinType? = null
|
||||||
|
|||||||
+10
-10
@@ -19,22 +19,22 @@ package org.jetbrains.kotlin.backend.common.bridges
|
|||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
|
|
||||||
public interface FunctionHandle {
|
interface FunctionHandle {
|
||||||
public val isDeclaration: Boolean
|
val isDeclaration: Boolean
|
||||||
public val isAbstract: Boolean
|
val isAbstract: Boolean
|
||||||
|
|
||||||
public fun getOverridden(): Iterable<FunctionHandle>
|
fun getOverridden(): Iterable<FunctionHandle>
|
||||||
}
|
}
|
||||||
|
|
||||||
public data class Bridge<Signature>(
|
data class Bridge<Signature>(
|
||||||
public val from: Signature,
|
val from: Signature,
|
||||||
public val to: Signature
|
val to: Signature
|
||||||
) {
|
) {
|
||||||
override fun toString() = "$from -> $to"
|
override fun toString() = "$from -> $to"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun <Function : FunctionHandle, Signature> generateBridges(
|
fun <Function : FunctionHandle, Signature> generateBridges(
|
||||||
function: Function,
|
function: Function,
|
||||||
signature: (Function) -> Signature
|
signature: (Function) -> Signature
|
||||||
): Set<Bridge<Signature>> {
|
): Set<Bridge<Signature>> {
|
||||||
@@ -69,7 +69,7 @@ public fun <Function : FunctionHandle, Signature> generateBridges(
|
|||||||
return bridgesToGenerate.map { Bridge(it, method) }.toSet()
|
return bridgesToGenerate.map { Bridge(it, method) }.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function): MutableSet<Function> {
|
fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function): MutableSet<Function> {
|
||||||
val collector = object : DFS.NodeHandlerWithListResult<Function, Function>() {
|
val collector = object : DFS.NodeHandlerWithListResult<Function, Function>() {
|
||||||
override fun afterChildren(current: Function) {
|
override fun afterChildren(current: Function) {
|
||||||
if (current.isDeclaration) {
|
if (current.isDeclaration) {
|
||||||
@@ -86,7 +86,7 @@ public fun <Function : FunctionHandle> findAllReachableDeclarations(function: Fu
|
|||||||
* Given a concrete function, finds an implementation (a concrete declaration) of this function in the supertypes.
|
* Given a concrete function, finds an implementation (a concrete declaration) of this function in the supertypes.
|
||||||
* The implementation is guaranteed to exist because if it wouldn't, the given function would've been abstract
|
* The implementation is guaranteed to exist because if it wouldn't, the given function would've been abstract
|
||||||
*/
|
*/
|
||||||
public fun <Function : FunctionHandle> findConcreteSuperDeclaration(function: Function): Function {
|
fun <Function : FunctionHandle> findConcreteSuperDeclaration(function: Function): Function {
|
||||||
require(!function.isAbstract, { "Only concrete functions have implementations: $function" })
|
require(!function.isAbstract, { "Only concrete functions have implementations: $function" })
|
||||||
|
|
||||||
if (function.isDeclaration) return function
|
if (function.isDeclaration) return function
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
||||||
|
|
||||||
public fun <Signature> generateBridgesForFunctionDescriptor(
|
fun <Signature> generateBridgesForFunctionDescriptor(
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
signature: (FunctionDescriptor) -> Signature
|
signature: (FunctionDescriptor) -> Signature
|
||||||
): Set<Bridge<Signature>> {
|
): Set<Bridge<Signature>> {
|
||||||
@@ -47,16 +47,16 @@ public fun <Signature> generateBridgesForFunctionDescriptor(
|
|||||||
* can generate a bridge near an implementation (of course, in case it has a super-declaration with a different signature). Ultimately this
|
* can generate a bridge near an implementation (of course, in case it has a super-declaration with a different signature). Ultimately this
|
||||||
* eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated.
|
* eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated.
|
||||||
*/
|
*/
|
||||||
public data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescriptor) : FunctionHandle {
|
data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescriptor) : FunctionHandle {
|
||||||
private val overridden = descriptor.getOverriddenDescriptors().map { DescriptorBasedFunctionHandle(it.getOriginal()) }
|
private val overridden = descriptor.overriddenDescriptors.map { DescriptorBasedFunctionHandle(it.original) }
|
||||||
|
|
||||||
override val isDeclaration: Boolean =
|
override val isDeclaration: Boolean =
|
||||||
descriptor.getKind().isReal() ||
|
descriptor.kind.isReal ||
|
||||||
findTraitImplementation(descriptor) != null
|
findTraitImplementation(descriptor) != null
|
||||||
|
|
||||||
override val isAbstract: Boolean =
|
override val isAbstract: Boolean =
|
||||||
descriptor.getModality() == Modality.ABSTRACT ||
|
descriptor.modality == Modality.ABSTRACT ||
|
||||||
DescriptorUtils.isInterface(descriptor.getContainingDeclaration())
|
DescriptorUtils.isInterface(descriptor.containingDeclaration)
|
||||||
|
|
||||||
override fun getOverridden() = overridden
|
override fun getOverridden() = overridden
|
||||||
}
|
}
|
||||||
@@ -67,14 +67,14 @@ public data class DescriptorBasedFunctionHandle(val descriptor: FunctionDescript
|
|||||||
* trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake
|
* trait implementation should be generated into the class containing the fake override; or null if the given function is not a fake
|
||||||
* override of any trait implementation or such method was already generated into the superclass or is a method from Any.
|
* override of any trait implementation or such method was already generated into the superclass or is a method from Any.
|
||||||
*/
|
*/
|
||||||
public fun findTraitImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
fun findTraitImplementation(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||||
if (descriptor.getKind().isReal()) return null
|
if (descriptor.kind.isReal) return null
|
||||||
if (isOrOverridesSynthesized(descriptor)) return null
|
if (isOrOverridesSynthesized(descriptor)) return null
|
||||||
|
|
||||||
val implementation = findImplementationFromInterface(descriptor) ?: return null
|
val implementation = findImplementationFromInterface(descriptor) ?: return null
|
||||||
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
|
val immediateConcreteSuper = firstSuperMethodFromKotlin(descriptor, implementation) ?: return null
|
||||||
|
|
||||||
if (!DescriptorUtils.isInterface(immediateConcreteSuper.getContainingDeclaration())) {
|
if (!DescriptorUtils.isInterface(immediateConcreteSuper.containingDeclaration)) {
|
||||||
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
|
// If this implementation is already generated into the superclass, we need not generate it again, it'll be inherited
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ public fun findTraitImplementation(descriptor: CallableMemberDescriptor): Callab
|
|||||||
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
|
* Given a fake override, returns an overridden non-abstract function from an interface which is the actual implementation of this function
|
||||||
* that should be called when the given fake override is called.
|
* that should be called when the given fake override is called.
|
||||||
*/
|
*/
|
||||||
public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
fun findImplementationFromInterface(descriptor: CallableMemberDescriptor): CallableMemberDescriptor? {
|
||||||
val overridden = OverrideResolver.getOverriddenDeclarations(descriptor)
|
val overridden = OverrideResolver.getOverriddenDeclarations(descriptor)
|
||||||
val filtered = OverrideResolver.filterOutOverridden(overridden)
|
val filtered = OverrideResolver.filterOutOverridden(overridden)
|
||||||
|
|
||||||
@@ -102,12 +102,12 @@ public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor)
|
|||||||
* returns the first immediate super function of the given fake override which overrides that implementation.
|
* returns the first immediate super function of the given fake override which overrides that implementation.
|
||||||
* The returned function should be called from TImpl-bridges generated for the given fake override.
|
* The returned function should be called from TImpl-bridges generated for the given fake override.
|
||||||
*/
|
*/
|
||||||
public fun firstSuperMethodFromKotlin(
|
fun firstSuperMethodFromKotlin(
|
||||||
descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
implementation: CallableMemberDescriptor
|
implementation: CallableMemberDescriptor
|
||||||
): CallableMemberDescriptor? {
|
): CallableMemberDescriptor? {
|
||||||
return descriptor.getOverriddenDescriptors().firstOrNull { overridden ->
|
return descriptor.overriddenDescriptors.firstOrNull { overridden ->
|
||||||
overridden.getModality() != Modality.ABSTRACT &&
|
overridden.modality != Modality.ABSTRACT &&
|
||||||
(overridden == implementation || OverrideResolver.overrides(overridden, implementation))
|
(overridden == implementation || OverrideResolver.overrides(overridden, implementation))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,24 +18,24 @@ package org.jetbrains.kotlin.backend.common.output
|
|||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
public interface OutputFileCollection {
|
interface OutputFileCollection {
|
||||||
public fun get(relativePath: String): OutputFile?
|
fun get(relativePath: String): OutputFile?
|
||||||
public fun asList(): List<OutputFile>
|
fun asList(): List<OutputFile>
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SimpleOutputFileCollection(private val outputFiles: List<OutputFile>) : OutputFileCollection {
|
class SimpleOutputFileCollection(private val outputFiles: List<OutputFile>) : OutputFileCollection {
|
||||||
override fun get(relativePath: String): OutputFile? = outputFiles.firstOrNull { it.relativePath == relativePath }
|
override fun get(relativePath: String): OutputFile? = outputFiles.firstOrNull { it.relativePath == relativePath }
|
||||||
override fun asList(): List<OutputFile> = outputFiles
|
override fun asList(): List<OutputFile> = outputFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OutputFile {
|
interface OutputFile {
|
||||||
public val relativePath: String
|
val relativePath: String
|
||||||
public val sourceFiles: List<File>
|
val sourceFiles: List<File>
|
||||||
public fun asByteArray(): ByteArray
|
fun asByteArray(): ByteArray
|
||||||
public fun asText(): String
|
fun asText(): String
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SimpleOutputFile(
|
class SimpleOutputFile(
|
||||||
override val sourceFiles: List<File>,
|
override val sourceFiles: List<File>,
|
||||||
override val relativePath: String,
|
override val relativePath: String,
|
||||||
private val content: String
|
private val content: String
|
||||||
@@ -46,7 +46,7 @@ public class SimpleOutputFile(
|
|||||||
override fun toString() = "$relativePath (compiled from $sourceFiles)"
|
override fun toString() = "$relativePath (compiled from $sourceFiles)"
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SimpleOutputBinaryFile(
|
class SimpleOutputBinaryFile(
|
||||||
override val sourceFiles: List<File>,
|
override val sourceFiles: List<File>,
|
||||||
override val relativePath: String,
|
override val relativePath: String,
|
||||||
private val content: ByteArray
|
private val content: ByteArray
|
||||||
|
|||||||
+7
-7
@@ -24,18 +24,18 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
open public class AbstractAccessorForFunctionDescriptor(
|
open class AbstractAccessorForFunctionDescriptor(
|
||||||
containingDeclaration: DeclarationDescriptor,
|
containingDeclaration: DeclarationDescriptor,
|
||||||
name: Name
|
name: Name
|
||||||
) : SimpleFunctionDescriptorImpl(containingDeclaration, null, Annotations.EMPTY,
|
) : SimpleFunctionDescriptorImpl(containingDeclaration, null, Annotations.EMPTY,
|
||||||
name, CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE) {
|
name, CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE) {
|
||||||
|
|
||||||
protected fun copyTypeParameters(descriptor: FunctionDescriptor): List<TypeParameterDescriptor> = descriptor.getTypeParameters().map {
|
protected fun copyTypeParameters(descriptor: FunctionDescriptor): List<TypeParameterDescriptor> = descriptor.typeParameters.map {
|
||||||
val copy = TypeParameterDescriptorImpl.createForFurtherModification(
|
val copy = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||||
this, it.getAnnotations(), it.isReified(),
|
this, it.annotations, it.isReified,
|
||||||
it.getVariance(), it.getName(),
|
it.variance, it.name,
|
||||||
it.getIndex(), SourceElement.NO_SOURCE)
|
it.index, SourceElement.NO_SOURCE)
|
||||||
for (upperBound in it.getUpperBounds()) {
|
for (upperBound in it.upperBounds) {
|
||||||
copy.addUpperBound(upperBound)
|
copy.addUpperBound(upperBound)
|
||||||
}
|
}
|
||||||
copy.setInitialized()
|
copy.setInitialized()
|
||||||
@@ -43,5 +43,5 @@ open public class AbstractAccessorForFunctionDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun copyValueParameters(descriptor: FunctionDescriptor): List<ValueParameterDescriptor> =
|
protected fun copyValueParameters(descriptor: FunctionDescriptor): List<ValueParameterDescriptor> =
|
||||||
descriptor.getValueParameters().map { it.copy(this, it.getName()) }
|
descriptor.valueParameters.map { it.copy(this, it.name) }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
public class AccessorForConstructorDescriptor(
|
class AccessorForConstructorDescriptor(
|
||||||
private val calleeDescriptor: ConstructorDescriptor,
|
private val calleeDescriptor: ConstructorDescriptor,
|
||||||
containingDeclaration: DeclarationDescriptor,
|
containingDeclaration: DeclarationDescriptor,
|
||||||
private val superCallTarget: ClassDescriptor?
|
private val superCallTarget: ClassDescriptor?
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ open class BranchedValue(
|
|||||||
}, IFEQ)
|
}, IFEQ)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue =
|
fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue =
|
||||||
if (operandType.getSort() == Type.OBJECT)
|
if (operandType.sort == Type.OBJECT)
|
||||||
ObjectCompare(opToken, operandType, left, right)
|
ObjectCompare(opToken, operandType, left, right)
|
||||||
else
|
else
|
||||||
NumberCompare(opToken, operandType, left, right)
|
NumberCompare(opToken, operandType, left, right)
|
||||||
|
|||||||
@@ -20,32 +20,32 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public interface Callable {
|
interface Callable {
|
||||||
public val owner: Type
|
val owner: Type
|
||||||
|
|
||||||
public val dispatchReceiverType: Type?
|
val dispatchReceiverType: Type?
|
||||||
|
|
||||||
public val extensionReceiverType: Type?
|
val extensionReceiverType: Type?
|
||||||
|
|
||||||
public val generateCalleeType: Type?
|
val generateCalleeType: Type?
|
||||||
|
|
||||||
public val valueParameterTypes: List<Type>
|
val valueParameterTypes: List<Type>
|
||||||
|
|
||||||
public val parameterTypes: Array<Type>
|
val parameterTypes: Array<Type>
|
||||||
|
|
||||||
public val returnType: Type
|
val returnType: Type
|
||||||
|
|
||||||
public fun genInvokeInstruction(v: InstructionAdapter)
|
fun genInvokeInstruction(v: InstructionAdapter)
|
||||||
|
|
||||||
public fun isStaticCall(): Boolean
|
fun isStaticCall(): Boolean
|
||||||
|
|
||||||
public fun invokeMethodWithArguments(resolvedCall: ResolvedCall<*>, receiver: StackValue, codegen: ExpressionCodegen): StackValue {
|
fun invokeMethodWithArguments(resolvedCall: ResolvedCall<*>, receiver: StackValue, codegen: ExpressionCodegen): StackValue {
|
||||||
return StackValue.functionCall(returnType) {
|
return StackValue.functionCall(returnType) {
|
||||||
codegen.invokeMethodWithArguments(this, resolvedCall, receiver)
|
codegen.invokeMethodWithArguments(this, resolvedCall, receiver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun afterReceiverGeneration(v: InstructionAdapter) {
|
fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
import org.jetbrains.org.objectweb.asm.util.Printer
|
import org.jetbrains.org.objectweb.asm.util.Printer
|
||||||
|
|
||||||
public class CallableMethod(
|
class CallableMethod(
|
||||||
override val owner: Type,
|
override val owner: Type,
|
||||||
private val defaultImplOwner: Type?,
|
private val defaultImplOwner: Type?,
|
||||||
private val defaultMethodDesc: String,
|
private val defaultMethodDesc: String,
|
||||||
@@ -37,48 +37,48 @@ public class CallableMethod(
|
|||||||
override val extensionReceiverType: Type?,
|
override val extensionReceiverType: Type?,
|
||||||
override val generateCalleeType: Type?
|
override val generateCalleeType: Type?
|
||||||
) : Callable {
|
) : Callable {
|
||||||
public fun getValueParameters(): List<JvmMethodParameterSignature> =
|
fun getValueParameters(): List<JvmMethodParameterSignature> =
|
||||||
signature.getValueParameters()
|
signature.valueParameters
|
||||||
|
|
||||||
override val valueParameterTypes: List<Type>
|
override val valueParameterTypes: List<Type>
|
||||||
get() = signature.getValueParameters().filter { it.getKind() == JvmMethodParameterKind.VALUE }.map { it.getAsmType() }
|
get() = signature.valueParameters.filter { it.kind == JvmMethodParameterKind.VALUE }.map { it.asmType }
|
||||||
|
|
||||||
public fun getAsmMethod(): Method =
|
fun getAsmMethod(): Method =
|
||||||
signature.getAsmMethod()
|
signature.asmMethod
|
||||||
|
|
||||||
override val parameterTypes: Array<Type>
|
override val parameterTypes: Array<Type>
|
||||||
get() = getAsmMethod().getArgumentTypes()
|
get() = getAsmMethod().argumentTypes
|
||||||
|
|
||||||
|
|
||||||
public override fun genInvokeInstruction(v: InstructionAdapter) {
|
override fun genInvokeInstruction(v: InstructionAdapter) {
|
||||||
v.visitMethodInsn(invokeOpcode, owner.getInternalName(), getAsmMethod().getName(), getAsmMethod().getDescriptor())
|
v.visitMethodInsn(invokeOpcode, owner.internalName, getAsmMethod().name, getAsmMethod().descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun genInvokeDefaultInstruction(v: InstructionAdapter) {
|
fun genInvokeDefaultInstruction(v: InstructionAdapter) {
|
||||||
if (defaultImplOwner == null) {
|
if (defaultImplOwner == null) {
|
||||||
throw IllegalStateException()
|
throw IllegalStateException()
|
||||||
}
|
}
|
||||||
|
|
||||||
val method = getAsmMethod()
|
val method = getAsmMethod()
|
||||||
|
|
||||||
if ("<init>".equals(method.getName())) {
|
if ("<init>".equals(method.name)) {
|
||||||
v.aconst(null)
|
v.aconst(null)
|
||||||
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", defaultMethodDesc, false)
|
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.internalName, "<init>", defaultMethodDesc, false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.getInternalName(),
|
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.internalName,
|
||||||
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
|
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
|
||||||
|
|
||||||
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
|
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val returnType: Type
|
override val returnType: Type
|
||||||
get() = signature.getReturnType()
|
get() = signature.returnType
|
||||||
|
|
||||||
override fun isStaticCall(): Boolean =
|
override fun isStaticCall(): Boolean =
|
||||||
invokeOpcode == INVOKESTATIC
|
invokeOpcode == INVOKESTATIC
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
"${Printer.OPCODES[invokeOpcode]} ${owner.getInternalName()}.$signature"
|
"${Printer.OPCODES[invokeOpcode]} ${owner.internalName}.$signature"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
|
|||||||
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
|
|
||||||
public abstract class ClassNameCollectionClassBuilderFactory(
|
abstract class ClassNameCollectionClassBuilderFactory(
|
||||||
delegate: ClassBuilderFactory
|
delegate: ClassBuilderFactory
|
||||||
) : DelegatingClassBuilderFactory(delegate) {
|
) : DelegatingClassBuilderFactory(delegate) {
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
|||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
public class CodegenFileClassesProvider : JvmFileClassesProvider {
|
class CodegenFileClassesProvider : JvmFileClassesProvider {
|
||||||
override public fun getFileClassInfo(file: KtFile): JvmFileClassInfo =
|
override fun getFileClassInfo(file: KtFile): JvmFileClassInfo =
|
||||||
JvmFileClassUtil.getFileClassInfoNoResolve(file)
|
JvmFileClassUtil.getFileClassInfoNoResolve(file)
|
||||||
}
|
}
|
||||||
+27
-27
@@ -65,14 +65,14 @@ class CollectionStubMethodGenerator(
|
|||||||
val (child, typeParameters) = createSyntheticSubclass()
|
val (child, typeParameters) = createSyntheticSubclass()
|
||||||
// If the original class has any type parameters, we copied them and now we need to substitute types of the newly created type
|
// If the original class has any type parameters, we copied them and now we need to substitute types of the newly created type
|
||||||
// parameters as arguments for the type parameters of the original class
|
// parameters as arguments for the type parameters of the original class
|
||||||
val parentType = newType(descriptor, typeParameters.map { TypeProjectionImpl(it.getDefaultType()) })
|
val parentType = newType(descriptor, typeParameters.map { TypeProjectionImpl(it.defaultType) })
|
||||||
|
|
||||||
// Now we need to determine the arguments which should be substituted for the MutableCollection super class. To do that,
|
// Now we need to determine the arguments which should be substituted for the MutableCollection super class. To do that,
|
||||||
// we look for type arguments which were substituted in the inheritance of the original class from Collection and use them
|
// we look for type arguments which were substituted in the inheritance of the original class from Collection and use them
|
||||||
// to construct the needed MutableCollection type. Since getAllSupertypes() may return several types which correspond to the
|
// to construct the needed MutableCollection type. Since getAllSupertypes() may return several types which correspond to the
|
||||||
// Collection class descriptor, we find the most specific one (which is guaranteed to exist by front-end)
|
// Collection class descriptor, we find the most specific one (which is guaranteed to exist by front-end)
|
||||||
val readOnlyCollectionType = TypeUtils.getAllSupertypes(parentType).findMostSpecificTypeForClass(readOnlyClass)
|
val readOnlyCollectionType = TypeUtils.getAllSupertypes(parentType).findMostSpecificTypeForClass(readOnlyClass)
|
||||||
val mutableCollectionType = newType(mutableClass, readOnlyCollectionType.getArguments())
|
val mutableCollectionType = newType(mutableClass, readOnlyCollectionType.arguments)
|
||||||
|
|
||||||
child.addSupertype(parentType)
|
child.addSupertype(parentType)
|
||||||
child.addSupertype(mutableCollectionType)
|
child.addSupertype(mutableCollectionType)
|
||||||
@@ -81,10 +81,10 @@ class CollectionStubMethodGenerator(
|
|||||||
// Bind fake overrides and for each fake override originated from the MutableCollection, save its signature to generate a stub
|
// Bind fake overrides and for each fake override originated from the MutableCollection, save its signature to generate a stub
|
||||||
// or save its descriptor to generate all the needed bridges
|
// or save its descriptor to generate all the needed bridges
|
||||||
for (method in findFakeOverridesForMethodsFromMutableCollection(child, mutableClass)) {
|
for (method in findFakeOverridesForMethodsFromMutableCollection(child, mutableClass)) {
|
||||||
if (method.getModality() == Modality.ABSTRACT) {
|
if (method.modality == Modality.ABSTRACT) {
|
||||||
// If the fake override is abstract and it's _declared_ as abstract in the class, skip it because the method is already
|
// If the fake override is abstract and it's _declared_ as abstract in the class, skip it because the method is already
|
||||||
// present in the bytecode (abstract) and we don't want a duplicate signature error
|
// present in the bytecode (abstract) and we don't want a duplicate signature error
|
||||||
if (method.findOverriddenFromDirectSuperClass(descriptor)?.getKind() == DECLARATION) continue
|
if (method.findOverriddenFromDirectSuperClass(descriptor)?.kind == DECLARATION) continue
|
||||||
|
|
||||||
// Otherwise we can safely generate the stub with the substituted signature
|
// Otherwise we can safely generate the stub with the substituted signature
|
||||||
val signature = method.signature()
|
val signature = method.signature()
|
||||||
@@ -160,18 +160,18 @@ class CollectionStubMethodGenerator(
|
|||||||
|
|
||||||
val collectionClasses = with(descriptor.builtIns) {
|
val collectionClasses = with(descriptor.builtIns) {
|
||||||
listOf(
|
listOf(
|
||||||
pair(getCollection(), getMutableCollection()),
|
pair(collection, mutableCollection),
|
||||||
pair(getSet(), getMutableSet()),
|
pair(set, mutableSet),
|
||||||
pair(getList(), getMutableList()),
|
pair(list, mutableList),
|
||||||
pair(getMap(), getMutableMap()),
|
pair(map, mutableMap),
|
||||||
pair(getMapEntry(), getMutableMapEntry()),
|
pair(mapEntry, mutableMapEntry),
|
||||||
pair(getIterable(), getMutableIterable()),
|
pair(iterable, mutableIterable),
|
||||||
pair(getIterator(), getMutableIterator()),
|
pair(iterator, mutableIterator),
|
||||||
pair(getListIterator(), getMutableListIterator())
|
pair(listIterator, mutableListIterator)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val allSuperClasses = TypeUtils.getAllSupertypes(descriptor.getDefaultType()).classes().toHashSet()
|
val allSuperClasses = TypeUtils.getAllSupertypes(descriptor.defaultType).classes().toHashSet()
|
||||||
|
|
||||||
val ourSuperCollectionClasses = collectionClasses.filter { pair ->
|
val ourSuperCollectionClasses = collectionClasses.filter { pair ->
|
||||||
pair.readOnlyClass in allSuperClasses && pair.mutableClass !in allSuperClasses
|
pair.readOnlyClass in allSuperClasses && pair.mutableClass !in allSuperClasses
|
||||||
@@ -180,13 +180,13 @@ class CollectionStubMethodGenerator(
|
|||||||
|
|
||||||
// Filter out built-in classes which are overridden by other built-in classes in the list, to avoid duplicating methods.
|
// Filter out built-in classes which are overridden by other built-in classes in the list, to avoid duplicating methods.
|
||||||
val redundantClasses = ourSuperCollectionClasses.flatMapTo(HashSet<ClassDescriptor>()) { pair ->
|
val redundantClasses = ourSuperCollectionClasses.flatMapTo(HashSet<ClassDescriptor>()) { pair ->
|
||||||
pair.readOnlyClass.getTypeConstructor().getSupertypes().classes()
|
pair.readOnlyClass.typeConstructor.supertypes.classes()
|
||||||
}
|
}
|
||||||
return ourSuperCollectionClasses.filter { klass -> klass.readOnlyClass !in redundantClasses }
|
return ourSuperCollectionClasses.filter { klass -> klass.readOnlyClass !in redundantClasses }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Collection<KotlinType>.classes(): Collection<ClassDescriptor> =
|
private fun Collection<KotlinType>.classes(): Collection<ClassDescriptor> =
|
||||||
this.map { it.getConstructor().getDeclarationDescriptor() as ClassDescriptor }
|
this.map { it.constructor.declarationDescriptor as ClassDescriptor }
|
||||||
|
|
||||||
private fun findFakeOverridesForMethodsFromMutableCollection(
|
private fun findFakeOverridesForMethodsFromMutableCollection(
|
||||||
klass: ClassDescriptor,
|
klass: ClassDescriptor,
|
||||||
@@ -212,7 +212,7 @@ class CollectionStubMethodGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Collection<KotlinType>.findMostSpecificTypeForClass(klass: ClassDescriptor): KotlinType {
|
private fun Collection<KotlinType>.findMostSpecificTypeForClass(klass: ClassDescriptor): KotlinType {
|
||||||
val types = this.filter { it.getConstructor().getDeclarationDescriptor() == klass }
|
val types = this.filter { it.constructor.declarationDescriptor == klass }
|
||||||
if (types.isEmpty()) error("No supertype of $klass in $this")
|
if (types.isEmpty()) error("No supertype of $klass in $this")
|
||||||
if (types.size == 1) return types.first()
|
if (types.size == 1) return types.first()
|
||||||
// Find the first type in the list such that it's a subtype of every other type in that list
|
// Find the first type in the list such that it's a subtype of every other type in that list
|
||||||
@@ -222,11 +222,11 @@ class CollectionStubMethodGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createSyntheticSubclass(): Pair<MutableClassDescriptor, List<TypeParameterDescriptor>> {
|
private fun createSyntheticSubclass(): Pair<MutableClassDescriptor, List<TypeParameterDescriptor>> {
|
||||||
val child = MutableClassDescriptor(descriptor.getContainingDeclaration(), ClassKind.CLASS, false,
|
val child = MutableClassDescriptor(descriptor.containingDeclaration, ClassKind.CLASS, false,
|
||||||
Name.special("<synthetic inheritor of ${descriptor.getName()}>"), descriptor.getSource())
|
Name.special("<synthetic inheritor of ${descriptor.name}>"), descriptor.source)
|
||||||
child.setModality(Modality.FINAL)
|
child.modality = Modality.FINAL
|
||||||
child.setVisibility(Visibilities.PUBLIC)
|
child.visibility = Visibilities.PUBLIC
|
||||||
val typeParameters = descriptor.getTypeConstructor().getParameters()
|
val typeParameters = descriptor.typeConstructor.parameters
|
||||||
val newTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size)
|
val newTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size)
|
||||||
DescriptorSubstitutor.substituteTypeParameters(typeParameters, TypeSubstitution.EMPTY, child, newTypeParameters)
|
DescriptorSubstitutor.substituteTypeParameters(typeParameters, TypeSubstitution.EMPTY, child, newTypeParameters)
|
||||||
child.setTypeParameterDescriptors(typeParameters)
|
child.setTypeParameterDescriptors(typeParameters)
|
||||||
@@ -234,7 +234,7 @@ class CollectionStubMethodGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(classDescriptor: ClassDescriptor): FunctionDescriptor? {
|
private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(classDescriptor: ClassDescriptor): FunctionDescriptor? {
|
||||||
return this.getOverriddenDescriptors().firstOrNull { it.getContainingDeclaration() == classDescriptor }
|
return this.overriddenDescriptors.firstOrNull { it.containingDeclaration == classDescriptor }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newType(classDescriptor: ClassDescriptor, typeArguments: List<TypeProjection>): KotlinType {
|
private fun newType(classDescriptor: ClassDescriptor, typeArguments: List<TypeProjection>): KotlinType {
|
||||||
@@ -246,13 +246,13 @@ class CollectionStubMethodGenerator(
|
|||||||
private fun generateMethodStub(signature: JvmMethodSignature, synthetic: Boolean) {
|
private fun generateMethodStub(signature: JvmMethodSignature, synthetic: Boolean) {
|
||||||
// TODO: investigate if it makes sense to generate abstract stubs in traits
|
// TODO: investigate if it makes sense to generate abstract stubs in traits
|
||||||
var access = ACC_PUBLIC
|
var access = ACC_PUBLIC
|
||||||
if (descriptor.getKind() == ClassKind.INTERFACE) access = access or ACC_ABSTRACT
|
if (descriptor.kind == ClassKind.INTERFACE) access = access or ACC_ABSTRACT
|
||||||
if (synthetic) access = access or ACC_SYNTHETIC
|
if (synthetic) access = access or ACC_SYNTHETIC
|
||||||
|
|
||||||
val asmMethod = signature.getAsmMethod()
|
val asmMethod = signature.asmMethod
|
||||||
val genericSignature = if (synthetic) null else signature.getGenericsSignature()
|
val genericSignature = if (synthetic) null else signature.genericsSignature
|
||||||
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, asmMethod.getName(), asmMethod.getDescriptor(), genericSignature, null)
|
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, asmMethod.name, asmMethod.descriptor, genericSignature, null)
|
||||||
if (descriptor.getKind() != ClassKind.INTERFACE) {
|
if (descriptor.kind != ClassKind.INTERFACE) {
|
||||||
mv.visitCode()
|
mv.visitCode()
|
||||||
AsmUtil.genThrow(InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection")
|
AsmUtil.genThrow(InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection")
|
||||||
FunctionCodegen.endVisit(mv, "built-in stub for $signature", null)
|
FunctionCodegen.endVisit(mv, "built-in stub for $signature", null)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class DefaultCallMask(val size: Int) {
|
|||||||
return masks
|
return masks
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun generateOnStackIfNeeded(callGenerator: CallGenerator): Boolean {
|
fun generateOnStackIfNeeded(callGenerator: CallGenerator): Boolean {
|
||||||
val toInts = toInts()
|
val toInts = toInts()
|
||||||
for (mask in toInts) {
|
for (mask in toInts) {
|
||||||
callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE))
|
callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE))
|
||||||
|
|||||||
+22
-22
@@ -33,7 +33,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|||||||
* Generates Java overloads for functions and constructors that have the default
|
* Generates Java overloads for functions and constructors that have the default
|
||||||
* parameter values substituted.
|
* parameter values substituted.
|
||||||
*/
|
*/
|
||||||
public class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||||
/**
|
/**
|
||||||
* If all of the parameters of the specified constructor declare default values,
|
* If all of the parameters of the specified constructor declare default values,
|
||||||
* generates a no-argument constructor that passes default values for all arguments.
|
* generates a no-argument constructor that passes default values for all arguments.
|
||||||
@@ -118,19 +118,19 @@ public class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
|||||||
val typeMapper = state.typeMapper
|
val typeMapper = state.typeMapper
|
||||||
val isStatic = AsmUtil.isStaticMethod(contextKind, functionDescriptor)
|
val isStatic = AsmUtil.isStaticMethod(contextKind, functionDescriptor)
|
||||||
val flags = AsmUtil.getVisibilityAccessFlag(functionDescriptor) or (if (isStatic) Opcodes.ACC_STATIC else 0)
|
val flags = AsmUtil.getVisibilityAccessFlag(functionDescriptor) or (if (isStatic) Opcodes.ACC_STATIC else 0)
|
||||||
val remainingParameters = getRemainingParameters(functionDescriptor.getOriginal(), substituteCount)
|
val remainingParameters = getRemainingParameters(functionDescriptor.original, substituteCount)
|
||||||
val signature = typeMapper.mapSignature(functionDescriptor, contextKind, remainingParameters)
|
val signature = typeMapper.mapSignature(functionDescriptor, contextKind, remainingParameters)
|
||||||
val mv = classBuilder.newMethod(OtherOrigin(methodElement, functionDescriptor), flags,
|
val mv = classBuilder.newMethod(OtherOrigin(methodElement, functionDescriptor), flags,
|
||||||
signature.getAsmMethod().getName(),
|
signature.asmMethod.name,
|
||||||
signature.getAsmMethod().getDescriptor(),
|
signature.asmMethod.descriptor,
|
||||||
signature.getGenericsSignature(),
|
signature.genericsSignature,
|
||||||
FunctionCodegen.getThrownExceptions(functionDescriptor, typeMapper))
|
FunctionCodegen.getThrownExceptions(functionDescriptor, typeMapper))
|
||||||
|
|
||||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, signature.getReturnType())
|
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, signature.returnType)
|
||||||
|
|
||||||
remainingParameters.withIndex().forEach {
|
remainingParameters.withIndex().forEach {
|
||||||
val annotationCodegen = AnnotationCodegen.forParameter(it.index, mv, typeMapper)
|
val annotationCodegen = AnnotationCodegen.forParameter(it.index, mv, typeMapper)
|
||||||
annotationCodegen.genAnnotations(it.value, signature.getValueParameters()[it.index].getAsmType())
|
annotationCodegen.genAnnotations(it.value, signature.valueParameters[it.index].asmType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) {
|
if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) {
|
||||||
@@ -148,14 +148,14 @@ public class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
|||||||
v.load(thisIndex, methodOwner) // Load this on stack
|
v.load(thisIndex, methodOwner) // Load this on stack
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val delegateOwner = delegateFunctionDescriptor.getContainingDeclaration()
|
val delegateOwner = delegateFunctionDescriptor.containingDeclaration
|
||||||
if (delegateOwner is ClassDescriptor && delegateOwner.isCompanionObject()) {
|
if (delegateOwner is ClassDescriptor && delegateOwner.isCompanionObject) {
|
||||||
val singletonValue = StackValue.singleton(delegateOwner, typeMapper)
|
val singletonValue = StackValue.singleton(delegateOwner, typeMapper)
|
||||||
singletonValue.put(singletonValue.type, v);
|
singletonValue.put(singletonValue.type, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val receiver = functionDescriptor.getExtensionReceiverParameter()
|
val receiver = functionDescriptor.extensionReceiverParameter
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
val receiverType = typeMapper.mapType(receiver)
|
val receiverType = typeMapper.mapType(receiver)
|
||||||
val receiverIndex = frameMap.enter(receiver, receiverType)
|
val receiverIndex = frameMap.enter(receiver, receiverType)
|
||||||
@@ -167,8 +167,8 @@ public class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
|||||||
|
|
||||||
var mask = 0
|
var mask = 0
|
||||||
val masks = arrayListOf<Int>()
|
val masks = arrayListOf<Int>()
|
||||||
for (parameterDescriptor in functionDescriptor.getValueParameters()) {
|
for (parameterDescriptor in functionDescriptor.valueParameters) {
|
||||||
val paramType = typeMapper.mapType(parameterDescriptor.getType())
|
val paramType = typeMapper.mapType(parameterDescriptor.type)
|
||||||
if (parameterDescriptor in remainingParameters) {
|
if (parameterDescriptor in remainingParameters) {
|
||||||
val index = frameMap.getIndex(parameterDescriptor)
|
val index = frameMap.getIndex(parameterDescriptor)
|
||||||
StackValue.local(index, paramType).put(paramType, v)
|
StackValue.local(index, paramType).put(paramType, v)
|
||||||
@@ -195,39 +195,39 @@ public class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
|||||||
|
|
||||||
val defaultMethod = typeMapper.mapDefaultMethod(delegateFunctionDescriptor, contextKind)
|
val defaultMethod = typeMapper.mapDefaultMethod(delegateFunctionDescriptor, contextKind)
|
||||||
if (functionDescriptor is ConstructorDescriptor) {
|
if (functionDescriptor is ConstructorDescriptor) {
|
||||||
v.invokespecial(methodOwner.getInternalName(), defaultMethod.getName(), defaultMethod.getDescriptor(), false)
|
v.invokespecial(methodOwner.internalName, defaultMethod.name, defaultMethod.descriptor, false)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.invokestatic(methodOwner.getInternalName(), defaultMethod.getName(), defaultMethod.getDescriptor(), false)
|
v.invokestatic(methodOwner.internalName, defaultMethod.name, defaultMethod.descriptor, false)
|
||||||
}
|
}
|
||||||
v.areturn(signature.getReturnType())
|
v.areturn(signature.returnType)
|
||||||
FunctionCodegen.endVisit(mv, null, methodElement)
|
FunctionCodegen.endVisit(mv, null, methodElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRemainingParameters(functionDescriptor: FunctionDescriptor,
|
private fun getRemainingParameters(functionDescriptor: FunctionDescriptor,
|
||||||
substituteCount: Int): List<ValueParameterDescriptor> {
|
substituteCount: Int): List<ValueParameterDescriptor> {
|
||||||
var remainingCount = functionDescriptor.countDefaultParameters() - substituteCount
|
var remainingCount = functionDescriptor.countDefaultParameters() - substituteCount
|
||||||
return functionDescriptor.getValueParameters().filter { !it.declaresDefaultValue() || --remainingCount >= 0 }
|
return functionDescriptor.valueParameters.filter { !it.declaresDefaultValue() || --remainingCount >= 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isEmptyConstructorNeeded(constructorDescriptor: ConstructorDescriptor, classOrObject: KtClassOrObject): Boolean {
|
private fun isEmptyConstructorNeeded(constructorDescriptor: ConstructorDescriptor, classOrObject: KtClassOrObject): Boolean {
|
||||||
val classDescriptor = constructorDescriptor.getContainingDeclaration()
|
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||||
if (classDescriptor.getKind() != ClassKind.CLASS) return false
|
if (classDescriptor.kind != ClassKind.CLASS) return false
|
||||||
|
|
||||||
if (classOrObject.isLocal()) return false
|
if (classOrObject.isLocal()) return false
|
||||||
|
|
||||||
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
|
if (CodegenBinding.canHaveOuter(state.bindingContext, classDescriptor)) return false
|
||||||
|
|
||||||
if (Visibilities.isPrivate(classDescriptor.getVisibility()) || Visibilities.isPrivate(constructorDescriptor.getVisibility()))
|
if (Visibilities.isPrivate(classDescriptor.visibility) || Visibilities.isPrivate(constructorDescriptor.visibility))
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if (constructorDescriptor.getValueParameters().isEmpty()) return false
|
if (constructorDescriptor.valueParameters.isEmpty()) return false
|
||||||
if (classOrObject is KtClass && hasSecondaryConstructorsWithNoParameters(classOrObject)) return false
|
if (classOrObject is KtClass && hasSecondaryConstructorsWithNoParameters(classOrObject)) return false
|
||||||
|
|
||||||
return constructorDescriptor.getValueParameters().all { it.declaresDefaultValue() }
|
return constructorDescriptor.valueParameters.all { it.declaresDefaultValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasSecondaryConstructorsWithNoParameters(klass: KtClass) =
|
private fun hasSecondaryConstructorsWithNoParameters(klass: KtClass) =
|
||||||
klass.getSecondaryConstructors().any { it.getValueParameters().isEmpty() }
|
klass.getSecondaryConstructors().any { it.valueParameters.isEmpty() }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,18 +25,18 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
|
|||||||
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
|
|
||||||
public abstract class DelegatingClassBuilderFactory(
|
abstract class DelegatingClassBuilderFactory(
|
||||||
protected val delegate: ClassBuilderFactory
|
protected val delegate: ClassBuilderFactory
|
||||||
|
|
||||||
) : ClassBuilderFactory by delegate {
|
) : ClassBuilderFactory by delegate {
|
||||||
|
|
||||||
abstract override fun newClassBuilder(origin: JvmDeclarationOrigin): DelegatingClassBuilder
|
abstract override fun newClassBuilder(origin: JvmDeclarationOrigin): DelegatingClassBuilder
|
||||||
|
|
||||||
public override fun asBytes(builder: ClassBuilder?): ByteArray? {
|
override fun asBytes(builder: ClassBuilder?): ByteArray? {
|
||||||
return delegate.asBytes((builder as DelegatingClassBuilder).getDelegate())
|
return delegate.asBytes((builder as DelegatingClassBuilder).getDelegate())
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun asText(builder: ClassBuilder?): String? {
|
override fun asText(builder: ClassBuilder?): String? {
|
||||||
return delegate.asText((builder as DelegatingClassBuilder).getDelegate())
|
return delegate.asText((builder as DelegatingClassBuilder).getDelegate())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
|||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
|
||||||
public class InlineCycleReporter(val diagnostics: DiagnosticSink) {
|
class InlineCycleReporter(val diagnostics: DiagnosticSink) {
|
||||||
|
|
||||||
val processingFunctions = linkedMapOf<PsiElement, CallableDescriptor>()
|
val processingFunctions = linkedMapOf<PsiElement, CallableDescriptor>()
|
||||||
|
|
||||||
public fun enterIntoInlining(call: ResolvedCall<*>?): Boolean {
|
fun enterIntoInlining(call: ResolvedCall<*>?): Boolean {
|
||||||
//null call for default method inlining
|
//null call for default method inlining
|
||||||
if (call != null) {
|
if (call != null) {
|
||||||
val callElement = call.getCall().getCallElement()
|
val callElement = call.call.callElement
|
||||||
if (processingFunctions.contains(callElement)) {
|
if (processingFunctions.contains(callElement)) {
|
||||||
val cycle = processingFunctions.asSequence().dropWhile { it.key != callElement }
|
val cycle = processingFunctions.asSequence().dropWhile { it.key != callElement }
|
||||||
cycle.forEach {
|
cycle.forEach {
|
||||||
@@ -38,14 +38,14 @@ public class InlineCycleReporter(val diagnostics: DiagnosticSink) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
processingFunctions.put(callElement, call.getResultingDescriptor().getOriginal())
|
processingFunctions.put(callElement, call.resultingDescriptor.original)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun exitFromInliningOf(call: ResolvedCall<*>?) {
|
fun exitFromInliningOf(call: ResolvedCall<*>?) {
|
||||||
if (call != null) {
|
if (call != null) {
|
||||||
val callElement = call.getCall().getCallElement()
|
val callElement = call.call.callElement
|
||||||
processingFunctions.remove(callElement)
|
processingFunctions.remove(callElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
|
|||||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class InterfaceImplBodyCodegen(
|
class InterfaceImplBodyCodegen(
|
||||||
aClass: KtClassOrObject,
|
aClass: KtClassOrObject,
|
||||||
context: ClassContext,
|
context: ClassContext,
|
||||||
v: ClassBuilder,
|
v: ClassBuilder,
|
||||||
@@ -54,7 +54,7 @@ public class InterfaceImplBodyCodegen(
|
|||||||
typeMapper.mapDefaultImpls(descriptor).internalName,
|
typeMapper.mapDefaultImpls(descriptor).internalName,
|
||||||
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
||||||
)
|
)
|
||||||
v.visitSource(myClass.getContainingFile().getName(), null)
|
v.visitSource(myClass.containingFile.name, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun classForInnerClassRecord(): ClassDescriptor? {
|
override fun classForInnerClassRecord(): ClassDescriptor? {
|
||||||
@@ -69,12 +69,12 @@ public class InterfaceImplBodyCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSyntheticParts() {
|
override fun generateSyntheticParts() {
|
||||||
for (memberDescriptor in descriptor.getDefaultType().getMemberScope().getContributedDescriptors()) {
|
for (memberDescriptor in descriptor.defaultType.memberScope.getContributedDescriptors()) {
|
||||||
if (memberDescriptor !is CallableMemberDescriptor) continue
|
if (memberDescriptor !is CallableMemberDescriptor) continue
|
||||||
|
|
||||||
if (memberDescriptor.getKind().isReal()) continue
|
if (memberDescriptor.kind.isReal) continue
|
||||||
if (memberDescriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) continue
|
if (memberDescriptor.visibility == Visibilities.INVISIBLE_FAKE) continue
|
||||||
if (memberDescriptor.getModality() == Modality.ABSTRACT) continue
|
if (memberDescriptor.modality == Modality.ABSTRACT) continue
|
||||||
|
|
||||||
val implementation = findImplementationFromInterface(memberDescriptor) ?: continue
|
val implementation = findImplementationFromInterface(memberDescriptor) ?: continue
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ public class InterfaceImplBodyCodegen(
|
|||||||
if (implementation is JavaMethodDescriptor) continue
|
if (implementation is JavaMethodDescriptor) continue
|
||||||
|
|
||||||
// We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body
|
// We create a copy of the function with kind = DECLARATION so that FunctionCodegen will generate its body
|
||||||
val copy = memberDescriptor.copy(memberDescriptor.getContainingDeclaration(), Modality.OPEN, memberDescriptor.getVisibility(),
|
val copy = memberDescriptor.copy(memberDescriptor.containingDeclaration, Modality.OPEN, memberDescriptor.visibility,
|
||||||
CallableMemberDescriptor.Kind.DECLARATION, true)
|
CallableMemberDescriptor.Kind.DECLARATION, true)
|
||||||
|
|
||||||
if (memberDescriptor is FunctionDescriptor) {
|
if (memberDescriptor is FunctionDescriptor) {
|
||||||
@@ -90,13 +90,13 @@ public class InterfaceImplBodyCodegen(
|
|||||||
}
|
}
|
||||||
else if (memberDescriptor is PropertyDescriptor) {
|
else if (memberDescriptor is PropertyDescriptor) {
|
||||||
implementation as PropertyDescriptor
|
implementation as PropertyDescriptor
|
||||||
val getter = (copy as PropertyDescriptor).getGetter()
|
val getter = (copy as PropertyDescriptor).getter
|
||||||
val implGetter = implementation.getGetter()
|
val implGetter = implementation.getter
|
||||||
if (getter != null && implGetter != null) {
|
if (getter != null && implGetter != null) {
|
||||||
generateDelegationToSuperTraitImpl(getter, implGetter)
|
generateDelegationToSuperTraitImpl(getter, implGetter)
|
||||||
}
|
}
|
||||||
val setter = copy.getSetter()
|
val setter = copy.setter
|
||||||
val implSetter = implementation.getSetter()
|
val implSetter = implementation.setter
|
||||||
if (setter != null && implSetter != null) {
|
if (setter != null && implSetter != null) {
|
||||||
generateDelegationToSuperTraitImpl(setter, implSetter)
|
generateDelegationToSuperTraitImpl(setter, implSetter)
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ public class InterfaceImplBodyCodegen(
|
|||||||
val iv = codegen.v
|
val iv = codegen.v
|
||||||
|
|
||||||
val method = typeMapper.mapToCallableMethod(delegateTo, true)
|
val method = typeMapper.mapToCallableMethod(delegateTo, true)
|
||||||
val myParameters = signature.getValueParameters()
|
val myParameters = signature.valueParameters
|
||||||
val calleeParameters = method.getValueParameters()
|
val calleeParameters = method.getValueParameters()
|
||||||
|
|
||||||
if (myParameters.size != calleeParameters.size) {
|
if (myParameters.size != calleeParameters.size) {
|
||||||
@@ -135,14 +135,14 @@ public class InterfaceImplBodyCodegen(
|
|||||||
var k = 0
|
var k = 0
|
||||||
val it = calleeParameters.iterator()
|
val it = calleeParameters.iterator()
|
||||||
for (parameter in myParameters) {
|
for (parameter in myParameters) {
|
||||||
val type = parameter.getAsmType()
|
val type = parameter.asmType
|
||||||
StackValue.local(k, type).put(it.next().getAsmType(), iv)
|
StackValue.local(k, type).put(it.next().asmType, iv)
|
||||||
k += type.getSize()
|
k += type.size
|
||||||
}
|
}
|
||||||
|
|
||||||
method.genInvokeInstruction(iv)
|
method.genInvokeInstruction(iv)
|
||||||
StackValue.coerce(method.returnType, signature.getReturnType(), iv)
|
StackValue.coerce(method.returnType, signature.returnType, iv)
|
||||||
iv.areturn(signature.getReturnType())
|
iv.areturn(signature.returnType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,15 +79,14 @@ class JvmStaticGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
|
||||||
public fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
|
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.correspondingProperty else descriptor
|
||||||
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor
|
|
||||||
val copies = CodegenUtil.copyFunctions(
|
val copies = CodegenUtil.copyFunctions(
|
||||||
memberDescriptor,
|
memberDescriptor,
|
||||||
memberDescriptor,
|
memberDescriptor,
|
||||||
descriptor.getContainingDeclaration().getContainingDeclaration(),
|
descriptor.containingDeclaration.containingDeclaration,
|
||||||
descriptor.getModality(),
|
descriptor.modality,
|
||||||
descriptor.getVisibility(),
|
descriptor.visibility,
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class MultifileClassCodegen(
|
class MultifileClassCodegen(
|
||||||
private val state: GenerationState,
|
private val state: GenerationState,
|
||||||
public val files: Collection<KtFile>,
|
val files: Collection<KtFile>,
|
||||||
private val facadeFqName: FqName
|
private val facadeFqName: FqName
|
||||||
) {
|
) {
|
||||||
private val facadeClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(facadeFqName)
|
private val facadeClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(facadeFqName)
|
||||||
@@ -74,7 +74,7 @@ public class MultifileClassCodegen(
|
|||||||
private fun getDeserializedCallables(compiledPackageFragment: PackageFragmentDescriptor) =
|
private fun getDeserializedCallables(compiledPackageFragment: PackageFragmentDescriptor) =
|
||||||
compiledPackageFragment.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CALLABLES, MemberScope.ALL_NAME_FILTER).filterIsInstance<DeserializedCallableMemberDescriptor>()
|
compiledPackageFragment.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CALLABLES, MemberScope.ALL_NAME_FILTER).filterIsInstance<DeserializedCallableMemberDescriptor>()
|
||||||
|
|
||||||
public val packageParts = PackageParts(facadeFqName.parent().asString())
|
val packageParts = PackageParts(facadeFqName.parent().asString())
|
||||||
|
|
||||||
private val classBuilder = ClassBuilderOnDemand {
|
private val classBuilder = ClassBuilderOnDemand {
|
||||||
val originFile = files.firstOrNull()
|
val originFile = files.firstOrNull()
|
||||||
@@ -103,7 +103,7 @@ public class MultifileClassCodegen(
|
|||||||
classBuilder
|
classBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun generate(errorHandler: CompilationErrorHandler) {
|
fun generate(errorHandler: CompilationErrorHandler) {
|
||||||
val generateCallableMemberTasks = HashMap<CallableMemberDescriptor, () -> Unit>()
|
val generateCallableMemberTasks = HashMap<CallableMemberDescriptor, () -> Unit>()
|
||||||
val partFqNames = arrayListOf<FqName>()
|
val partFqNames = arrayListOf<FqName>()
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ public class MultifileClassCodegen(
|
|||||||
writeKotlinMultifileFacadeAnnotationIfNeeded(partFqNames)
|
writeKotlinMultifileFacadeAnnotationIfNeeded(partFqNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun generateClassOrObject(classOrObject: KtClassOrObject, packagePartContext: FieldOwnerContext<PackageFragmentDescriptor>) {
|
fun generateClassOrObject(classOrObject: KtClassOrObject, packagePartContext: FieldOwnerContext<PackageFragmentDescriptor>) {
|
||||||
MemberCodegen.genClassOrObject(packagePartContext, classOrObject, state, null)
|
MemberCodegen.genClassOrObject(packagePartContext, classOrObject, state, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +292,7 @@ public class MultifileClassCodegen(
|
|||||||
override fun generateKotlinAnnotation() = throw UnsupportedOperationException()
|
override fun generateKotlinAnnotation() = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun done() {
|
fun done() {
|
||||||
classBuilder.done()
|
classBuilder.done()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class MultifileClassPartCodegen(
|
class MultifileClassPartCodegen(
|
||||||
v: ClassBuilder,
|
v: ClassBuilder,
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
private val filePartType: Type,
|
private val filePartType: Type,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
|
|
||||||
public class PropertyReferenceCodegen(
|
class PropertyReferenceCodegen(
|
||||||
state: GenerationState,
|
state: GenerationState,
|
||||||
parentCodegen: MemberCodegen<*>,
|
parentCodegen: MemberCodegen<*>,
|
||||||
context: ClassContext,
|
context: ClassContext,
|
||||||
@@ -68,22 +68,22 @@ public class PropertyReferenceCodegen(
|
|||||||
element,
|
element,
|
||||||
V1_6,
|
V1_6,
|
||||||
ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor),
|
ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor),
|
||||||
asmType.getInternalName(),
|
asmType.internalName,
|
||||||
null,
|
null,
|
||||||
superAsmType.getInternalName(),
|
superAsmType.internalName,
|
||||||
emptyArray()
|
emptyArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
v.visitSource(element.getContainingFile().getName(), null)
|
v.visitSource(element.containingFile.name, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
|
// TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
|
||||||
override fun generateBody() {
|
override fun generateBody() {
|
||||||
generateConstInstance(asmType, wrapperMethod.getReturnType())
|
generateConstInstance(asmType, wrapperMethod.returnType)
|
||||||
|
|
||||||
generateMethod("property reference init", 0, method("<init>", Type.VOID_TYPE)) {
|
generateMethod("property reference init", 0, method("<init>", Type.VOID_TYPE)) {
|
||||||
load(0, OBJECT_TYPE)
|
load(0, OBJECT_TYPE)
|
||||||
invokespecial(superAsmType.getInternalName(), "<init>", "()V", false)
|
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
||||||
@@ -91,7 +91,7 @@ public class PropertyReferenceCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
generateMethod("property reference getName", ACC_PUBLIC, method("getName", JAVA_STRING_TYPE)) {
|
generateMethod("property reference getName", ACC_PUBLIC, method("getName", JAVA_STRING_TYPE)) {
|
||||||
aconst(target.getName().asString())
|
aconst(target.name.asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) {
|
generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) {
|
||||||
@@ -108,11 +108,11 @@ public class PropertyReferenceCodegen(
|
|||||||
// return type and value parameter types. However, it's created only to be able to use
|
// return type and value parameter types. However, it's created only to be able to use
|
||||||
// ExpressionCodegen#intermediateValueForProperty, which is poorly coupled with everything else.
|
// ExpressionCodegen#intermediateValueForProperty, which is poorly coupled with everything else.
|
||||||
val fakeDescriptor = SimpleFunctionDescriptorImpl.create(
|
val fakeDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||||
classDescriptor, Annotations.EMPTY, Name.identifier(method.getName()), CallableMemberDescriptor.Kind.DECLARATION,
|
classDescriptor, Annotations.EMPTY, Name.identifier(method.name), CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE
|
||||||
)
|
)
|
||||||
fakeDescriptor.initialize(null, classDescriptor.getThisAsReceiverParameter(), emptyList(), emptyList(),
|
fakeDescriptor.initialize(null, classDescriptor.thisAsReceiverParameter, emptyList(), emptyList(),
|
||||||
classDescriptor.builtIns.getAnyType(), Modality.OPEN, Visibilities.PUBLIC)
|
classDescriptor.builtIns.anyType, Modality.OPEN, Visibilities.PUBLIC)
|
||||||
|
|
||||||
val fakeCodegen = ExpressionCodegen(
|
val fakeCodegen = ExpressionCodegen(
|
||||||
this, FrameMap(), OBJECT_TYPE, context.intoFunction(fakeDescriptor), state, this@PropertyReferenceCodegen
|
this, FrameMap(), OBJECT_TYPE, context.intoFunction(fakeDescriptor), state, this@PropertyReferenceCodegen
|
||||||
@@ -147,13 +147,13 @@ public class PropertyReferenceCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateMethod(debugString: String, access: Int, method: Method, generate: InstructionAdapter.() -> Unit) {
|
private fun generateMethod(debugString: String, access: Int, method: Method, generate: InstructionAdapter.() -> Unit) {
|
||||||
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, method.getName(), method.getDescriptor(), null, null)
|
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, method.name, method.descriptor, null, null)
|
||||||
|
|
||||||
if (state.classBuilderMode == ClassBuilderMode.FULL) {
|
if (state.classBuilderMode == ClassBuilderMode.FULL) {
|
||||||
val iv = InstructionAdapter(mv)
|
val iv = InstructionAdapter(mv)
|
||||||
iv.visitCode()
|
iv.visitCode()
|
||||||
iv.generate()
|
iv.generate()
|
||||||
iv.areturn(method.getReturnType())
|
iv.areturn(method.returnType)
|
||||||
FunctionCodegen.endVisit(mv, debugString, element)
|
FunctionCodegen.endVisit(mv, debugString, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,9 +162,9 @@ public class PropertyReferenceCodegen(
|
|||||||
writeKotlinSyntheticClassAnnotation(v, state)
|
writeKotlinSyntheticClassAnnotation(v, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun putInstanceOnStack(): StackValue =
|
fun putInstanceOnStack(): StackValue =
|
||||||
StackValue.operation(wrapperMethod.getReturnType()) { iv ->
|
StackValue.operation(wrapperMethod.returnType) { iv ->
|
||||||
iv.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, wrapperMethod.getReturnType().getDescriptor())
|
iv.getstatic(asmType.internalName, JvmAbi.INSTANCE_FIELD, wrapperMethod.returnType.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.RawSignature
|
|||||||
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
import org.jetbrains.org.objectweb.asm.FieldVisitor
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
|
|
||||||
public abstract class SignatureCollectingClassBuilderFactory(
|
abstract class SignatureCollectingClassBuilderFactory(
|
||||||
delegate: ClassBuilderFactory
|
delegate: ClassBuilderFactory
|
||||||
) : DelegatingClassBuilderFactory(delegate) {
|
) : DelegatingClassBuilderFactory(delegate) {
|
||||||
|
|
||||||
|
|||||||
@@ -22,19 +22,19 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
|
||||||
data public class SourceInfo(val source: String, val pathOrCleanFQN: String, val linesInFile: Int) {
|
data class SourceInfo(val source: String, val pathOrCleanFQN: String, val linesInFile: Int) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun createInfo(element: KtElement?, internalClassName: String): SourceInfo {
|
fun createInfo(element: KtElement?, internalClassName: String): SourceInfo {
|
||||||
assert(element != null) { "Couldn't create source mapper for null element " + internalClassName }
|
assert(element != null) { "Couldn't create source mapper for null element " + internalClassName }
|
||||||
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.getContainingFile(), true)
|
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.containingFile, true)
|
||||||
assert(lineNumbers != null) { "Couldn't extract line count in " + element.getContainingFile() }
|
assert(lineNumbers != null) { "Couldn't extract line count in " + element.containingFile }
|
||||||
|
|
||||||
//TODO hack condition for package parts cleaning
|
//TODO hack condition for package parts cleaning
|
||||||
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
||||||
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
||||||
|
|
||||||
return SourceInfo(element.getContainingKtFile().getName(), cleanedClassFqName, lineNumbers!!)
|
return SourceInfo(element.getContainingKtFile().name, cleanedClassFqName, lineNumbers!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class CoercionValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class StackValueWithLeaveTask(
|
class StackValueWithLeaveTask(
|
||||||
val stackValue: StackValue,
|
val stackValue: StackValue,
|
||||||
val leaveTasks: (StackValue) -> Unit
|
val leaveTasks: (StackValue) -> Unit
|
||||||
) : StackValue(stackValue.type) {
|
) : StackValue(stackValue.type) {
|
||||||
|
|||||||
+5
-5
@@ -22,15 +22,15 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
public interface WrappedAnnotated : Annotated {
|
interface WrappedAnnotated : Annotated {
|
||||||
public val originalAnnotated: Annotated
|
val originalAnnotated: Annotated
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AnnotatedWithFakeAnnotations(override val originalAnnotated: Annotated, private val actual: Annotations) : WrappedAnnotated {
|
class AnnotatedWithFakeAnnotations(override val originalAnnotated: Annotated, private val actual: Annotations) : WrappedAnnotated {
|
||||||
override fun getAnnotations() = actual
|
override fun getAnnotations() = actual
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AnnotatedWithOnlyTargetedAnnotations(private val original: Annotated) : Annotated {
|
class AnnotatedWithOnlyTargetedAnnotations(private val original: Annotated) : Annotated {
|
||||||
private val annotations: Annotations = UseSiteTargetedAnnotations(original.annotations)
|
private val annotations: Annotations = UseSiteTargetedAnnotations(original.annotations)
|
||||||
|
|
||||||
override fun getAnnotations() = annotations
|
override fun getAnnotations() = annotations
|
||||||
@@ -52,4 +52,4 @@ public class AnnotatedWithOnlyTargetedAnnotations(private val original: Annotate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)
|
class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)
|
||||||
@@ -43,8 +43,7 @@ class BridgeForBuiltinSpecial<Signature>(
|
|||||||
)
|
)
|
||||||
|
|
||||||
object BuiltinSpecialBridgesUtil {
|
object BuiltinSpecialBridgesUtil {
|
||||||
@JvmStatic
|
@JvmStatic fun <Signature> generateBridgesForBuiltinSpecial(
|
||||||
public fun <Signature> generateBridgesForBuiltinSpecial(
|
|
||||||
function: FunctionDescriptor,
|
function: FunctionDescriptor,
|
||||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||||
): Set<BridgeForBuiltinSpecial<Signature>> {
|
): Set<BridgeForBuiltinSpecial<Signature>> {
|
||||||
@@ -93,8 +92,7 @@ object BuiltinSpecialBridgesUtil {
|
|||||||
return bridges
|
return bridges
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun <Signature> FunctionDescriptor.shouldHaveTypeSafeBarrier(
|
||||||
public fun <Signature> FunctionDescriptor.shouldHaveTypeSafeBarrier(
|
|
||||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(this) == null) return false
|
if (BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(this) == null) return false
|
||||||
@@ -143,7 +141,7 @@ private fun <Signature> needGenerateSpecialBridge(
|
|||||||
&& signatureByDescriptor(it) == overriddenBuiltinSignature }
|
&& signatureByDescriptor(it) == overriddenBuiltinSignature }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
|
fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
|
||||||
element: KtElement,
|
element: KtElement,
|
||||||
bindingContext: BindingContext
|
bindingContext: BindingContext
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ private fun generateNullCheckForNonSafeAs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String?
|
fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String?
|
||||||
= valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
= valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
||||||
|
|
||||||
fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObjectDeclaration, outerContext: FieldOwnerContext<*>, state: GenerationState) {
|
fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObjectDeclaration, outerContext: FieldOwnerContext<*>, state: GenerationState) {
|
||||||
|
|||||||
@@ -18,16 +18,14 @@ package org.jetbrains.kotlin.codegen.context
|
|||||||
|
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
public object CodegenContextUtil {
|
object CodegenContextUtil {
|
||||||
@JvmStatic
|
@JvmStatic fun getImplementationOwnerClassType(owner: CodegenContext<*>): Type? =
|
||||||
public fun getImplementationOwnerClassType(owner: CodegenContext<*>): Type? =
|
|
||||||
when (owner) {
|
when (owner) {
|
||||||
is MultifileClassFacadeContext -> owner.filePartType
|
is MultifileClassFacadeContext -> owner.filePartType
|
||||||
is DelegatingToPartContext -> owner.implementationOwnerClassType
|
is DelegatingToPartContext -> owner.implementationOwnerClassType
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun isImplClassOwner(owner: CodegenContext<*>): Boolean =
|
||||||
public fun isImplClassOwner(owner: CodegenContext<*>): Boolean =
|
|
||||||
owner !is MultifileClassFacadeContext
|
owner !is MultifileClassFacadeContext
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -21,11 +21,11 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
|||||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
public interface ClassBuilderInterceptorExtension {
|
interface ClassBuilderInterceptorExtension {
|
||||||
companion object : ProjectExtensionDescriptor<ClassBuilderInterceptorExtension>(
|
companion object : ProjectExtensionDescriptor<ClassBuilderInterceptorExtension>(
|
||||||
"org.jetbrains.kotlin.classBuilderFactoryInterceptorExtension", ClassBuilderInterceptorExtension::class.java)
|
"org.jetbrains.kotlin.classBuilderFactoryInterceptorExtension", ClassBuilderInterceptorExtension::class.java)
|
||||||
|
|
||||||
public fun interceptClassBuilderFactory(
|
fun interceptClassBuilderFactory(
|
||||||
interceptedFactory: ClassBuilderFactory,
|
interceptedFactory: ClassBuilderFactory,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
diagnostics: DiagnosticSink
|
diagnostics: DiagnosticSink
|
||||||
|
|||||||
+7
-7
@@ -26,28 +26,28 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
|
|||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
|
||||||
public interface ExpressionCodegenExtension {
|
interface ExpressionCodegenExtension {
|
||||||
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
|
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
|
||||||
"org.jetbrains.kotlin.expressionCodegenExtension", ExpressionCodegenExtension::class.java)
|
"org.jetbrains.kotlin.expressionCodegenExtension", ExpressionCodegenExtension::class.java)
|
||||||
|
|
||||||
public class Context(
|
class Context(
|
||||||
public val typeMapper: JetTypeMapper,
|
val typeMapper: JetTypeMapper,
|
||||||
public val v: InstructionAdapter
|
val v: InstructionAdapter
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for generating custom byte code for the property value obtain. This function has lazy semantics.
|
* Used for generating custom byte code for the property value obtain. This function has lazy semantics.
|
||||||
* Returns new stack value.
|
* Returns new stack value.
|
||||||
*/
|
*/
|
||||||
public fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for generating custom byte code for the function call. This function has lazy semantics.
|
* Used for generating custom byte code for the function call. This function has lazy semantics.
|
||||||
* Returns new stack value.
|
* Returns new stack value.
|
||||||
*/
|
*/
|
||||||
public fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
|
||||||
|
|
||||||
public fun generateClassSyntheticParts(
|
fun generateClassSyntheticParts(
|
||||||
classBuilder: ClassBuilder,
|
classBuilder: ClassBuilder,
|
||||||
state: GenerationState,
|
state: GenerationState,
|
||||||
classOrObject: KtClassOrObject,
|
classOrObject: KtClassOrObject,
|
||||||
|
|||||||
+15
-15
@@ -25,26 +25,26 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
|||||||
import java.util.Comparator
|
import java.util.Comparator
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
|
|
||||||
public abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
||||||
|
|
||||||
public val tryBlocksMetaInfo: IntervalMetaInfo<TryCatchBlockNodeInfo> = IntervalMetaInfo()
|
val tryBlocksMetaInfo: IntervalMetaInfo<TryCatchBlockNodeInfo> = IntervalMetaInfo()
|
||||||
|
|
||||||
public val localVarsMetaInfo: IntervalMetaInfo<LocalVarNodeWrapper> = IntervalMetaInfo()
|
val localVarsMetaInfo: IntervalMetaInfo<LocalVarNodeWrapper> = IntervalMetaInfo()
|
||||||
|
|
||||||
public var nextFreeLocalIndex: Int = parameterSize
|
var nextFreeLocalIndex: Int = parameterSize
|
||||||
private set
|
private set
|
||||||
|
|
||||||
public fun getStartNodes(label: LabelNode): List<TryCatchBlockNodeInfo> {
|
fun getStartNodes(label: LabelNode): List<TryCatchBlockNodeInfo> {
|
||||||
return tryBlocksMetaInfo.intervalStarts.get(label)
|
return tryBlocksMetaInfo.intervalStarts.get(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getEndNodes(label: LabelNode): List<TryCatchBlockNodeInfo> {
|
fun getEndNodes(label: LabelNode): List<TryCatchBlockNodeInfo> {
|
||||||
return tryBlocksMetaInfo.intervalEnds.get(label)
|
return tryBlocksMetaInfo.intervalEnds.get(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open fun processInstruction(curInstr: AbstractInsnNode, directOrder: Boolean) {
|
open fun processInstruction(curInstr: AbstractInsnNode, directOrder: Boolean) {
|
||||||
if (curInstr is VarInsnNode || curInstr is IincInsnNode) {
|
if (curInstr is VarInsnNode || curInstr is IincInsnNode) {
|
||||||
val argSize = InlineCodegenUtil.getLoadStoreArgSize(curInstr.getOpcode())
|
val argSize = InlineCodegenUtil.getLoadStoreArgSize(curInstr.opcode)
|
||||||
val varIndex = if (curInstr is VarInsnNode) curInstr.`var` else (curInstr as IincInsnNode).`var`
|
val varIndex = if (curInstr is VarInsnNode) curInstr.`var` else (curInstr as IincInsnNode).`var`
|
||||||
nextFreeLocalIndex = Math.max(nextFreeLocalIndex, varIndex + argSize)
|
nextFreeLocalIndex = Math.max(nextFreeLocalIndex, varIndex + argSize)
|
||||||
}
|
}
|
||||||
@@ -55,9 +55,9 @@ public abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract fun instructionIndex(inst: AbstractInsnNode): Int
|
abstract fun instructionIndex(inst: AbstractInsnNode): Int
|
||||||
|
|
||||||
public fun sortTryCatchBlocks(intervals: List<TryCatchBlockNodeInfo>): List<TryCatchBlockNodeInfo> {
|
fun sortTryCatchBlocks(intervals: List<TryCatchBlockNodeInfo>): List<TryCatchBlockNodeInfo> {
|
||||||
val comp = Comparator { t1: TryCatchBlockNodeInfo, t2: TryCatchBlockNodeInfo ->
|
val comp = Comparator { t1: TryCatchBlockNodeInfo, t2: TryCatchBlockNodeInfo ->
|
||||||
var result = instructionIndex(t1.handler) - instructionIndex(t2.handler)
|
var result = instructionIndex(t1.handler) - instructionIndex(t2.handler)
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
@@ -83,7 +83,7 @@ public abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun substituteLocalVarTable(node: MethodNode) {
|
fun substituteLocalVarTable(node: MethodNode) {
|
||||||
node.localVariables.clear()
|
node.localVariables.clear()
|
||||||
for (info in localVarsMetaInfo.getMeaningfulIntervals()) {
|
for (info in localVarsMetaInfo.getMeaningfulIntervals()) {
|
||||||
node.localVariables.add(info.node)
|
node.localVariables.add(info.node)
|
||||||
@@ -165,16 +165,16 @@ private fun Interval.isMeaningless(): Boolean {
|
|||||||
val start = this.startLabel
|
val start = this.startLabel
|
||||||
var end: AbstractInsnNode = this.endLabel
|
var end: AbstractInsnNode = this.endLabel
|
||||||
while (end != start && !end.isMeaningful) {
|
while (end != start && !end.isMeaningful) {
|
||||||
end = end.getPrevious()
|
end = end.previous
|
||||||
}
|
}
|
||||||
return start == end
|
return start == end
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : SplittableInterval<T>> IntervalMetaInfo<T>.getMeaningfulIntervals(): List<T> {
|
fun <T : SplittableInterval<T>> IntervalMetaInfo<T>.getMeaningfulIntervals(): List<T> {
|
||||||
return allIntervals.filterNot { it.isMeaningless() }
|
return allIntervals.filterNot { it.isMeaningless() }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DefaultProcessor(val node: MethodNode, parameterSize: Int) : CoveringTryCatchNodeProcessor(parameterSize) {
|
class DefaultProcessor(val node: MethodNode, parameterSize: Int) : CoveringTryCatchNodeProcessor(parameterSize) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
node.tryCatchBlocks.forEach { addTryNode(it) }
|
node.tryCatchBlocks.forEach { addTryNode(it) }
|
||||||
@@ -194,7 +194,7 @@ public class DefaultProcessor(val node: MethodNode, parameterSize: Int) : Coveri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInterval<LocalVarNodeWrapper> {
|
class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInterval<LocalVarNodeWrapper> {
|
||||||
override val startLabel: LabelNode
|
override val startLabel: LabelNode
|
||||||
get() = node.start
|
get() = node.start
|
||||||
override val endLabel: LabelNode
|
override val endLabel: LabelNode
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
public class DeferredMethodVisitor(
|
class DeferredMethodVisitor(
|
||||||
val intermediate: MethodNode,
|
val intermediate: MethodNode,
|
||||||
val resultNode: () -> MethodVisitor
|
val resultNode: () -> MethodVisitor
|
||||||
) : MethodVisitor(InlineCodegenUtil.API, intermediate) {
|
) : MethodVisitor(InlineCodegenUtil.API, intermediate) {
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ internal class Parameters(val real: List<ParameterInfo>, val captured: List<Capt
|
|||||||
private val actualDeclShifts: Array<ParameterInfo?>
|
private val actualDeclShifts: Array<ParameterInfo?>
|
||||||
private val paramToDeclByteCodeIndex: HashMap<ParameterInfo, Int> = hashMapOf()
|
private val paramToDeclByteCodeIndex: HashMap<ParameterInfo, Int> = hashMapOf()
|
||||||
|
|
||||||
public val realArgsSizeOnStack = real.sumBy { it.type.size }
|
val realArgsSizeOnStack = real.sumBy { it.type.size }
|
||||||
public val capturedArgsSizeOnStack = captured.sumBy { it.type.size }
|
val capturedArgsSizeOnStack = captured.sumBy { it.type.size }
|
||||||
|
|
||||||
public val argsSizeOnStack = realArgsSizeOnStack + capturedArgsSizeOnStack
|
val argsSizeOnStack = realArgsSizeOnStack + capturedArgsSizeOnStack
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val declIndexesToActual = arrayOfNulls<Int>(argsSizeOnStack)
|
val declIndexesToActual = arrayOfNulls<Int>(argsSizeOnStack)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
|||||||
|
|
||||||
private class ParameterNameAndNullability(val name: String, val nullable: Boolean)
|
private class ParameterNameAndNullability(val name: String, val nullable: Boolean)
|
||||||
|
|
||||||
public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) {
|
class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) {
|
||||||
|
|
||||||
enum class OperationKind {
|
enum class OperationKind {
|
||||||
NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS;
|
NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS;
|
||||||
@@ -43,25 +43,21 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker"
|
||||||
public val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker"
|
@JvmField val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification"
|
||||||
@JvmField
|
|
||||||
public val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification"
|
|
||||||
|
|
||||||
private fun isOperationReifiedMarker(insn: AbstractInsnNode) =
|
private fun isOperationReifiedMarker(insn: AbstractInsnNode) =
|
||||||
isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME }
|
isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME }
|
||||||
|
|
||||||
private fun isReifiedMarker(insn: AbstractInsnNode, namePredicate: (String) -> Boolean): Boolean {
|
private fun isReifiedMarker(insn: AbstractInsnNode, namePredicate: (String) -> Boolean): Boolean {
|
||||||
if (insn.getOpcode() != Opcodes.INVOKESTATIC || insn !is MethodInsnNode) return false
|
if (insn.opcode != Opcodes.INVOKESTATIC || insn !is MethodInsnNode) return false
|
||||||
return insn.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME && namePredicate(insn.name)
|
return insn.owner == IntrinsicMethods.INTRINSICS_CLASS_NAME && namePredicate(insn.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun isNeedClassReificationMarker(insn: AbstractInsnNode): Boolean =
|
||||||
public fun isNeedClassReificationMarker(insn: AbstractInsnNode): Boolean =
|
|
||||||
isReifiedMarker(insn) { s -> s == NEED_CLASS_REIFICATION_MARKER_METHOD_NAME }
|
isReifiedMarker(insn) { s -> s == NEED_CLASS_REIFICATION_MARKER_METHOD_NAME }
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun putNeedClassReificationMarker(v: MethodVisitor) {
|
||||||
public fun putNeedClassReificationMarker(v: MethodVisitor) {
|
|
||||||
v.visitMethodInsn(
|
v.visitMethodInsn(
|
||||||
Opcodes.INVOKESTATIC,
|
Opcodes.INVOKESTATIC,
|
||||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, NEED_CLASS_REIFICATION_MARKER_METHOD_NAME,
|
IntrinsicMethods.INTRINSICS_CLASS_NAME, NEED_CLASS_REIFICATION_MARKER_METHOD_NAME,
|
||||||
@@ -77,7 +73,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
* e.g. when we're generating inline function containing reified T
|
* e.g. when we're generating inline function containing reified T
|
||||||
* and another function containing reifiable parts is inlined into that function
|
* and another function containing reifiable parts is inlined into that function
|
||||||
*/
|
*/
|
||||||
public fun reifyInstructions(node: MethodNode): ReifiedTypeParametersUsages {
|
fun reifyInstructions(node: MethodNode): ReifiedTypeParametersUsages {
|
||||||
if (parametersMapping == null) return ReifiedTypeParametersUsages()
|
if (parametersMapping == null) return ReifiedTypeParametersUsages()
|
||||||
val instructions = node.instructions
|
val instructions = node.instructions
|
||||||
maxStackSize = 0
|
maxStackSize = 0
|
||||||
@@ -95,7 +91,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun reifySignature(oldSignature: String): SignatureReificationResult {
|
fun reifySignature(oldSignature: String): SignatureReificationResult {
|
||||||
if (parametersMapping == null) return SignatureReificationResult(oldSignature, ReifiedTypeParametersUsages())
|
if (parametersMapping == null) return SignatureReificationResult(oldSignature, ReifiedTypeParametersUsages())
|
||||||
|
|
||||||
val signatureRemapper = object : SignatureWriter() {
|
val signatureRemapper = object : SignatureWriter() {
|
||||||
@@ -223,13 +219,13 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processNextTypeInsn(insn: MethodInsnNode, parameter: Type, expectedNextOpcode: Int): Boolean {
|
private fun processNextTypeInsn(insn: MethodInsnNode, parameter: Type, expectedNextOpcode: Int): Boolean {
|
||||||
if (insn.getNext()?.getOpcode() != expectedNextOpcode) return false
|
if (insn.next?.opcode != expectedNextOpcode) return false
|
||||||
(insn.getNext() as TypeInsnNode).desc = parameter.getInternalName()
|
(insn.next as TypeInsnNode).desc = parameter.internalName
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processJavaClass(insn: MethodInsnNode, parameter: Type): Boolean {
|
private fun processJavaClass(insn: MethodInsnNode, parameter: Type): Boolean {
|
||||||
val next = insn.getNext()
|
val next = insn.next
|
||||||
if (next !is LdcInsnNode) return false
|
if (next !is LdcInsnNode) return false
|
||||||
next.cst = parameter
|
next.cst = parameter
|
||||||
return true
|
return true
|
||||||
@@ -255,14 +251,14 @@ private val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get(
|
|||||||
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReifiedTypeParameterMappings() {
|
class ReifiedTypeParameterMappings() {
|
||||||
private val mappingsByName = hashMapOf<String, ReifiedTypeParameterMapping>()
|
private val mappingsByName = hashMapOf<String, ReifiedTypeParameterMapping>()
|
||||||
|
|
||||||
public fun addParameterMappingToType(name: String, type: KotlinType, asmType: Type, signature: String) {
|
fun addParameterMappingToType(name: String, type: KotlinType, asmType: Type, signature: String) {
|
||||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type, asmType, newName = null, signature = signature)
|
mappingsByName[name] = ReifiedTypeParameterMapping(name, type, asmType, newName = null, signature = signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addParameterMappingToNewParameter(name: String, type: KotlinType, newName: String) {
|
fun addParameterMappingToNewParameter(name: String, type: KotlinType, newName: String) {
|
||||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = type, asmType = null, newName = newName, signature = null)
|
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = type, asmType = null, newName = newName, signature = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,20 +267,20 @@ public class ReifiedTypeParameterMappings() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReifiedTypeParameterMapping(
|
class ReifiedTypeParameterMapping(
|
||||||
val name: String, val type: KotlinType, val asmType: Type?, val newName: String?, val signature: String?
|
val name: String, val type: KotlinType, val asmType: Type?, val newName: String?, val signature: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
public class ReifiedTypeParametersUsages {
|
class ReifiedTypeParametersUsages {
|
||||||
val usedTypeParameters: MutableSet<String> = hashSetOf()
|
val usedTypeParameters: MutableSet<String> = hashSetOf()
|
||||||
|
|
||||||
public fun wereUsedReifiedParameters(): Boolean = usedTypeParameters.isNotEmpty()
|
fun wereUsedReifiedParameters(): Boolean = usedTypeParameters.isNotEmpty()
|
||||||
|
|
||||||
public fun addUsedReifiedParameter(name: String) {
|
fun addUsedReifiedParameter(name: String) {
|
||||||
usedTypeParameters.add(name)
|
usedTypeParameters.add(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun propagateChildUsagesWithinContext(child: ReifiedTypeParametersUsages, context: MethodContext) {
|
fun propagateChildUsagesWithinContext(child: ReifiedTypeParametersUsages, context: MethodContext) {
|
||||||
if (!child.wereUsedReifiedParameters()) return
|
if (!child.wereUsedReifiedParameters()) return
|
||||||
// used for propagating reified TP usages from children member codegen to parent's
|
// used for propagating reified TP usages from children member codegen to parent's
|
||||||
// mark enclosing object-literal/lambda as needed reification iff
|
// mark enclosing object-literal/lambda as needed reification iff
|
||||||
@@ -298,7 +294,7 @@ public class ReifiedTypeParametersUsages {
|
|||||||
}.forEach { usedTypeParameters.add(it) }
|
}.forEach { usedTypeParameters.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun mergeAll(other: ReifiedTypeParametersUsages) {
|
fun mergeAll(other: ReifiedTypeParametersUsages) {
|
||||||
if (!other.wereUsedReifiedParameters()) return
|
if (!other.wereUsedReifiedParameters()) return
|
||||||
usedTypeParameters.addAll(other.usedTypeParameters)
|
usedTypeParameters.addAll(other.usedTypeParameters)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
//TODO join parameter
|
//TODO join parameter
|
||||||
public class SMAPBuilder(val source: String,
|
class SMAPBuilder(val source: String,
|
||||||
val path: String,
|
val path: String,
|
||||||
val fileMappings: List<FileMapping>) {
|
val fileMappings: List<FileMapping>) {
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ public class SMAPBuilder(val source: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class NestedSourceMapper(parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo) : DefaultSourceMapper(sourceInfo, parent) {
|
open class NestedSourceMapper(parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo) : DefaultSourceMapper(sourceInfo, parent) {
|
||||||
|
|
||||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
||||||
val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) {
|
val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) {
|
||||||
@@ -81,7 +81,7 @@ public open class NestedSourceMapper(parent: SourceMapper, val ranges: List<Rang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNode) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNode) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
||||||
|
|
||||||
override fun visitSource(name: String, path: String) {
|
override fun visitSource(name: String, path: String) {
|
||||||
super.visitSource(name, path)
|
super.visitSource(name, path)
|
||||||
@@ -162,7 +162,7 @@ interface SourceMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object IdenticalSourceMapper : SourceMapper {
|
object IdenticalSourceMapper : SourceMapper {
|
||||||
override val resultMappings: List<FileMapping>
|
override val resultMappings: List<FileMapping>
|
||||||
get() = emptyList()
|
get() = emptyList()
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ public object IdenticalSourceMapper : SourceMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: SourceMapper?): SourceMapper {
|
open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: SourceMapper?): SourceMapper {
|
||||||
|
|
||||||
protected var maxUsedValue: Int = sourceInfo.linesInFile
|
protected var maxUsedValue: Int = sourceInfo.linesInFile
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ class RawFileMapping(val name: String, val path: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun initRange(start: Int, end: Int) {
|
fun initRange(start: Int, end: Int) {
|
||||||
assert(lineMappings.isEmpty()) { "initRange should only be called for empty mapping" }
|
assert(lineMappings.isEmpty) { "initRange should only be called for empty mapping" }
|
||||||
for (index in start..end) {
|
for (index in start..end) {
|
||||||
lineMappings.put(index, index)
|
lineMappings.put(index, index)
|
||||||
}
|
}
|
||||||
@@ -319,7 +319,7 @@ class RawFileMapping(val name: String, val path: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open public class FileMapping(val name: String, val path: String) {
|
open class FileMapping(val name: String, val path: String) {
|
||||||
val lineMappings = arrayListOf<RangeMapping>()
|
val lineMappings = arrayListOf<RangeMapping>()
|
||||||
|
|
||||||
var id = -1;
|
var id = -1;
|
||||||
@@ -329,7 +329,7 @@ open public class FileMapping(val name: String, val path: String) {
|
|||||||
lineMapping.parent = this
|
lineMapping.parent = this
|
||||||
}
|
}
|
||||||
|
|
||||||
public object SKIP : FileMapping("no-source-info", "no-source-info") {
|
object SKIP : FileMapping("no-source-info", "no-source-info") {
|
||||||
init {
|
init {
|
||||||
addRangeMapping(RangeMapping.SKIP)
|
addRangeMapping(RangeMapping.SKIP)
|
||||||
}
|
}
|
||||||
@@ -337,7 +337,7 @@ open public class FileMapping(val name: String, val path: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO comparable
|
//TODO comparable
|
||||||
data public class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
|
data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
|
||||||
|
|
||||||
var parent: FileMapping? = null;
|
var parent: FileMapping? = null;
|
||||||
|
|
||||||
@@ -366,6 +366,6 @@ data public class RangeMapping(val source: Int, val dest: Int, var range: Int =
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public val SKIP = RangeMapping(-1, -1, 1)
|
val SKIP = RangeMapping(-1, -1, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.codegen.SourceInfo
|
|||||||
class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) {
|
class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) {
|
||||||
|
|
||||||
val lineNumbers =
|
val lineNumbers =
|
||||||
InsnSequence(node.instructions.getFirst(), null).filterIsInstance<LineNumberNode>().map {
|
InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map {
|
||||||
val index = Collections.binarySearch(classSMAP.intervals, RangeMapping(it.line, it.line, 1)) {
|
val index = Collections.binarySearch(classSMAP.intervals, RangeMapping(it.line, it.line, 1)) {
|
||||||
value, key ->
|
value, key ->
|
||||||
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
|
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import com.intellij.util.SmartFMap
|
|||||||
object SMAPParser {
|
object SMAPParser {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
/*null smap means that there is no any debug info in file (e.g. sourceName)*/
|
/*null smap means that there is no any debug info in file (e.g. sourceName)*/ fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
|
||||||
public fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
|
|
||||||
if (mappingInfo == null || mappingInfo.isEmpty()) {
|
if (mappingInfo == null || mappingInfo.isEmpty()) {
|
||||||
val fm: FileMapping
|
val fm: FileMapping
|
||||||
if (source == null || source.isEmpty()) {
|
if (source == null || source.isEmpty()) {
|
||||||
@@ -40,8 +39,7 @@ object SMAPParser {
|
|||||||
return parse(mappingInfo)
|
return parse(mappingInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun parse(mappingInfo: String): SMAP {
|
||||||
public fun parse(mappingInfo: String): SMAP {
|
|
||||||
val fileMappings = linkedMapOf<Int, FileMapping>()
|
val fileMappings = linkedMapOf<Int, FileMapping>()
|
||||||
|
|
||||||
val fileSectionStart = mappingInfo.indexOf(SMAP.FILE_SECTION) + SMAP.FILE_SECTION.length
|
val fileSectionStart = mappingInfo.indexOf(SMAP.FILE_SECTION) + SMAP.FILE_SECTION.length
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ enum class TryCatchPosition {
|
|||||||
INNER
|
INNER
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SplitPair<T: Interval>(val patchedPart: T, val newPart: T)
|
class SplitPair<T: Interval>(val patchedPart: T, val newPart: T)
|
||||||
|
|
||||||
class SimpleInterval(override val startLabel: LabelNode, override val endLabel: LabelNode ) : Interval
|
class SimpleInterval(override val startLabel: LabelNode, override val endLabel: LabelNode ) : Interval
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ interface Interval {
|
|||||||
val endLabel: LabelNode
|
val endLabel: LabelNode
|
||||||
|
|
||||||
/*note that some intervals are mutable */
|
/*note that some intervals are mutable */
|
||||||
public fun isEmpty(): Boolean = startLabel == endLabel
|
fun isEmpty(): Boolean = startLabel == endLabel
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||||
|
|
||||||
public val FunctionDescriptor.sourceFilePath: String
|
val FunctionDescriptor.sourceFilePath: String
|
||||||
get() {
|
get() {
|
||||||
val source = source as PsiSourceElement
|
val source = source as PsiSourceElement
|
||||||
val containingFile = source.psi?.containingFile
|
val containingFile = source.psi?.containingFile
|
||||||
return containingFile?.virtualFile?.canonicalPath!!
|
return containingFile?.virtualFile?.canonicalPath!!
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun FunctionDescriptor.getClassFilePath(typeMapper: JetTypeMapper, cache: IncrementalCache): String {
|
fun FunctionDescriptor.getClassFilePath(typeMapper: JetTypeMapper, cache: IncrementalCache): String {
|
||||||
val container = containingDeclaration as? DeclarationDescriptorWithSource
|
val container = containingDeclaration as? DeclarationDescriptorWithSource
|
||||||
val source = container?.source
|
val source = container?.source
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil.correctElementType
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class ArrayGet : IntrinsicMethod() {
|
class ArrayGet : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createIntrinsicCallable(method) {
|
createIntrinsicCallable(method) {
|
||||||
val type = correctElementType(calcReceiverType())
|
val type = correctElementType(calcReceiverType())
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class ArrayIterator : IntrinsicMethod() {
|
class ArrayIterator : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createUnaryIntrinsicCallable(method) {
|
createUnaryIntrinsicCallable(method) {
|
||||||
val methodSignature = "(${method.owner.getDescriptor()})${returnType.getDescriptor()}"
|
val methodSignature = "(${method.owner.descriptor})${returnType.descriptor}"
|
||||||
val intrinsicOwner =
|
val intrinsicOwner =
|
||||||
if (AsmUtil.isPrimitive(method.owner.elementType))
|
if (AsmUtil.isPrimitive(method.owner.elementType))
|
||||||
"kotlin/jvm/internal/ArrayIteratorsKt"
|
"kotlin/jvm/internal/ArrayIteratorsKt"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.codegen.CallableMethod
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class ArraySet : IntrinsicMethod() {
|
class ArraySet : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable {
|
override fun toCallable(method: CallableMethod): Callable {
|
||||||
val type = correctElementType(method.dispatchReceiverType)
|
val type = correctElementType(method.dispatchReceiverType)
|
||||||
return object : IntrinsicCallable(
|
return object : IntrinsicCallable(
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.codegen.StackValue
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
public class ArraySize : IntrinsicPropertyGetter() {
|
class ArraySize : IntrinsicPropertyGetter() {
|
||||||
override fun generate(
|
override fun generate(
|
||||||
resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue
|
resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue
|
||||||
) = StackValue.operation(returnType) {
|
) = StackValue.operation(returnType) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.ISHR
|
|||||||
import org.jetbrains.org.objectweb.asm.Opcodes.IUSHR
|
import org.jetbrains.org.objectweb.asm.Opcodes.IUSHR
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
public class BinaryOp(private val opcode: Int) : IntrinsicMethod() {
|
class BinaryOp(private val opcode: Int) : IntrinsicMethod() {
|
||||||
private fun shift(): Boolean =
|
private fun shift(): Boolean =
|
||||||
opcode == ISHL || opcode == ISHR || opcode == IUSHR
|
opcode == ISHL || opcode == ISHR || opcode == IUSHR
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.codegen.CallableMethod
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
public class Clone : IntrinsicMethod() {
|
class Clone : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod, isSuperCall: Boolean): Callable =
|
override fun toCallable(method: CallableMethod, isSuperCall: Boolean): Callable =
|
||||||
createUnaryIntrinsicCallable(method, OBJECT_TYPE) {
|
createUnaryIntrinsicCallable(method, OBJECT_TYPE) {
|
||||||
val opcode = if (isSuperCall) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL
|
val opcode = if (isSuperCall) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.codegen.CallableMethod
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class CompareTo : IntrinsicMethod() {
|
class CompareTo : IntrinsicMethod() {
|
||||||
private fun genInvoke(type: Type?, v: InstructionAdapter) {
|
private fun genInvoke(type: Type?, v: InstructionAdapter) {
|
||||||
when (type) {
|
when (type) {
|
||||||
Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
|
Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class Concat : IntrinsicMethod() {
|
class Concat : IntrinsicMethod() {
|
||||||
fun generateImpl(
|
fun generateImpl(
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.codegen.Callable
|
|||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
|
|
||||||
public class Equals : IntrinsicMethod() {
|
class Equals : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createBinaryIntrinsicCallable(
|
createBinaryIntrinsicCallable(
|
||||||
method.returnType,
|
method.returnType,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class HashCode : IntrinsicMethod() {
|
class HashCode : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
object : IntrinsicCallable(
|
object : IntrinsicCallable(
|
||||||
Type.INT_TYPE,
|
Type.INT_TYPE,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.KtCallExpression
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
|
|
||||||
public class IdentityEquals : IntrinsicMethod() {
|
class IdentityEquals : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
object : IntrinsicCallable(method) {
|
object : IntrinsicCallable(method) {
|
||||||
override fun invokeMethodWithArguments(
|
override fun invokeMethodWithArguments(
|
||||||
@@ -34,17 +34,17 @@ public class IdentityEquals : IntrinsicMethod() {
|
|||||||
receiver: StackValue,
|
receiver: StackValue,
|
||||||
codegen: ExpressionCodegen
|
codegen: ExpressionCodegen
|
||||||
): StackValue {
|
): StackValue {
|
||||||
val element = resolvedCall.getCall().getCallElement()
|
val element = resolvedCall.call.callElement
|
||||||
val left: StackValue
|
val left: StackValue
|
||||||
val right: StackValue
|
val right: StackValue
|
||||||
if (element is KtCallExpression) {
|
if (element is KtCallExpression) {
|
||||||
left = StackValue.receiver(resolvedCall, receiver, codegen, this)
|
left = StackValue.receiver(resolvedCall, receiver, codegen, this)
|
||||||
right = codegen.gen(resolvedCall.getValueArgumentsByIndex()!!.single().getArguments().single().getArgumentExpression())
|
right = codegen.gen(resolvedCall.valueArgumentsByIndex!!.single().arguments.single().getArgumentExpression())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
element as KtBinaryExpression
|
element as KtBinaryExpression
|
||||||
left = codegen.gen(element.getLeft())
|
left = codegen.gen(element.left)
|
||||||
right = codegen.gen(element.getRight())
|
right = codegen.gen(element.right)
|
||||||
}
|
}
|
||||||
return StackValue.cmp(KtTokens.EQEQEQ, OBJECT_TYPE, left, right)
|
return StackValue.cmp(KtTokens.EQEQEQ, OBJECT_TYPE, left, right)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import org.jetbrains.kotlin.codegen.CallableMethod
|
|||||||
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
|
||||||
public class Increment(private val myDelta: Int) : IntrinsicMethod() {
|
class Increment(private val myDelta: Int) : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod, isSuper: Boolean, resolvedCall: ResolvedCall<*>): Callable =
|
override fun toCallable(method: CallableMethod, isSuper: Boolean, resolvedCall: ResolvedCall<*>): Callable =
|
||||||
createIntrinsicCallable(method) {
|
createIntrinsicCallable(method) {
|
||||||
val jetExpression = resolvedCall.getCall().getCalleeExpression()
|
val jetExpression = resolvedCall.call.calleeExpression
|
||||||
assert(jetExpression !is KtPrefixExpression) { "There should be postfix increment ${jetExpression!!.getText()}" }
|
assert(jetExpression !is KtPrefixExpression) { "There should be postfix increment ${jetExpression!!.text}" }
|
||||||
genIncrement(returnType, myDelta, it)
|
genIncrement(returnType, myDelta, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.codegen.CallableMethod
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public open class IntrinsicCallable(
|
open class IntrinsicCallable(
|
||||||
override val returnType: Type,
|
override val returnType: Type,
|
||||||
override val valueParameterTypes: List<Type>,
|
override val valueParameterTypes: List<Type>,
|
||||||
override val dispatchReceiverType: Type?,
|
override val dispatchReceiverType: Type?,
|
||||||
@@ -45,7 +45,7 @@ public open class IntrinsicCallable(
|
|||||||
invokeIntrinsic(v)
|
invokeIntrinsic(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
public open fun invokeIntrinsic(v: InstructionAdapter) {
|
open fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
invoke(v)
|
invoke(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public open class IntrinsicCallable(
|
|||||||
override val owner: Type
|
override val owner: Type
|
||||||
get() = throw UnsupportedOperationException()
|
get() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
public fun calcReceiverType(): Type =
|
fun calcReceiverType(): Type =
|
||||||
extensionReceiverType ?: dispatchReceiverType!!
|
extensionReceiverType ?: dispatchReceiverType!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ fun createBinaryIntrinsicCallable(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun createUnaryIntrinsicCallable(
|
fun createUnaryIntrinsicCallable(
|
||||||
callable: CallableMethod,
|
callable: CallableMethod,
|
||||||
newReturnType: Type? = null,
|
newReturnType: Type? = null,
|
||||||
needPrimitiveCheck: Boolean = false,
|
needPrimitiveCheck: Boolean = false,
|
||||||
@@ -103,7 +103,7 @@ public fun createUnaryIntrinsicCallable(
|
|||||||
return intrinsic
|
return intrinsic
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun createIntrinsicCallable(
|
fun createIntrinsicCallable(
|
||||||
callable: CallableMethod,
|
callable: CallableMethod,
|
||||||
invoke: IntrinsicCallable.(v: InstructionAdapter) -> Unit
|
invoke: IntrinsicCallable.(v: InstructionAdapter) -> Unit
|
||||||
): IntrinsicCallable {
|
): IntrinsicCallable {
|
||||||
|
|||||||
+2
-2
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.codegen.StackValue
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
public abstract class IntrinsicPropertyGetter : IntrinsicMethod() {
|
abstract class IntrinsicPropertyGetter : IntrinsicMethod() {
|
||||||
public abstract fun generate(
|
abstract fun generate(
|
||||||
resolvedCall: ResolvedCall<*>?,
|
resolvedCall: ResolvedCall<*>?,
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
returnType: Type,
|
returnType: Type,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.codegen.Callable
|
|||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
public class Inv : IntrinsicMethod() {
|
class Inv : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable {
|
override fun toCallable(method: CallableMethod): Callable {
|
||||||
val type = numberFunctionOperandType(method.returnType)
|
val type = numberFunctionOperandType(method.returnType)
|
||||||
return createUnaryIntrinsicCallable(method, newThisType = type) {
|
return createUnaryIntrinsicCallable(method, newThisType = type) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class IteratorNext : IntrinsicMethod() {
|
class IteratorNext : IntrinsicMethod() {
|
||||||
private fun getIteratorName(returnType: Type): String {
|
private fun getIteratorName(returnType: Type): String {
|
||||||
return when (returnType) {
|
return when (returnType) {
|
||||||
Type.CHAR_TYPE -> "Char"
|
Type.CHAR_TYPE -> "Char"
|
||||||
@@ -47,7 +47,7 @@ public class IteratorNext : IntrinsicMethod() {
|
|||||||
v.invokevirtual(
|
v.invokevirtual(
|
||||||
BUILT_INS_PACKAGE_FQ_NAME.asString() + "/" + name + "Iterator",
|
BUILT_INS_PACKAGE_FQ_NAME.asString() + "/" + name + "Iterator",
|
||||||
"next$name",
|
"next$name",
|
||||||
"()" + returnType.getDescriptor(),
|
"()" + returnType.descriptor,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class JavaClassArray : IntrinsicMethod() {
|
class JavaClassArray : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createIntrinsicCallable(method) {
|
createIntrinsicCallable(method) {
|
||||||
//do nothing all generated as vararg
|
//do nothing all generated as vararg
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class JavaClassFunction : IntrinsicMethod() {
|
class JavaClassFunction : IntrinsicMethod() {
|
||||||
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
||||||
val javaClass = resolvedCall.getResultingDescriptor().getReturnType()!!.getArguments().first().getType()
|
val javaClass = resolvedCall.resultingDescriptor.returnType!!.arguments.first().type
|
||||||
return object : IntrinsicCallable(getType(Class::class.java), listOf(), null, null) {
|
return object : IntrinsicCallable(getType(Class::class.java), listOf(), null, null) {
|
||||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(javaClass, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
|
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(javaClass, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class JavaClassProperty : IntrinsicPropertyGetter() {
|
class JavaClassProperty : IntrinsicPropertyGetter() {
|
||||||
public override fun generate(
|
override fun generate(
|
||||||
resolvedCall: ResolvedCall<*>?,
|
resolvedCall: ResolvedCall<*>?,
|
||||||
codegen: ExpressionCodegen,
|
codegen: ExpressionCodegen,
|
||||||
returnType: Type,
|
returnType: Type,
|
||||||
@@ -47,7 +47,7 @@ public class JavaClassProperty : IntrinsicPropertyGetter() {
|
|||||||
receiver.put(type, v)
|
receiver.put(type, v)
|
||||||
AsmUtil.pop(v, type)
|
AsmUtil.pop(v, type)
|
||||||
}
|
}
|
||||||
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;")
|
v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
receiver.put(type, v)
|
receiver.put(type, v)
|
||||||
@@ -58,11 +58,11 @@ public class JavaClassProperty : IntrinsicPropertyGetter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
||||||
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver()!!.getType())
|
val classType = codegen.getState().typeMapper.mapType(resolvedCall.call.dispatchReceiver!!.type)
|
||||||
return object : IntrinsicCallable(getType(Class::class.java), listOf(), classType, null) {
|
return object : IntrinsicCallable(getType(Class::class.java), listOf(), classType, null) {
|
||||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
if (isPrimitive(classType)) {
|
if (isPrimitive(classType)) {
|
||||||
v.getstatic(boxType(classType).getInternalName(), "TYPE", "Ljava/lang/Class;")
|
v.getstatic(boxType(classType).internalName, "TYPE", "Ljava/lang/Class;")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class KClassJavaProperty : IntrinsicPropertyGetter() {
|
class KClassJavaProperty : IntrinsicPropertyGetter() {
|
||||||
override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
|
override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
|
||||||
val extensionReceiver = resolvedCall!!.extensionReceiver as ReceiverValue
|
val extensionReceiver = resolvedCall!!.extensionReceiver as ReceiverValue
|
||||||
val type = extensionReceiver.type.arguments.single().type
|
val type = extensionReceiver.type.arguments.single().type
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class NewArray : IntrinsicMethod() {
|
class NewArray : IntrinsicMethod() {
|
||||||
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
||||||
val jetType = resolvedCall.getResultingDescriptor().getReturnType()!!
|
val jetType = resolvedCall.resultingDescriptor.returnType!!
|
||||||
val type = codegen.getState().typeMapper.mapType(jetType)
|
val type = codegen.getState().typeMapper.mapType(jetType)
|
||||||
return object : IntrinsicCallable(type, listOf(Type.INT_TYPE), null, null) {
|
return object : IntrinsicCallable(type, listOf(Type.INT_TYPE), null, null) {
|
||||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.codegen.StackValue
|
|||||||
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
|
||||||
public class Not : IntrinsicMethod() {
|
class Not : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
object : IntrinsicCallable(method) {
|
object : IntrinsicCallable(method) {
|
||||||
override fun invokeMethodWithArguments(
|
override fun invokeMethodWithArguments(
|
||||||
@@ -31,10 +31,10 @@ public class Not : IntrinsicMethod() {
|
|||||||
receiver: StackValue,
|
receiver: StackValue,
|
||||||
codegen: ExpressionCodegen
|
codegen: ExpressionCodegen
|
||||||
): StackValue {
|
): StackValue {
|
||||||
val element = resolvedCall.getCall().getCallElement()
|
val element = resolvedCall.call.callElement
|
||||||
val stackValue =
|
val stackValue =
|
||||||
if (element is KtPrefixExpression) {
|
if (element is KtPrefixExpression) {
|
||||||
codegen.gen(element.getBaseExpression())
|
codegen.gen(element.baseExpression)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
StackValue.receiver(resolvedCall, receiver, codegen, this)
|
StackValue.receiver(resolvedCall, receiver, codegen, this)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.codegen.Callable
|
|||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
|
|
||||||
public class NumberCast : IntrinsicMethod() {
|
class NumberCast : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createUnaryIntrinsicCallable(method) {
|
createUnaryIntrinsicCallable(method) {
|
||||||
StackValue.coerce(calcReceiverType(), returnType, it)
|
StackValue.coerce(calcReceiverType(), returnType, it)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import org.jetbrains.org.objectweb.asm.Type.*
|
import org.jetbrains.org.objectweb.asm.Type.*
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
public class RangeTo : IntrinsicMethod() {
|
class RangeTo : IntrinsicMethod() {
|
||||||
private fun nameToPrimitive(name: String): Type =
|
private fun nameToPrimitive(name: String): Type =
|
||||||
when (name) {
|
when (name) {
|
||||||
"Double" -> DOUBLE_TYPE
|
"Double" -> DOUBLE_TYPE
|
||||||
@@ -37,7 +37,7 @@ public class RangeTo : IntrinsicMethod() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toCallable(method: CallableMethod): Callable {
|
override fun toCallable(method: CallableMethod): Callable {
|
||||||
val argType = nameToPrimitive(method.returnType.getInternalName().substringAfter("kotlin/").substringBefore("Range"))
|
val argType = nameToPrimitive(method.returnType.internalName.substringAfter("kotlin/").substringBefore("Range"))
|
||||||
return object : IntrinsicCallable(
|
return object : IntrinsicCallable(
|
||||||
method.returnType,
|
method.returnType,
|
||||||
method.valueParameterTypes.map { argType },
|
method.valueParameterTypes.map { argType },
|
||||||
@@ -60,7 +60,7 @@ public class RangeTo : IntrinsicMethod() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
v.invokespecial(returnType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
|
v.invokespecial(returnType.internalName, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class StringGetChar : IntrinsicMethod() {
|
class StringGetChar : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createIntrinsicCallable(method) {
|
createIntrinsicCallable(method) {
|
||||||
it.invokevirtual("java/lang/String", "charAt", "(I)C", false)
|
it.invokevirtual("java/lang/String", "charAt", "(I)C", false)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class StringPlus : IntrinsicMethod() {
|
class StringPlus : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createIntrinsicCallable(method) {
|
createIntrinsicCallable(method) {
|
||||||
it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus",
|
it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus",
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class ToString : IntrinsicMethod() {
|
class ToString : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable {
|
override fun toCallable(method: CallableMethod): Callable {
|
||||||
val type = AsmUtil.stringValueOfType(method.dispatchReceiverType ?: method.extensionReceiverType)
|
val type = AsmUtil.stringValueOfType(method.dispatchReceiverType ?: method.extensionReceiverType)
|
||||||
return createUnaryIntrinsicCallable(method, newThisType = type) {
|
return createUnaryIntrinsicCallable(method, newThisType = type) {
|
||||||
it.invokestatic("java/lang/String", "valueOf", "(${type.getDescriptor()})Ljava/lang/String;", false)
|
it.invokestatic("java/lang/String", "valueOf", "(${type.descriptor})Ljava/lang/String;", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.*
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
import kotlin.text.Regex
|
import kotlin.text.Regex
|
||||||
|
|
||||||
public object TypeIntrinsics {
|
object TypeIntrinsics {
|
||||||
public @JvmStatic fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type) {
|
@JvmStatic fun instanceOf(v: InstructionAdapter, jetType: KotlinType, boxedAsmType: Type) {
|
||||||
val functionTypeArity = getFunctionTypeArity(jetType)
|
val functionTypeArity = getFunctionTypeArity(jetType)
|
||||||
if (functionTypeArity >= 0) {
|
if (functionTypeArity >= 0) {
|
||||||
v.iconst(functionTypeArity)
|
v.iconst(functionTypeArity)
|
||||||
@@ -57,7 +57,7 @@ public object TypeIntrinsics {
|
|||||||
LdcInsnNode(Integer(value))
|
LdcInsnNode(Integer(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
public @JvmStatic fun instanceOf(instanceofInsn: TypeInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type) {
|
@JvmStatic fun instanceOf(instanceofInsn: TypeInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type) {
|
||||||
val functionTypeArity = getFunctionTypeArity(jetType)
|
val functionTypeArity = getFunctionTypeArity(jetType)
|
||||||
if (functionTypeArity >= 0) {
|
if (functionTypeArity >= 0) {
|
||||||
instructions.insertBefore(instanceofInsn, iconstNode(functionTypeArity))
|
instructions.insertBefore(instanceofInsn, iconstNode(functionTypeArity))
|
||||||
@@ -78,8 +78,7 @@ public object TypeIntrinsics {
|
|||||||
instanceofInsn.desc = asmType.internalName
|
instanceofInsn.desc = asmType.internalName
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun checkcast(
|
||||||
public fun checkcast(
|
|
||||||
v: InstructionAdapter,
|
v: InstructionAdapter,
|
||||||
kotlinType: KotlinType, asmType: Type,
|
kotlinType: KotlinType, asmType: Type,
|
||||||
// This parameter is just for sake of optimization:
|
// This parameter is just for sake of optimization:
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class UnaryMinus : IntrinsicMethod() {
|
class UnaryMinus : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createUnaryIntrinsicCallable(method, numberFunctionOperandType(method.returnType), needPrimitiveCheck = true) {
|
createUnaryIntrinsicCallable(method, numberFunctionOperandType(method.returnType), needPrimitiveCheck = true) {
|
||||||
it.neg(returnType)
|
it.neg(returnType)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
|||||||
import org.jetbrains.kotlin.codegen.Callable
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
|
||||||
public class UnaryPlus : IntrinsicMethod() {
|
class UnaryPlus : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createUnaryIntrinsicCallable(method) {
|
createUnaryIntrinsicCallable(method) {
|
||||||
//nothing
|
//nothing
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
|||||||
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||||
|
|
||||||
public class DeadCodeEliminationMethodTransformer : MethodTransformer() {
|
class DeadCodeEliminationMethodTransformer : MethodTransformer() {
|
||||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||||
val frames = MethodTransformer.analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
|
val frames = MethodTransformer.analyze(internalClassName, methodNode, OptimizationBasicInterpreter())
|
||||||
val insnList = methodNode.instructions
|
val insnList = methodNode.instructions
|
||||||
|
|||||||
+3
-3
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
|||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.tree.*
|
import org.jetbrains.org.objectweb.asm.tree.*
|
||||||
|
|
||||||
public class LabelNormalizationMethodTransformer : MethodTransformer() {
|
class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||||
public override fun transform(internalClassName: String, methodNode: MethodNode) {
|
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||||
TransformerForMethod(methodNode).transform()
|
TransformerForMethod(methodNode).transform()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ public class LabelNormalizationMethodTransformer : MethodTransformer() {
|
|||||||
val instructions = methodNode.instructions
|
val instructions = methodNode.instructions
|
||||||
val newLabelNodes = hashMapOf<Label, LabelNode>()
|
val newLabelNodes = hashMapOf<Label, LabelNode>()
|
||||||
|
|
||||||
public fun transform() {
|
fun transform() {
|
||||||
if (rewriteLabelInstructions()) {
|
if (rewriteLabelInstructions()) {
|
||||||
rewriteNonLabelInstructions()
|
rewriteNonLabelInstructions()
|
||||||
rewriteTryCatchBlocks()
|
rewriteTryCatchBlocks()
|
||||||
|
|||||||
+2
-2
@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransfor
|
|||||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
public class MandatoryMethodTransformer : MethodTransformer() {
|
class MandatoryMethodTransformer : MethodTransformer() {
|
||||||
private val labelNormalization = LabelNormalizationMethodTransformer()
|
private val labelNormalization = LabelNormalizationMethodTransformer()
|
||||||
private val fixStack = FixStackMethodTransformer()
|
private val fixStack = FixStackMethodTransformer()
|
||||||
|
|
||||||
public override fun transform(internalClassName: String, methodNode: MethodNode) {
|
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||||
labelNormalization.transform(internalClassName, methodNode)
|
labelNormalization.transform(internalClassName, methodNode)
|
||||||
fixStack.transform(internalClassName, methodNode)
|
fixStack.transform(internalClassName, methodNode)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||||
|
|
||||||
public class RedundantGotoMethodTransformer : MethodTransformer() {
|
class RedundantGotoMethodTransformer : MethodTransformer() {
|
||||||
/**
|
/**
|
||||||
* Removes redundant GOTO's, i.e. to subsequent labels
|
* Removes redundant GOTO's, i.e. to subsequent labels
|
||||||
*/
|
*/
|
||||||
@@ -35,7 +35,7 @@ public class RedundantGotoMethodTransformer : MethodTransformer() {
|
|||||||
val currentLabels = hashSetOf<LabelNode>()
|
val currentLabels = hashSetOf<LabelNode>()
|
||||||
for (insn in insns) {
|
for (insn in insns) {
|
||||||
if (insn.isMeaningful) {
|
if (insn.isMeaningful) {
|
||||||
if (insn.getOpcode() == Opcodes.GOTO && (insn as JumpInsnNode).label in currentLabels) {
|
if (insn.opcode == Opcodes.GOTO && (insn as JumpInsnNode).label in currentLabels) {
|
||||||
insnsToRemove.add(insn)
|
insnsToRemove.add(insn)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+2
-2
@@ -23,7 +23,7 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
public class NullabilityInterpreter(insns: InsnList) : BoxingInterpreter(insns) {
|
class NullabilityInterpreter(insns: InsnList) : BoxingInterpreter(insns) {
|
||||||
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue) = makeNotNullIfNeeded(insn, super.unaryOperation(insn, value))
|
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue) = makeNotNullIfNeeded(insn, super.unaryOperation(insn, value))
|
||||||
|
|
||||||
override fun newOperation(insn: AbstractInsnNode) = makeNotNullIfNeeded(insn, super.newOperation(insn))
|
override fun newOperation(insn: AbstractInsnNode) = makeNotNullIfNeeded(insn, super.newOperation(insn))
|
||||||
@@ -35,7 +35,7 @@ public class NullabilityInterpreter(insns: InsnList) : BoxingInterpreter(insns)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun makeNotNullIfNeeded(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
|
private fun makeNotNullIfNeeded(insn: AbstractInsnNode, value: BasicValue?): BasicValue? =
|
||||||
when (insn.getOpcode()) {
|
when (insn.opcode) {
|
||||||
Opcodes.ANEWARRAY, Opcodes.NEWARRAY, Opcodes.LDC, Opcodes.NEW -> NotNullBasicValue(value)
|
Opcodes.ANEWARRAY, Opcodes.NEWARRAY, Opcodes.LDC, Opcodes.NEW -> NotNullBasicValue(value)
|
||||||
else -> value
|
else -> value
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -25,15 +25,15 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public open class MethodAnalyzer<V : Value>(
|
open class MethodAnalyzer<V : Value>(
|
||||||
public val owner: String,
|
val owner: String,
|
||||||
public val method: MethodNode,
|
val method: MethodNode,
|
||||||
protected val interpreter: Interpreter<V>
|
protected val interpreter: Interpreter<V>
|
||||||
) {
|
) {
|
||||||
public val instructions: InsnList = method.instructions
|
val instructions: InsnList = method.instructions
|
||||||
public val nInsns: Int = instructions.size()
|
val nInsns: Int = instructions.size()
|
||||||
|
|
||||||
public val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
|
val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
|
||||||
|
|
||||||
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
|
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
|
||||||
private val queued: BooleanArray = BooleanArray(nInsns)
|
private val queued: BooleanArray = BooleanArray(nInsns)
|
||||||
@@ -45,7 +45,7 @@ public open class MethodAnalyzer<V : Value>(
|
|||||||
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
|
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
|
||||||
|
|
||||||
protected open fun newFrame(src: Frame<out V>): Frame<V> {
|
protected open fun newFrame(src: Frame<out V>): Frame<V> {
|
||||||
val frame = newFrame(src.getLocals(), src.getMaxStackSize())
|
val frame = newFrame(src.locals, src.maxStackSize)
|
||||||
frame.init(src)
|
frame.init(src)
|
||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ public open class MethodAnalyzer<V : Value>(
|
|||||||
protected open fun visitControlFlowExceptionEdge(insn: Int, tcb: TryCatchBlockNode): Boolean =
|
protected open fun visitControlFlowExceptionEdge(insn: Int, tcb: TryCatchBlockNode): Boolean =
|
||||||
visitControlFlowExceptionEdge(insn, instructions.indexOf(tcb.handler))
|
visitControlFlowExceptionEdge(insn, instructions.indexOf(tcb.handler))
|
||||||
|
|
||||||
public fun analyze(): Array<Frame<V>?> {
|
fun analyze(): Array<Frame<V>?> {
|
||||||
if (nInsns == 0) return frames
|
if (nInsns == 0) return frames
|
||||||
|
|
||||||
checkAssertions()
|
checkAssertions()
|
||||||
@@ -75,8 +75,8 @@ public open class MethodAnalyzer<V : Value>(
|
|||||||
|
|
||||||
val insnNode = method.instructions[insn]
|
val insnNode = method.instructions[insn]
|
||||||
try {
|
try {
|
||||||
val insnOpcode = insnNode.getOpcode()
|
val insnOpcode = insnNode.opcode
|
||||||
val insnType = insnNode.getType()
|
val insnType = insnNode.type
|
||||||
|
|
||||||
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
||||||
visitNopInsn(f, insn)
|
visitNopInsn(f, insn)
|
||||||
@@ -121,11 +121,11 @@ public open class MethodAnalyzer<V : Value>(
|
|||||||
return frames
|
return frames
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getFrame(insn: AbstractInsnNode): Frame<V>? =
|
fun getFrame(insn: AbstractInsnNode): Frame<V>? =
|
||||||
frames[instructions.indexOf(insn)]
|
frames[instructions.indexOf(insn)]
|
||||||
|
|
||||||
private fun checkAssertions() {
|
private fun checkAssertions() {
|
||||||
if (instructions.toArray().any { it.getOpcode() == Opcodes.JSR || it.getOpcode() == Opcodes.RET })
|
if (instructions.toArray().any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
|
||||||
throw AssertionError("Subroutines are deprecated since Java 6")
|
throw AssertionError("Subroutines are deprecated since Java 6")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ public open class MethodAnalyzer<V : Value>(
|
|||||||
}
|
}
|
||||||
for (arg in args) {
|
for (arg in args) {
|
||||||
current.setLocal(local++, interpreter.newValue(arg))
|
current.setLocal(local++, interpreter.newValue(arg))
|
||||||
if (arg.getSize() == 2) {
|
if (arg.size == 2) {
|
||||||
current.setLocal(local++, interpreter.newValue(null))
|
current.setLocal(local++, interpreter.newValue(null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,20 +21,20 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||||
|
|
||||||
val AbstractInsnNode.isMeaningful: Boolean get() =
|
val AbstractInsnNode.isMeaningful: Boolean get() =
|
||||||
when (this.getType()) {
|
when (this.type) {
|
||||||
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME -> false
|
AbstractInsnNode.LABEL, AbstractInsnNode.LINE, AbstractInsnNode.FRAME -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InsnSequence(val from: AbstractInsnNode, val to: AbstractInsnNode?) : Sequence<AbstractInsnNode> {
|
class InsnSequence(val from: AbstractInsnNode, val to: AbstractInsnNode?) : Sequence<AbstractInsnNode> {
|
||||||
public constructor(insnList: InsnList) : this(insnList.getFirst(), null)
|
constructor(insnList: InsnList) : this(insnList.first, null)
|
||||||
|
|
||||||
override fun iterator(): Iterator<AbstractInsnNode> {
|
override fun iterator(): Iterator<AbstractInsnNode> {
|
||||||
return object : Iterator<AbstractInsnNode> {
|
return object : Iterator<AbstractInsnNode> {
|
||||||
var current: AbstractInsnNode? = from
|
var current: AbstractInsnNode? = from
|
||||||
override fun next(): AbstractInsnNode {
|
override fun next(): AbstractInsnNode {
|
||||||
val result = current
|
val result = current
|
||||||
current = current!!.getNext()
|
current = current!!.next
|
||||||
return result!!
|
return result!!
|
||||||
}
|
}
|
||||||
override fun hasNext() = current != to
|
override fun hasNext() = current != to
|
||||||
@@ -58,11 +58,11 @@ fun MethodNode.prepareForEmitting() {
|
|||||||
|
|
||||||
// We should remove linenumbers after last meaningful instruction
|
// We should remove linenumbers after last meaningful instruction
|
||||||
// because they point to index of non-existing instruction and it leads to VerifyError
|
// because they point to index of non-existing instruction and it leads to VerifyError
|
||||||
var current = instructions.getLast()
|
var current = instructions.last
|
||||||
while (!current.isMeaningful) {
|
while (!current.isMeaningful) {
|
||||||
val prev = current.getPrevious()
|
val prev = current.previous
|
||||||
|
|
||||||
if (current.getType() == AbstractInsnNode.LINE) {
|
if (current.type == AbstractInsnNode.LINE) {
|
||||||
instructions.remove(current)
|
instructions.remove(current)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ fun MethodNode.prepareForEmitting() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class BasicValueWrapper(val wrappedValue: BasicValue?) : BasicValue(wrappedValue?.getType()) {
|
abstract class BasicValueWrapper(val wrappedValue: BasicValue?) : BasicValue(wrappedValue?.type) {
|
||||||
val basicValue: BasicValue? get() = (wrappedValue as? BasicValueWrapper)?.basicValue ?: wrappedValue
|
val basicValue: BasicValue? get() = (wrappedValue as? BasicValueWrapper)?.basicValue ?: wrappedValue
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@@ -79,23 +79,23 @@ abstract class BasicValueWrapper(val wrappedValue: BasicValue?) : BasicValue(wra
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun AbstractInsnNode.findNextOrNull(predicate: (AbstractInsnNode) -> Boolean): AbstractInsnNode? {
|
inline fun AbstractInsnNode.findNextOrNull(predicate: (AbstractInsnNode) -> Boolean): AbstractInsnNode? {
|
||||||
var finger = this.getNext()
|
var finger = this.next
|
||||||
while (finger != null && !predicate(finger)) {
|
while (finger != null && !predicate(finger)) {
|
||||||
finger = finger.getNext()
|
finger = finger.next
|
||||||
}
|
}
|
||||||
return finger
|
return finger
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun AbstractInsnNode.findPreviousOrNull(predicate: (AbstractInsnNode) -> Boolean): AbstractInsnNode? {
|
inline fun AbstractInsnNode.findPreviousOrNull(predicate: (AbstractInsnNode) -> Boolean): AbstractInsnNode? {
|
||||||
var finger = this.getPrevious()
|
var finger = this.previous
|
||||||
while (finger != null && !predicate(finger)) {
|
while (finger != null && !predicate(finger)) {
|
||||||
finger = finger.getPrevious()
|
finger = finger.previous
|
||||||
}
|
}
|
||||||
return finger
|
return finger
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AbstractInsnNode.hasOpcode(): Boolean =
|
fun AbstractInsnNode.hasOpcode(): Boolean =
|
||||||
getOpcode() >= 0
|
opcode >= 0
|
||||||
|
|
||||||
// See InstructionAdapter
|
// See InstructionAdapter
|
||||||
//
|
//
|
||||||
|
|||||||
+14
-14
@@ -40,31 +40,31 @@ internal class FixStackAnalyzer(
|
|||||||
val savedStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
|
val savedStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
|
||||||
var maxExtraStackSize = 0; private set
|
var maxExtraStackSize = 0; private set
|
||||||
|
|
||||||
protected override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean {
|
override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean {
|
||||||
val insnNode = instructions[insn]
|
val insnNode = instructions[insn]
|
||||||
return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode))
|
return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> =
|
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> =
|
||||||
FixStackFrame(nLocals, nStack)
|
FixStackFrame(nLocals, nStack)
|
||||||
|
|
||||||
private fun indexOf(node: AbstractInsnNode) = method.instructions.indexOf(node)
|
private fun indexOf(node: AbstractInsnNode) = method.instructions.indexOf(node)
|
||||||
|
|
||||||
public inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<BasicValue>(nLocals, nStack) {
|
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<BasicValue>(nLocals, nStack) {
|
||||||
val extraStack = Stack<BasicValue>()
|
val extraStack = Stack<BasicValue>()
|
||||||
|
|
||||||
public override fun init(src: Frame<out BasicValue>): Frame<BasicValue> {
|
override fun init(src: Frame<out BasicValue>): Frame<BasicValue> {
|
||||||
extraStack.clear()
|
extraStack.clear()
|
||||||
extraStack.addAll((src as FixStackFrame).extraStack)
|
extraStack.addAll((src as FixStackFrame).extraStack)
|
||||||
return super.init(src)
|
return super.init(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun clearStack() {
|
override fun clearStack() {
|
||||||
extraStack.clear()
|
extraStack.clear()
|
||||||
super.clearStack()
|
super.clearStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
|
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
|
||||||
when {
|
when {
|
||||||
PseudoInsn.SAVE_STACK_BEFORE_TRY.isa(insn) ->
|
PseudoInsn.SAVE_STACK_BEFORE_TRY.isa(insn) ->
|
||||||
executeSaveStackBeforeTry(insn)
|
executeSaveStackBeforeTry(insn)
|
||||||
@@ -83,15 +83,15 @@ internal class FixStackAnalyzer(
|
|||||||
super.execute(insn, interpreter)
|
super.execute(insn, interpreter)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getStackContent(): List<BasicValue> {
|
fun getStackContent(): List<BasicValue> {
|
||||||
val savedStack = arrayListOf<BasicValue>()
|
val savedStack = arrayListOf<BasicValue>()
|
||||||
IntRange(0, super.getStackSize() - 1).mapTo(savedStack) { super.getStack(it) }
|
IntRange(0, super.getStackSize() - 1).mapTo(savedStack) { super.getStack(it) }
|
||||||
savedStack.addAll(extraStack)
|
savedStack.addAll(extraStack)
|
||||||
return savedStack
|
return savedStack
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun push(value: BasicValue) {
|
override fun push(value: BasicValue) {
|
||||||
if (super.getStackSize() < getMaxStackSize()) {
|
if (super.getStackSize() < maxStackSize) {
|
||||||
super.push(value)
|
super.push(value)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -100,11 +100,11 @@ internal class FixStackAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun pushAll(values: Collection<BasicValue>) {
|
fun pushAll(values: Collection<BasicValue>) {
|
||||||
values.forEach { push(it) }
|
values.forEach { push(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun pop(): BasicValue {
|
override fun pop(): BasicValue {
|
||||||
if (extraStack.isNotEmpty()) {
|
if (extraStack.isNotEmpty()) {
|
||||||
return extraStack.pop()
|
return extraStack.pop()
|
||||||
}
|
}
|
||||||
@@ -113,12 +113,12 @@ internal class FixStackAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getStack(i: Int): BasicValue {
|
override fun getStack(i: Int): BasicValue {
|
||||||
if (i < super.getMaxStackSize()) {
|
if (i < super.getMaxStackSize()) {
|
||||||
return super.getStack(i)
|
return super.getStack(i)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return extraStack[i - getMaxStackSize()]
|
return extraStack[i - maxStackSize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ internal class FixStackAnalyzer(
|
|||||||
|
|
||||||
private fun FixStackFrame.executeAfterInlineCallMarker(insn: AbstractInsnNode) {
|
private fun FixStackFrame.executeAfterInlineCallMarker(insn: AbstractInsnNode) {
|
||||||
val beforeInlineMarker = context.openingInlineMethodMarker[insn]
|
val beforeInlineMarker = context.openingInlineMethodMarker[insn]
|
||||||
if (getStackSize() > 0) {
|
if (stackSize > 0) {
|
||||||
val returnValue = pop()
|
val returnValue = pop()
|
||||||
clearStack()
|
clearStack()
|
||||||
val savedValues = savedStacks[beforeInlineMarker]
|
val savedValues = savedStacks[beforeInlineMarker]
|
||||||
|
|||||||
+5
-5
@@ -77,23 +77,23 @@ internal class FixStackContext(val methodNode: MethodNode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun visitFixStackBeforeJump(insnNode: AbstractInsnNode) {
|
private fun visitFixStackBeforeJump(insnNode: AbstractInsnNode) {
|
||||||
val next = insnNode.getNext()
|
val next = insnNode.next
|
||||||
assert(next.getOpcode() == Opcodes.GOTO) { "${indexOf(insnNode)}: should be followed by GOTO" }
|
assert(next.opcode == Opcodes.GOTO) { "${indexOf(insnNode)}: should be followed by GOTO" }
|
||||||
breakContinueGotoNodes.add(next as JumpInsnNode)
|
breakContinueGotoNodes.add(next as JumpInsnNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitFakeAlwaysTrueIfeq(insnNode: AbstractInsnNode) {
|
private fun visitFakeAlwaysTrueIfeq(insnNode: AbstractInsnNode) {
|
||||||
assert(insnNode.getNext().getOpcode() == Opcodes.IFEQ) { "${indexOf(insnNode)}: should be followed by IFEQ" }
|
assert(insnNode.next.opcode == Opcodes.IFEQ) { "${indexOf(insnNode)}: should be followed by IFEQ" }
|
||||||
fakeAlwaysTrueIfeqMarkers.add(insnNode)
|
fakeAlwaysTrueIfeqMarkers.add(insnNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitFakeAlwaysFalseIfeq(insnNode: AbstractInsnNode) {
|
private fun visitFakeAlwaysFalseIfeq(insnNode: AbstractInsnNode) {
|
||||||
assert(insnNode.getNext().getOpcode() == Opcodes.IFEQ) { "${indexOf(insnNode)}: should be followed by IFEQ" }
|
assert(insnNode.next.opcode == Opcodes.IFEQ) { "${indexOf(insnNode)}: should be followed by IFEQ" }
|
||||||
fakeAlwaysFalseIfeqMarkers.add(insnNode)
|
fakeAlwaysFalseIfeqMarkers.add(insnNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visitSaveStackBeforeTry(insnNode: AbstractInsnNode) {
|
private fun visitSaveStackBeforeTry(insnNode: AbstractInsnNode) {
|
||||||
val tryStartLabel = insnNode.getNext()
|
val tryStartLabel = insnNode.next
|
||||||
assert(tryStartLabel is LabelNode) { "${indexOf(insnNode)}: save should be followed by a label" }
|
assert(tryStartLabel is LabelNode) { "${indexOf(insnNode)}: save should be followed by a label" }
|
||||||
saveStackNodesForTryStartLabel[tryStartLabel as LabelNode] = insnNode
|
saveStackNodesForTryStartLabel[tryStartLabel as LabelNode] = insnNode
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -24,8 +24,8 @@ import org.jetbrains.kotlin.codegen.pseudoInsns.parsePseudoInsnOrNull
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
public class FixStackMethodTransformer : MethodTransformer() {
|
class FixStackMethodTransformer : MethodTransformer() {
|
||||||
public override fun transform(internalClassName: String, methodNode: MethodNode) {
|
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||||
val context = FixStackContext(methodNode)
|
val context = FixStackContext(methodNode)
|
||||||
|
|
||||||
if (!context.hasAnyMarkers()) return
|
if (!context.hasAnyMarkers()) return
|
||||||
@@ -73,19 +73,19 @@ public class FixStackMethodTransformer : MethodTransformer() {
|
|||||||
val labelIndex = methodNode.instructions.indexOf(gotoNode.label)
|
val labelIndex = methodNode.instructions.indexOf(gotoNode.label)
|
||||||
|
|
||||||
val DEAD_CODE = -1 // Stack size is always non-negative
|
val DEAD_CODE = -1 // Stack size is always non-negative
|
||||||
val actualStackSize = analyzer.frames[gotoIndex]?.getStackSize() ?: DEAD_CODE
|
val actualStackSize = analyzer.frames[gotoIndex]?.stackSize ?: DEAD_CODE
|
||||||
val expectedStackSize = analyzer.frames[labelIndex]?.getStackSize() ?: DEAD_CODE
|
val expectedStackSize = analyzer.frames[labelIndex]?.stackSize ?: DEAD_CODE
|
||||||
|
|
||||||
if (actualStackSize != DEAD_CODE && expectedStackSize != DEAD_CODE) {
|
if (actualStackSize != DEAD_CODE && expectedStackSize != DEAD_CODE) {
|
||||||
assert(expectedStackSize <= actualStackSize) { "Label at $labelIndex, jump at $gotoIndex: stack underflow: $expectedStackSize > $actualStackSize" }
|
assert(expectedStackSize <= actualStackSize) { "Label at $labelIndex, jump at $gotoIndex: stack underflow: $expectedStackSize > $actualStackSize" }
|
||||||
val frame = analyzer.frames[gotoIndex]!!
|
val frame = analyzer.frames[gotoIndex]!!
|
||||||
actions.add({ replaceMarkerWithPops(methodNode, gotoNode.getPrevious(), expectedStackSize, frame) })
|
actions.add({ replaceMarkerWithPops(methodNode, gotoNode.previous, expectedStackSize, frame) })
|
||||||
}
|
}
|
||||||
else if (actualStackSize != DEAD_CODE && expectedStackSize == DEAD_CODE) {
|
else if (actualStackSize != DEAD_CODE && expectedStackSize == DEAD_CODE) {
|
||||||
throw AssertionError("Live jump $gotoIndex to dead label $labelIndex")
|
throw AssertionError("Live jump $gotoIndex to dead label $labelIndex")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val marker = gotoNode.getPrevious()
|
val marker = gotoNode.previous
|
||||||
actions.add({ methodNode.instructions.remove(marker) })
|
actions.add({ methodNode.instructions.remove(marker) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,8 +153,8 @@ public class FixStackMethodTransformer : MethodTransformer() {
|
|||||||
val savedStackDescriptor = localVariablesManager.getBeforeInlineDescriptor(inlineMarker)
|
val savedStackDescriptor = localVariablesManager.getBeforeInlineDescriptor(inlineMarker)
|
||||||
val afterInlineFrame = analyzer.getFrame(inlineMarker) as FixStackAnalyzer.FixStackFrame?
|
val afterInlineFrame = analyzer.getFrame(inlineMarker) as FixStackAnalyzer.FixStackFrame?
|
||||||
if (afterInlineFrame != null && savedStackDescriptor.isNotEmpty()) {
|
if (afterInlineFrame != null && savedStackDescriptor.isNotEmpty()) {
|
||||||
assert(afterInlineFrame.getStackSize() <= 1) { "Inline method should not leave more than 1 value on stack" }
|
assert(afterInlineFrame.stackSize <= 1) { "Inline method should not leave more than 1 value on stack" }
|
||||||
if (afterInlineFrame.getStackSize() == 1) {
|
if (afterInlineFrame.stackSize == 1) {
|
||||||
val afterInlineStackValues = afterInlineFrame.getStackContent()
|
val afterInlineStackValues = afterInlineFrame.getStackContent()
|
||||||
val returnValue = afterInlineStackValues.last()
|
val returnValue = afterInlineStackValues.last()
|
||||||
val returnValueLocalVarIndex = localVariablesManager.createReturnValueVariable(returnValue)
|
val returnValueLocalVarIndex = localVariablesManager.createReturnValueVariable(returnValue)
|
||||||
|
|||||||
+1
-1
@@ -91,7 +91,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
|
|||||||
|
|
||||||
fun createReturnValueVariable(returnValue: BasicValue): Int {
|
fun createReturnValueVariable(returnValue: BasicValue): Int {
|
||||||
val returnValueIndex = getFirstUnusedLocalVariableIndex()
|
val returnValueIndex = getFirstUnusedLocalVariableIndex()
|
||||||
updateMaxLocals(returnValueIndex + returnValue.getSize())
|
updateMaxLocals(returnValueIndex + returnValue.size)
|
||||||
return returnValueIndex
|
return returnValueIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+17
-17
@@ -26,13 +26,13 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
||||||
|
|
||||||
public inline fun InsnList.forEachPseudoInsn(block: (PseudoInsn, AbstractInsnNode) -> Unit) {
|
inline fun InsnList.forEachPseudoInsn(block: (PseudoInsn, AbstractInsnNode) -> Unit) {
|
||||||
InsnSequence(this).forEach { insn ->
|
InsnSequence(this).forEach { insn ->
|
||||||
parsePseudoInsnOrNull(insn)?.let { block(it, insn) }
|
parsePseudoInsnOrNull(insn)?.let { block(it, insn) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun InsnList.forEachInlineMarker(block: (String, MethodInsnNode) -> Unit) {
|
inline fun InsnList.forEachInlineMarker(block: (String, MethodInsnNode) -> Unit) {
|
||||||
InsnSequence(this).forEach { insn ->
|
InsnSequence(this).forEach { insn ->
|
||||||
if (InlineCodegenUtil.isInlineMarker(insn)) {
|
if (InlineCodegenUtil.isInlineMarker(insn)) {
|
||||||
val methodInsnNode = insn as MethodInsnNode
|
val methodInsnNode = insn as MethodInsnNode
|
||||||
@@ -41,15 +41,15 @@ public inline fun InsnList.forEachInlineMarker(block: (String, MethodInsnNode) -
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <V : Value> Frame<V>.top(): V? {
|
fun <V : Value> Frame<V>.top(): V? {
|
||||||
val stackSize = getStackSize()
|
val stackSize = stackSize
|
||||||
if (stackSize == 0)
|
if (stackSize == 0)
|
||||||
return null
|
return null
|
||||||
else
|
else
|
||||||
return getStack(stackSize - 1)
|
return getStack(stackSize - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun MethodNode.updateMaxLocals(newMaxLocals: Int) {
|
fun MethodNode.updateMaxLocals(newMaxLocals: Int) {
|
||||||
maxLocals = Math.max(maxLocals, newMaxLocals)
|
maxLocals = Math.max(maxLocals, newMaxLocals)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +57,10 @@ class SavedStackDescriptor(
|
|||||||
val savedValues: List<BasicValue>,
|
val savedValues: List<BasicValue>,
|
||||||
val firstLocalVarIndex: Int
|
val firstLocalVarIndex: Int
|
||||||
) {
|
) {
|
||||||
val savedValuesSize = savedValues.fold(0, { size, value -> size + value.getSize() })
|
val savedValuesSize = savedValues.fold(0, { size, value -> size + value.size })
|
||||||
val firstUnusedLocalVarIndex = firstLocalVarIndex + savedValuesSize
|
val firstUnusedLocalVarIndex = firstLocalVarIndex + savedValuesSize
|
||||||
|
|
||||||
public override fun toString(): String =
|
override fun toString(): String =
|
||||||
"@$firstLocalVarIndex: [$savedValues]"
|
"@$firstLocalVarIndex: [$savedValues]"
|
||||||
|
|
||||||
fun isNotEmpty(): Boolean = savedValues.isNotEmpty()
|
fun isNotEmpty(): Boolean = savedValues.isNotEmpty()
|
||||||
@@ -93,9 +93,9 @@ fun restoreStackWithReturnValue(
|
|||||||
returnValueLocalVarIndex: Int
|
returnValueLocalVarIndex: Int
|
||||||
) {
|
) {
|
||||||
with(methodNode.instructions) {
|
with(methodNode.instructions) {
|
||||||
insertBefore(nodeToReplace, VarInsnNode(returnValue.getType().getOpcode(Opcodes.ISTORE), returnValueLocalVarIndex))
|
insertBefore(nodeToReplace, VarInsnNode(returnValue.type.getOpcode(Opcodes.ISTORE), returnValueLocalVarIndex))
|
||||||
generateLoadInstructions(methodNode, nodeToReplace, savedStackDescriptor)
|
generateLoadInstructions(methodNode, nodeToReplace, savedStackDescriptor)
|
||||||
insertBefore(nodeToReplace, VarInsnNode(returnValue.getType().getOpcode(Opcodes.ILOAD), returnValueLocalVarIndex))
|
insertBefore(nodeToReplace, VarInsnNode(returnValue.type.getOpcode(Opcodes.ILOAD), returnValueLocalVarIndex))
|
||||||
remove(nodeToReplace)
|
remove(nodeToReplace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,22 +104,22 @@ fun generateLoadInstructions(methodNode: MethodNode, location: AbstractInsnNode,
|
|||||||
var localVarIndex = savedStackDescriptor.firstLocalVarIndex
|
var localVarIndex = savedStackDescriptor.firstLocalVarIndex
|
||||||
for (value in savedStackDescriptor.savedValues) {
|
for (value in savedStackDescriptor.savedValues) {
|
||||||
methodNode.instructions.insertBefore(location,
|
methodNode.instructions.insertBefore(location,
|
||||||
VarInsnNode(value.getType().getOpcode(Opcodes.ILOAD), localVarIndex))
|
VarInsnNode(value.type.getOpcode(Opcodes.ILOAD), localVarIndex))
|
||||||
localVarIndex += value.getSize()
|
localVarIndex += value.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateStoreInstructions(methodNode: MethodNode, location: AbstractInsnNode, savedStackDescriptor: SavedStackDescriptor) {
|
fun generateStoreInstructions(methodNode: MethodNode, location: AbstractInsnNode, savedStackDescriptor: SavedStackDescriptor) {
|
||||||
var localVarIndex = savedStackDescriptor.firstUnusedLocalVarIndex
|
var localVarIndex = savedStackDescriptor.firstUnusedLocalVarIndex
|
||||||
for (value in savedStackDescriptor.savedValues.asReversed()) {
|
for (value in savedStackDescriptor.savedValues.asReversed()) {
|
||||||
localVarIndex -= value.getSize()
|
localVarIndex -= value.size
|
||||||
methodNode.instructions.insertBefore(location,
|
methodNode.instructions.insertBefore(location,
|
||||||
VarInsnNode(value.getType().getOpcode(Opcodes.ISTORE), localVarIndex))
|
VarInsnNode(value.type.getOpcode(Opcodes.ISTORE), localVarIndex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPopInstruction(top: BasicValue) =
|
fun getPopInstruction(top: BasicValue) =
|
||||||
InsnNode(when (top.getSize()) {
|
InsnNode(when (top.size) {
|
||||||
1 -> Opcodes.POP
|
1 -> Opcodes.POP
|
||||||
2 -> Opcodes.POP2
|
2 -> Opcodes.POP2
|
||||||
else -> throw AssertionError("Unexpected value type size")
|
else -> throw AssertionError("Unexpected value type size")
|
||||||
@@ -127,14 +127,14 @@ fun getPopInstruction(top: BasicValue) =
|
|||||||
|
|
||||||
fun removeAlwaysFalseIfeq(methodNode: MethodNode, node: AbstractInsnNode) {
|
fun removeAlwaysFalseIfeq(methodNode: MethodNode, node: AbstractInsnNode) {
|
||||||
with (methodNode.instructions) {
|
with (methodNode.instructions) {
|
||||||
remove(node.getNext())
|
remove(node.next)
|
||||||
remove(node)
|
remove(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun replaceAlwaysTrueIfeqWithGoto(methodNode: MethodNode, node: AbstractInsnNode) {
|
fun replaceAlwaysTrueIfeqWithGoto(methodNode: MethodNode, node: AbstractInsnNode) {
|
||||||
with (methodNode.instructions) {
|
with (methodNode.instructions) {
|
||||||
val next = node.getNext() as JumpInsnNode
|
val next = node.next as JumpInsnNode
|
||||||
insertBefore(node, JumpInsnNode(Opcodes.GOTO, next.label))
|
insertBefore(node, JumpInsnNode(Opcodes.GOTO, next.label))
|
||||||
remove(node)
|
remove(node)
|
||||||
remove(next)
|
remove(next)
|
||||||
@@ -143,7 +143,7 @@ fun replaceAlwaysTrueIfeqWithGoto(methodNode: MethodNode, node: AbstractInsnNode
|
|||||||
|
|
||||||
fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, frame: Frame<BasicValue>) {
|
fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, frame: Frame<BasicValue>) {
|
||||||
with (methodNode.instructions) {
|
with (methodNode.instructions) {
|
||||||
while (frame.getStackSize() > expectedStackSize) {
|
while (frame.stackSize > expectedStackSize) {
|
||||||
val top = frame.pop()
|
val top = frame.pop()
|
||||||
insertBefore(node, getPopInstruction(top))
|
insertBefore(node, getPopInstruction(top))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||||
|
|
||||||
public val PSEUDO_INSN_CALL_OWNER: String = "kotlin/jvm/internal/\$PseudoInsn"
|
val PSEUDO_INSN_CALL_OWNER: String = "kotlin/jvm/internal/\$PseudoInsn"
|
||||||
|
|
||||||
public enum class PseudoInsn(val signature: String = "()V") {
|
enum class PseudoInsn(val signature: String = "()V") {
|
||||||
FIX_STACK_BEFORE_JUMP(),
|
FIX_STACK_BEFORE_JUMP(),
|
||||||
FAKE_ALWAYS_TRUE_IFEQ("()I"),
|
FAKE_ALWAYS_TRUE_IFEQ("()I"),
|
||||||
FAKE_ALWAYS_FALSE_IFEQ("()I"),
|
FAKE_ALWAYS_FALSE_IFEQ("()I"),
|
||||||
@@ -33,36 +33,36 @@ public enum class PseudoInsn(val signature: String = "()V") {
|
|||||||
RESTORE_STACK_IN_TRY_CATCH()
|
RESTORE_STACK_IN_TRY_CATCH()
|
||||||
;
|
;
|
||||||
|
|
||||||
public fun emit(iv: InstructionAdapter) {
|
fun emit(iv: InstructionAdapter) {
|
||||||
iv.invokestatic(PSEUDO_INSN_CALL_OWNER, toString(), signature, false)
|
iv.invokestatic(PSEUDO_INSN_CALL_OWNER, toString(), signature, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun createInsnNode(): MethodInsnNode =
|
fun createInsnNode(): MethodInsnNode =
|
||||||
MethodInsnNode(Opcodes.INVOKESTATIC, PSEUDO_INSN_CALL_OWNER, toString(), signature, false)
|
MethodInsnNode(Opcodes.INVOKESTATIC, PSEUDO_INSN_CALL_OWNER, toString(), signature, false)
|
||||||
|
|
||||||
public fun isa(node: AbstractInsnNode): Boolean =
|
fun isa(node: AbstractInsnNode): Boolean =
|
||||||
this == parsePseudoInsnOrNull(node)
|
this == parsePseudoInsnOrNull(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun isPseudoInsn(insn: AbstractInsnNode): Boolean =
|
fun isPseudoInsn(insn: AbstractInsnNode): Boolean =
|
||||||
insn is MethodInsnNode && insn.getOpcode() == Opcodes.INVOKESTATIC && insn.owner == PSEUDO_INSN_CALL_OWNER
|
insn is MethodInsnNode && insn.getOpcode() == Opcodes.INVOKESTATIC && insn.owner == PSEUDO_INSN_CALL_OWNER
|
||||||
|
|
||||||
public fun parsePseudoInsnOrNull(insn: AbstractInsnNode): PseudoInsn? =
|
fun parsePseudoInsnOrNull(insn: AbstractInsnNode): PseudoInsn? =
|
||||||
if (isPseudoInsn(insn))
|
if (isPseudoInsn(insn))
|
||||||
PseudoInsn.valueOf((insn as MethodInsnNode).name)
|
PseudoInsn.valueOf((insn as MethodInsnNode).name)
|
||||||
else null
|
else null
|
||||||
|
|
||||||
public fun InstructionAdapter.fixStackAndJump(label: Label) {
|
fun InstructionAdapter.fixStackAndJump(label: Label) {
|
||||||
PseudoInsn.FIX_STACK_BEFORE_JUMP.emit(this)
|
PseudoInsn.FIX_STACK_BEFORE_JUMP.emit(this)
|
||||||
this.goTo(label)
|
this.goTo(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun InstructionAdapter.fakeAlwaysTrueIfeq(label: Label) {
|
fun InstructionAdapter.fakeAlwaysTrueIfeq(label: Label) {
|
||||||
PseudoInsn.FAKE_ALWAYS_TRUE_IFEQ.emit(this)
|
PseudoInsn.FAKE_ALWAYS_TRUE_IFEQ.emit(this)
|
||||||
this.ifeq(label)
|
this.ifeq(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun InstructionAdapter.fakeAlwaysFalseIfeq(label: Label) {
|
fun InstructionAdapter.fakeAlwaysFalseIfeq(label: Label) {
|
||||||
PseudoInsn.FAKE_ALWAYS_FALSE_IFEQ.emit(this)
|
PseudoInsn.FAKE_ALWAYS_FALSE_IFEQ.emit(this)
|
||||||
this.ifeq(label)
|
this.ifeq(label)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import java.util.*
|
|||||||
|
|
||||||
// TODO: optimize by reordering records to minimize storage of 'range' fields
|
// TODO: optimize by reordering records to minimize storage of 'range' fields
|
||||||
class JvmStringTable(private val typeMapper: JetTypeMapper) : StringTable {
|
class JvmStringTable(private val typeMapper: JetTypeMapper) : StringTable {
|
||||||
public val strings = ArrayList<String>()
|
val strings = ArrayList<String>()
|
||||||
private val records = ArrayList<Record.Builder>()
|
private val records = ArrayList<Record.Builder>()
|
||||||
private val map = HashMap<String, Int>()
|
private val map = HashMap<String, Int>()
|
||||||
private val localNames = HashSet<Int>()
|
private val localNames = HashSet<Int>()
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper
|
||||||
|
|
||||||
public class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
|
class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
|
||||||
// We use empty BindingContext, because it is only used by JetTypeMapper for purposes irrelevant to the needs of this class
|
// We use empty BindingContext, because it is only used by JetTypeMapper for purposes irrelevant to the needs of this class
|
||||||
private val typeMapper: JetTypeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null, JvmAbi.DEFAULT_MODULE_NAME)
|
private val typeMapper: JetTypeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null, JvmAbi.DEFAULT_MODULE_NAME)
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -120,17 +120,17 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
|||||||
var ownNonFakeCount = 0
|
var ownNonFakeCount = 0
|
||||||
for (origin in origins) {
|
for (origin in origins) {
|
||||||
val member = origin.descriptor as? CallableMemberDescriptor?
|
val member = origin.descriptor as? CallableMemberDescriptor?
|
||||||
if (member != null && member.containingDeclaration == classOrigin.descriptor && member.getKind() != FAKE_OVERRIDE) {
|
if (member != null && member.containingDeclaration == classOrigin.descriptor && member.kind != FAKE_OVERRIDE) {
|
||||||
ownNonFakeCount++
|
ownNonFakeCount++
|
||||||
// If there's more than one real element, the clashing signature is already reported.
|
// If there's more than one real element, the clashing signature is already reported.
|
||||||
// Only clashes between fake overrides are interesting here
|
// Only clashes between fake overrides are interesting here
|
||||||
if (ownNonFakeCount > 1) continue@signatures
|
if (ownNonFakeCount > 1) continue@signatures
|
||||||
|
|
||||||
if (member.getKind() != DELEGATION) {
|
if (member.kind != DELEGATION) {
|
||||||
// Delegates don't have declarations in the code
|
// Delegates don't have declarations in the code
|
||||||
memberElement = origin.element ?: DescriptorToSourceUtils.descriptorToDeclaration(member)
|
memberElement = origin.element ?: DescriptorToSourceUtils.descriptorToDeclaration(member)
|
||||||
if (memberElement == null && member is PropertyAccessorDescriptor) {
|
if (memberElement == null && member is PropertyAccessorDescriptor) {
|
||||||
memberElement = DescriptorToSourceUtils.descriptorToDeclaration(member.getCorrespondingProperty())
|
memberElement = DescriptorToSourceUtils.descriptorToDeclaration(member.correspondingProperty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,18 +154,18 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
|||||||
|
|
||||||
fun processMember(member: DeclarationDescriptor?) {
|
fun processMember(member: DeclarationDescriptor?) {
|
||||||
// a member of super is not visible: no override
|
// a member of super is not visible: no override
|
||||||
if (member is DeclarationDescriptorWithVisibility && member.getVisibility() == Visibilities.INVISIBLE_FAKE) return
|
if (member is DeclarationDescriptorWithVisibility && member.visibility == Visibilities.INVISIBLE_FAKE) return
|
||||||
// if a signature clashes with a SAM-adapter or something like that, there's no harm
|
// if a signature clashes with a SAM-adapter or something like that, there's no harm
|
||||||
if (member is CallableMemberDescriptor && isOrOverridesSamAdapter(member)) return
|
if (member is CallableMemberDescriptor && isOrOverridesSamAdapter(member)) return
|
||||||
|
|
||||||
if (member is PropertyDescriptor) {
|
if (member is PropertyDescriptor) {
|
||||||
processMember(member.getGetter())
|
processMember(member.getter)
|
||||||
processMember(member.getSetter())
|
processMember(member.setter)
|
||||||
}
|
}
|
||||||
else if (member is FunctionDescriptor) {
|
else if (member is FunctionDescriptor) {
|
||||||
val methodSignature = typeMapper.mapSignature(member)
|
val methodSignature = typeMapper.mapSignature(member)
|
||||||
val rawSignature = RawSignature(
|
val rawSignature = RawSignature(
|
||||||
methodSignature.getAsmMethod().getName()!!, methodSignature.getAsmMethod().getDescriptor()!!, MemberKind.METHOD)
|
methodSignature.asmMethod.name!!, methodSignature.asmMethod.descriptor!!, MemberKind.METHOD)
|
||||||
groupedBySignature.putValue(rawSignature, OtherOrigin(member))
|
groupedBySignature.putValue(rawSignature, OtherOrigin(member))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
|||||||
private fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean {
|
private fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean {
|
||||||
if (descriptor is SamAdapterDescriptor<*>) return true
|
if (descriptor is SamAdapterDescriptor<*>) return true
|
||||||
|
|
||||||
return descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
return descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||||
&& descriptor.getOverriddenDescriptors().all { isOrOverridesSamAdapter(it) }
|
&& descriptor.overriddenDescriptors.all { isOrOverridesSamAdapter(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,40 +44,39 @@ import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
|||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
public class GenerationState @JvmOverloads constructor(
|
class GenerationState @JvmOverloads constructor(
|
||||||
public val project: Project,
|
val project: Project,
|
||||||
builderFactory: ClassBuilderFactory,
|
builderFactory: ClassBuilderFactory,
|
||||||
public val module: ModuleDescriptor,
|
val module: ModuleDescriptor,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
public val files: List<KtFile>,
|
val files: List<KtFile>,
|
||||||
disableCallAssertions: Boolean = true,
|
disableCallAssertions: Boolean = true,
|
||||||
disableParamAssertions: Boolean = true,
|
disableParamAssertions: Boolean = true,
|
||||||
public val generateDeclaredClassFilter: GenerationState.GenerateClassFilter = GenerationState.GenerateClassFilter.GENERATE_ALL,
|
val generateDeclaredClassFilter: GenerationState.GenerateClassFilter = GenerationState.GenerateClassFilter.GENERATE_ALL,
|
||||||
disableInline: Boolean = false,
|
disableInline: Boolean = false,
|
||||||
disableOptimization: Boolean = false,
|
disableOptimization: Boolean = false,
|
||||||
public val useTypeTableInSerializer: Boolean = false,
|
val useTypeTableInSerializer: Boolean = false,
|
||||||
public val packagesWithObsoleteParts: Collection<FqName> = emptySet(),
|
val packagesWithObsoleteParts: Collection<FqName> = emptySet(),
|
||||||
public val obsoleteMultifileClasses: Collection<FqName> = emptySet(),
|
val obsoleteMultifileClasses: Collection<FqName> = emptySet(),
|
||||||
// for PackageCodegen in incremental compilation mode
|
// for PackageCodegen in incremental compilation mode
|
||||||
public val targetId: TargetId? = null,
|
val targetId: TargetId? = null,
|
||||||
moduleName: String? = null,
|
moduleName: String? = null,
|
||||||
// 'outDirectory' is a hack to correctly determine if a compiled class is from the same module as the callee during
|
// 'outDirectory' is a hack to correctly determine if a compiled class is from the same module as the callee during
|
||||||
// partial compilation. Module chunks are treated as a single module.
|
// partial compilation. Module chunks are treated as a single module.
|
||||||
// TODO: get rid of it with the proper module infrastructure
|
// TODO: get rid of it with the proper module infrastructure
|
||||||
public val outDirectory: File? = null,
|
val outDirectory: File? = null,
|
||||||
public val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
|
val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
|
||||||
public val generateOpenMultifileClasses: Boolean = false,
|
val generateOpenMultifileClasses: Boolean = false,
|
||||||
public val progress: Progress = Progress.DEAF
|
val progress: Progress = Progress.DEAF
|
||||||
) {
|
) {
|
||||||
public abstract class GenerateClassFilter {
|
abstract class GenerateClassFilter {
|
||||||
public abstract fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean
|
abstract fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||||
public abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
|
abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||||
public abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
|
abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
|
||||||
public abstract fun shouldGenerateScript(script: KtScript): Boolean
|
abstract fun shouldGenerateScript(script: KtScript): Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField val GENERATE_ALL: GenerateClassFilter = object : GenerateClassFilter() {
|
||||||
public val GENERATE_ALL: GenerateClassFilter = object : GenerateClassFilter() {
|
|
||||||
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
||||||
|
|
||||||
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
||||||
@@ -89,7 +88,7 @@ public class GenerationState @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public val fileClassesProvider: CodegenFileClassesProvider = CodegenFileClassesProvider()
|
val fileClassesProvider: CodegenFileClassesProvider = CodegenFileClassesProvider()
|
||||||
|
|
||||||
private fun getIncrementalCacheForThisTarget() =
|
private fun getIncrementalCacheForThisTarget() =
|
||||||
if (incrementalCompilationComponents != null && targetId != null)
|
if (incrementalCompilationComponents != null && targetId != null)
|
||||||
@@ -100,47 +99,47 @@ public class GenerationState @JvmOverloads constructor(
|
|||||||
private val interceptedBuilderFactory: ClassBuilderFactory
|
private val interceptedBuilderFactory: ClassBuilderFactory
|
||||||
private var used = false
|
private var used = false
|
||||||
|
|
||||||
public val diagnostics: DiagnosticSink get() = extraJvmDiagnosticsTrace
|
val diagnostics: DiagnosticSink get() = extraJvmDiagnosticsTrace
|
||||||
public val collectedExtraJvmDiagnostics: Diagnostics = LazyJvmDiagnostics {
|
val collectedExtraJvmDiagnostics: Diagnostics = LazyJvmDiagnostics {
|
||||||
duplicateSignatureFactory.reportDiagnostics()
|
duplicateSignatureFactory.reportDiagnostics()
|
||||||
extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
public val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
|
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
|
||||||
public val classBuilderMode: ClassBuilderMode = builderFactory.getClassBuilderMode()
|
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
|
||||||
public val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState")
|
val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState")
|
||||||
public val bindingContext: BindingContext = bindingTrace.getBindingContext()
|
val bindingContext: BindingContext = bindingTrace.bindingContext
|
||||||
public val typeMapper: JetTypeMapper = JetTypeMapper(this.bindingContext, classBuilderMode, fileClassesProvider, getIncrementalCacheForThisTarget(), this.moduleName)
|
val typeMapper: JetTypeMapper = JetTypeMapper(this.bindingContext, classBuilderMode, fileClassesProvider, getIncrementalCacheForThisTarget(), this.moduleName)
|
||||||
public val intrinsics: IntrinsicMethods = IntrinsicMethods()
|
val intrinsics: IntrinsicMethods = IntrinsicMethods()
|
||||||
public val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
|
val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
|
||||||
public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
|
val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
|
||||||
public val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
|
val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
|
||||||
public val reflectionTypes: ReflectionTypes = ReflectionTypes(module)
|
val reflectionTypes: ReflectionTypes = ReflectionTypes(module)
|
||||||
public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes()
|
val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes()
|
||||||
public val factory: ClassFileFactory
|
val factory: ClassFileFactory
|
||||||
private val duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics
|
private val duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics
|
||||||
|
|
||||||
public val replSpecific = ForRepl()
|
val replSpecific = ForRepl()
|
||||||
|
|
||||||
//TODO: should be refactored out
|
//TODO: should be refactored out
|
||||||
public class ForRepl {
|
class ForRepl {
|
||||||
public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
|
var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
|
||||||
public var scriptResultFieldName: String? = null
|
var scriptResultFieldName: String? = null
|
||||||
public val shouldGenerateScriptResultValue: Boolean get() = scriptResultFieldName != null
|
val shouldGenerateScriptResultValue: Boolean get() = scriptResultFieldName != null
|
||||||
public var hasResult: Boolean = false
|
var hasResult: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
public val isCallAssertionsEnabled: Boolean = !disableCallAssertions
|
val isCallAssertionsEnabled: Boolean = !disableCallAssertions
|
||||||
@JvmName("isCallAssertionsEnabled") get
|
@JvmName("isCallAssertionsEnabled") get
|
||||||
|
|
||||||
public val isParamAssertionsEnabled: Boolean = !disableParamAssertions
|
val isParamAssertionsEnabled: Boolean = !disableParamAssertions
|
||||||
@JvmName("isParamAssertionsEnabled") get
|
@JvmName("isParamAssertionsEnabled") get
|
||||||
|
|
||||||
public val isInlineEnabled: Boolean = !disableInline
|
val isInlineEnabled: Boolean = !disableInline
|
||||||
@JvmName("isInlineEnabled") get
|
@JvmName("isInlineEnabled") get
|
||||||
|
|
||||||
|
|
||||||
public val rootContext: CodegenContext<*> = RootContext(this)
|
val rootContext: CodegenContext<*> = RootContext(this)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization)
|
val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization)
|
||||||
@@ -162,7 +161,7 @@ public class GenerationState @JvmOverloads constructor(
|
|||||||
this.factory = ClassFileFactory(this, interceptedBuilderFactory)
|
this.factory = ClassFileFactory(this, interceptedBuilderFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun beforeCompile() {
|
fun beforeCompile() {
|
||||||
markUsed()
|
markUsed()
|
||||||
|
|
||||||
CodegenBinding.initTrace(this)
|
CodegenBinding.initTrace(this)
|
||||||
@@ -174,7 +173,7 @@ public class GenerationState @JvmOverloads constructor(
|
|||||||
used = true
|
used = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun destroy() {
|
fun destroy() {
|
||||||
interceptedBuilderFactory.close()
|
interceptedBuilderFactory.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ private fun KotlinType.canHaveSubtypesIgnoringNullability(): Boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Variance): Variance {
|
fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Variance): Variance {
|
||||||
if (parameterVariance === Variance.INVARIANT) {
|
if (parameterVariance === Variance.INVARIANT) {
|
||||||
return projectionKind
|
return projectionKind
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -48,11 +48,11 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.DataOutputStream
|
import java.io.DataOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
public class BuiltInsSerializer(private val dependOnOldBuiltIns: Boolean) {
|
class BuiltInsSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||||
private var totalSize = 0
|
private var totalSize = 0
|
||||||
private var totalFiles = 0
|
private var totalFiles = 0
|
||||||
|
|
||||||
public fun serialize(
|
fun serialize(
|
||||||
destDir: File,
|
destDir: File,
|
||||||
srcDirs: List<File>,
|
srcDirs: List<File>,
|
||||||
extraClassPath: List<File>,
|
extraClassPath: List<File>,
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
|||||||
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
|
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
|
|
||||||
public class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
|
class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
|
||||||
override fun shouldUseTypeTable(): Boolean = true
|
override fun shouldUseTypeTable(): Boolean = true
|
||||||
|
|
||||||
override fun serializePackage(packageFragments: Collection<PackageFragmentDescriptor>, proto: ProtoBuf.Package.Builder) {
|
override fun serializePackage(packageFragments: Collection<PackageFragmentDescriptor>, proto: ProtoBuf.Package.Builder) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.common
|
package org.jetbrains.kotlin.cli.common
|
||||||
|
|
||||||
public val KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY = "kotlin.environment.keepalive"
|
val KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY = "kotlin.environment.keepalive"
|
||||||
|
|
||||||
|
|
||||||
fun String?.toBooleanLenient(): Boolean? = when (this?.toLowerCase()) {
|
fun String?.toBooleanLenient(): Boolean? = when (this?.toLowerCase()) {
|
||||||
|
|||||||
+7
-9
@@ -16,21 +16,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.common.messages
|
package org.jetbrains.kotlin.cli.common.messages
|
||||||
|
|
||||||
public data class CompilerMessageLocation private constructor(
|
data class CompilerMessageLocation private constructor(
|
||||||
public val path: String?,
|
val path: String?,
|
||||||
public val line: Int,
|
val line: Int,
|
||||||
public val column: Int,
|
val column: Int,
|
||||||
public val lineContent: String?
|
val lineContent: String?
|
||||||
) {
|
) {
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
path + (if (line != -1 || column != -1) " ($line:$column)" else "")
|
path + (if (line != -1 || column != -1) " ($line:$column)" else "")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField val NO_LOCATION: CompilerMessageLocation = CompilerMessageLocation(null, -1, -1, null)
|
||||||
public val NO_LOCATION: CompilerMessageLocation = CompilerMessageLocation(null, -1, -1, null)
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun create(
|
||||||
public fun create(
|
|
||||||
path: String?,
|
path: String?,
|
||||||
line: Int,
|
line: Int,
|
||||||
column: Int,
|
column: Int,
|
||||||
|
|||||||
+5
-5
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.modules.Module
|
|||||||
import org.jetbrains.kotlin.modules.JavaRootPath
|
import org.jetbrains.kotlin.modules.JavaRootPath
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class ModuleBuilder(
|
class ModuleBuilder(
|
||||||
private val name: String,
|
private val name: String,
|
||||||
private val outputDir: String,
|
private val outputDir: String,
|
||||||
private val type: String
|
private val type: String
|
||||||
@@ -30,19 +30,19 @@ public class ModuleBuilder(
|
|||||||
private val javaSourceRoots = ArrayList<JavaRootPath>()
|
private val javaSourceRoots = ArrayList<JavaRootPath>()
|
||||||
private val friendDirs = ArrayList<String>()
|
private val friendDirs = ArrayList<String>()
|
||||||
|
|
||||||
public fun addSourceFiles(pattern: String) {
|
fun addSourceFiles(pattern: String) {
|
||||||
sourceFiles.add(pattern)
|
sourceFiles.add(pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addClasspathEntry(name: String) {
|
fun addClasspathEntry(name: String) {
|
||||||
classpathRoots.add(name)
|
classpathRoots.add(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addJavaSourceRoot(rootPath: JavaRootPath) {
|
fun addJavaSourceRoot(rootPath: JavaRootPath) {
|
||||||
javaSourceRoots.add(rootPath)
|
javaSourceRoots.add(rootPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addFriendDir(friendDir: String) {
|
fun addFriendDir(friendDir: String) {
|
||||||
friendDirs.add(friendDir)
|
friendDirs.add(friendDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.io.File
|
|||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public object Main {
|
object Main {
|
||||||
private val KOTLIN_HOME: File
|
private val KOTLIN_HOME: File
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -99,8 +99,7 @@ public object Main {
|
|||||||
runner.run(classpath, arguments)
|
runner.run(classpath, arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun main(args: Array<String>) {
|
||||||
public fun main(args: Array<String>) {
|
|
||||||
try {
|
try {
|
||||||
run(args)
|
run(args)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
|||||||
/**
|
/**
|
||||||
* This class behaviour is the same as [MessageCollector.report] in [AnalyzerWithCompilerReport.reportDiagnostic].
|
* This class behaviour is the same as [MessageCollector.report] in [AnalyzerWithCompilerReport.reportDiagnostic].
|
||||||
*/
|
*/
|
||||||
public class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
|
class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
|
||||||
|
|
||||||
public interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
||||||
|
|
||||||
val messageCollector: MessageCollector
|
val messageCollector: MessageCollector
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -19,6 +19,6 @@ package org.jetbrains.kotlin.cli.common.messages
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
|
||||||
public interface DiagnosticMessageReporter {
|
interface DiagnosticMessageReporter {
|
||||||
fun report(diagnostic: Diagnostic, file: PsiFile, render: String)
|
fun report(diagnostic: Diagnostic, file: PsiFile, render: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
|
||||||
public fun OutputFileCollection.writeAll(outputDir: File, report: (sources: List<File>, output: File) -> Unit) {
|
fun OutputFileCollection.writeAll(outputDir: File, report: (sources: List<File>, output: File) -> Unit) {
|
||||||
for (file in asList()) {
|
for (file in asList()) {
|
||||||
val sources = file.sourceFiles
|
val sources = file.sourceFiles
|
||||||
val output = File(outputDir, file.relativePath)
|
val output = File(outputDir, file.relativePath)
|
||||||
@@ -35,11 +35,11 @@ public fun OutputFileCollection.writeAll(outputDir: File, report: (sources: List
|
|||||||
|
|
||||||
private val REPORT_NOTHING = { sources: List<File>, output: File -> }
|
private val REPORT_NOTHING = { sources: List<File>, output: File -> }
|
||||||
|
|
||||||
public fun OutputFileCollection.writeAllTo(outputDir: File) {
|
fun OutputFileCollection.writeAllTo(outputDir: File) {
|
||||||
writeAll(outputDir, REPORT_NOTHING)
|
writeAll(outputDir, REPORT_NOTHING)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun OutputFileCollection.writeAll(outputDir: File, messageCollector: MessageCollector) {
|
fun OutputFileCollection.writeAll(outputDir: File, messageCollector: MessageCollector) {
|
||||||
writeAll(outputDir) { sources, output ->
|
writeAll(outputDir) { sources, output ->
|
||||||
messageCollector.report(CompilerMessageSeverity.OUTPUT, OutputMessageUtil.formatOutputMessage(sources, output), CompilerMessageLocation.NO_LOCATION)
|
messageCollector.report(CompilerMessageSeverity.OUTPUT, OutputMessageUtil.formatOutputMessage(sources, output), CompilerMessageLocation.NO_LOCATION)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import java.io.File
|
|||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||||
|
|
||||||
override fun doExecute(arguments: K2JVMCompilerArguments, services: Services, messageCollector: MessageCollector, rootDisposable: Disposable): ExitCode {
|
override fun doExecute(arguments: K2JVMCompilerArguments, services: Services, messageCollector: MessageCollector, rootDisposable: Disposable): ExitCode {
|
||||||
val messageSeverityCollector = MessageSeverityCollector(messageCollector)
|
val messageSeverityCollector = MessageSeverityCollector(messageCollector)
|
||||||
@@ -54,7 +54,7 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
else
|
else
|
||||||
PathUtil.getKotlinPathsForCompiler()
|
PathUtil.getKotlinPathsForCompiler()
|
||||||
|
|
||||||
messageSeverityCollector.report(CompilerMessageSeverity.LOGGING, "Using Kotlin home directory " + paths.getHomePath(), CompilerMessageLocation.NO_LOCATION)
|
messageSeverityCollector.report(CompilerMessageSeverity.LOGGING, "Using Kotlin home directory " + paths.homePath, CompilerMessageLocation.NO_LOCATION)
|
||||||
PerformanceCounter.setTimeCounterEnabled(arguments.reportPerf);
|
PerformanceCounter.setTimeCounterEnabled(arguments.reportPerf);
|
||||||
|
|
||||||
val configuration = CompilerConfiguration()
|
val configuration = CompilerConfiguration()
|
||||||
@@ -108,7 +108,7 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
for (arg in arguments.freeArgs) {
|
for (arg in arguments.freeArgs) {
|
||||||
configuration.addKotlinSourceRoot(arg)
|
configuration.addKotlinSourceRoot(arg)
|
||||||
val file = File(arg)
|
val file = File(arg)
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory) {
|
||||||
configuration.addJavaSourceRoot(file)
|
configuration.addJavaSourceRoot(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,14 +159,14 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
messageSeverityCollector.report(CompilerMessageSeverity.WARNING, "The '-d' option with a directory destination is ignored because '-module' is specified", CompilerMessageLocation.NO_LOCATION)
|
messageSeverityCollector.report(CompilerMessageSeverity.WARNING, "The '-d' option with a directory destination is ignored because '-module' is specified", CompilerMessageLocation.NO_LOCATION)
|
||||||
}
|
}
|
||||||
|
|
||||||
val directory = File(arguments.module).getAbsoluteFile().getParentFile()
|
val directory = File(arguments.module).absoluteFile.parentFile
|
||||||
|
|
||||||
val compilerConfiguration = KotlinToJVMBytecodeCompiler.createCompilerConfiguration(configuration, moduleScript.getModules(), directory)
|
val compilerConfiguration = KotlinToJVMBytecodeCompiler.createCompilerConfiguration(configuration, moduleScript.modules, directory)
|
||||||
environment = createCoreEnvironment(rootDisposable, compilerConfiguration)
|
environment = createCoreEnvironment(rootDisposable, compilerConfiguration)
|
||||||
|
|
||||||
if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) return COMPILATION_ERROR
|
if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) return COMPILATION_ERROR
|
||||||
|
|
||||||
KotlinToJVMBytecodeCompiler.compileModules(environment, configuration, moduleScript.getModules(), directory, jar, friendPaths, arguments.includeRuntime)
|
KotlinToJVMBytecodeCompiler.compileModules(environment, configuration, moduleScript.modules, directory, jar, friendPaths, arguments.includeRuntime)
|
||||||
}
|
}
|
||||||
else if (arguments.script) {
|
else if (arguments.script) {
|
||||||
val scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size)
|
val scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size)
|
||||||
@@ -200,7 +200,7 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
return OK
|
return OK
|
||||||
}
|
}
|
||||||
catch (e: CompilationException) {
|
catch (e: CompilationException) {
|
||||||
messageSeverityCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.getElement()))
|
messageSeverityCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element))
|
||||||
return INTERNAL_ERROR
|
return INTERNAL_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,18 +235,17 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
private var elapsedJITTime = 0L
|
private var elapsedJITTime = 0L
|
||||||
private var shouldReportPerf = true
|
private var shouldReportPerf = true
|
||||||
|
|
||||||
public fun resetInitStartTime() {
|
fun resetInitStartTime() {
|
||||||
if (initStartNanos == 0L) {
|
if (initStartNanos == 0L) {
|
||||||
initStartNanos = System.nanoTime()
|
initStartNanos = System.nanoTime()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun main(args: Array<String>) {
|
||||||
public fun main(args: Array<String>) {
|
|
||||||
CLICompiler.doMain(K2JVMCompiler(), args)
|
CLICompiler.doMain(K2JVMCompiler(), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun reportPerf(configuration: CompilerConfiguration, message: String) {
|
fun reportPerf(configuration: CompilerConfiguration, message: String) {
|
||||||
if (!shouldReportPerf) return
|
if (!shouldReportPerf) return
|
||||||
|
|
||||||
val collector = configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
|
val collector = configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
|
||||||
@@ -255,17 +254,17 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
|
|
||||||
fun reportGCTime(configuration: CompilerConfiguration) {
|
fun reportGCTime(configuration: CompilerConfiguration) {
|
||||||
ManagementFactory.getGarbageCollectorMXBeans().forEach {
|
ManagementFactory.getGarbageCollectorMXBeans().forEach {
|
||||||
val currentTime = it.getCollectionTime()
|
val currentTime = it.collectionTime
|
||||||
val elapsedTime = elapsedGCTime.getOrElse(it.getName()) { 0 }
|
val elapsedTime = elapsedGCTime.getOrElse(it.name) { 0 }
|
||||||
val time = currentTime - elapsedTime
|
val time = currentTime - elapsedTime
|
||||||
reportPerf(configuration, "GC time for ${it.getName()} is $time ms")
|
reportPerf(configuration, "GC time for ${it.name} is $time ms")
|
||||||
elapsedGCTime[it.getName()] = currentTime
|
elapsedGCTime[it.name] = currentTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportCompilationTime(configuration: CompilerConfiguration) {
|
fun reportCompilationTime(configuration: CompilerConfiguration) {
|
||||||
val bean = ManagementFactory.getCompilationMXBean() ?: return
|
val bean = ManagementFactory.getCompilationMXBean() ?: return
|
||||||
val currentTime = bean.getTotalCompilationTime()
|
val currentTime = bean.totalCompilationTime
|
||||||
reportPerf(configuration, "JIT time is ${currentTime - elapsedJITTime} ms")
|
reportPerf(configuration, "JIT time is ${currentTime - elapsedJITTime} ms")
|
||||||
elapsedJITTime = currentTime
|
elapsedJITTime = currentTime
|
||||||
}
|
}
|
||||||
@@ -284,7 +283,7 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
classpath.addAll(arguments.classpath.split(File.pathSeparatorChar).map { File(it) })
|
classpath.addAll(arguments.classpath.split(File.pathSeparatorChar).map { File(it) })
|
||||||
}
|
}
|
||||||
if (!arguments.noStdlib) {
|
if (!arguments.noStdlib) {
|
||||||
classpath.add(paths.getRuntimePath())
|
classpath.add(paths.runtimePath)
|
||||||
}
|
}
|
||||||
return classpath
|
return classpath
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.net.URLClassLoader
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
public object PluginCliParser {
|
object PluginCliParser {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun loadPlugins(arguments: CommonCompilerArguments, configuration: CompilerConfiguration) {
|
fun loadPlugins(arguments: CommonCompilerArguments, configuration: CompilerConfiguration) {
|
||||||
@@ -35,7 +35,7 @@ public object PluginCliParser {
|
|||||||
?.map { File(it).toURI().toURL() }
|
?.map { File(it).toURI().toURL() }
|
||||||
?.toTypedArray()
|
?.toTypedArray()
|
||||||
?: arrayOf<URL>(),
|
?: arrayOf<URL>(),
|
||||||
javaClass.getClassLoader()
|
javaClass.classLoader
|
||||||
)
|
)
|
||||||
|
|
||||||
val componentRegistrars = ServiceLoader.load(ComponentRegistrar::class.java, classLoader).toArrayList()
|
val componentRegistrars = ServiceLoader.load(ComponentRegistrar::class.java, classLoader).toArrayList()
|
||||||
@@ -93,7 +93,7 @@ public object PluginCliParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PluginURLClassLoader(urls: Array<URL>, parent: ClassLoader) : ClassLoader(Thread.currentThread().getContextClassLoader()) {
|
private class PluginURLClassLoader(urls: Array<URL>, parent: ClassLoader) : ClassLoader(Thread.currentThread().contextClassLoader) {
|
||||||
private val childClassLoader: SelfThenParentURLClassLoader = SelfThenParentURLClassLoader(urls, parent)
|
private val childClassLoader: SelfThenParentURLClassLoader = SelfThenParentURLClassLoader(urls, parent)
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|||||||
+4
-4
@@ -62,7 +62,7 @@ import kotlin.properties.Delegates
|
|||||||
|
|
||||||
* To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses
|
* To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses
|
||||||
*/
|
*/
|
||||||
public class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSupport(), CodeAnalyzerInitializer {
|
class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSupport(), CodeAnalyzerInitializer {
|
||||||
private val psiManager = PsiManager.getInstance(project)
|
private val psiManager = PsiManager.getInstance(project)
|
||||||
private var bindingContext: BindingContext by Delegates.notNull()
|
private var bindingContext: BindingContext by Delegates.notNull()
|
||||||
private var module: ModuleDescriptor by Delegates.notNull()
|
private var module: ModuleDescriptor by Delegates.notNull()
|
||||||
@@ -172,7 +172,7 @@ public class CliLightClassGenerationSupport(project: Project) : LightClassGenera
|
|||||||
return NoScopeRecordCliBindingTrace()
|
return NoScopeRecordCliBindingTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NoScopeRecordCliBindingTrace : CliBindingTrace() {
|
class NoScopeRecordCliBindingTrace : CliBindingTrace() {
|
||||||
override fun <K, V> record(slice: WritableSlice<K, V>, key: K, value: V) {
|
override fun <K, V> record(slice: WritableSlice<K, V>, key: K, value: V) {
|
||||||
if (slice === BindingContext.LEXICAL_SCOPE) {
|
if (slice === BindingContext.LEXICAL_SCOPE) {
|
||||||
// In the compiler there's no need to keep scopes
|
// In the compiler there's no need to keep scopes
|
||||||
@@ -186,14 +186,14 @@ public class CliLightClassGenerationSupport(project: Project) : LightClassGenera
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class CliBindingTrace @TestOnly constructor() : BindingTraceContext() {
|
open class CliBindingTrace @TestOnly constructor() : BindingTraceContext() {
|
||||||
private var kotlinCodeAnalyzer: KotlinCodeAnalyzer? = null
|
private var kotlinCodeAnalyzer: KotlinCodeAnalyzer? = null
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return CliBindingTrace::class.java.name
|
return CliBindingTrace::class.java.name
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun setKotlinCodeAnalyzer(kotlinCodeAnalyzer: KotlinCodeAnalyzer) {
|
fun setKotlinCodeAnalyzer(kotlinCodeAnalyzer: KotlinCodeAnalyzer) {
|
||||||
this.kotlinCodeAnalyzer = kotlinCodeAnalyzer
|
this.kotlinCodeAnalyzer = kotlinCodeAnalyzer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClassFinder
|
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClassFinder
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
public class JvmCliVirtualFileFinder(private val index: JvmDependenciesIndex) : VirtualFileKotlinClassFinder() {
|
class JvmCliVirtualFileFinder(private val index: JvmDependenciesIndex) : VirtualFileKotlinClassFinder() {
|
||||||
|
|
||||||
override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? {
|
override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? {
|
||||||
val classFileName = classId.getRelativeClassName().asString().replace('.', '$')
|
val classFileName = classId.relativeClassName.asString().replace('.', '$')
|
||||||
return index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, rootType ->
|
return index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, rootType ->
|
||||||
dir.findChild("$classFileName.class")?.let {
|
dir.findChild("$classFileName.class")?.let {
|
||||||
if (it.isValid()) it else null
|
if (it.isValid) it else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user