mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-29 00:21:31 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22add1ee89 | ||
|
|
2ecc21b440 | ||
|
|
0113ccaad1 | ||
|
|
41141fbe23 | ||
|
|
1d076154b1 | ||
|
|
58d78011c0 | ||
|
|
b33ad0c528 | ||
|
|
6dbec92bfe | ||
|
|
bb57825d21 | ||
|
|
ddb50031d8 | ||
|
|
50dcd08cb5 | ||
|
|
df6298de39 | ||
|
|
a9c1e57230 | ||
|
|
378a964c2f | ||
|
|
170a0393f6 | ||
|
|
95d4dd4962 | ||
|
|
288248c964 |
2
.idea/ant.xml
generated
2
.idea/ant.xml
generated
@@ -3,7 +3,7 @@
|
||||
<component name="AntConfiguration">
|
||||
<buildFile url="file://$PROJECT_DIR$/compiler/frontend/buildLexer.xml" />
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml">
|
||||
<antCommandLine value="-J-XX:MaxPermSize=100m -J-ea" />
|
||||
<antCommandLine value="-J-XX:MaxPermSize=100m" />
|
||||
<maximumHeapSize value="1024" />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/update_dependencies.xml" />
|
||||
|
||||
1
.idea/dictionaries/Nikolay_Krasko.xml
generated
1
.idea/dictionaries/Nikolay_Krasko.xml
generated
@@ -2,7 +2,6 @@
|
||||
<dictionary name="Nikolay.Krasko">
|
||||
<words>
|
||||
<w>accessors</w>
|
||||
<w>fqname</w>
|
||||
<w>goto</w>
|
||||
<w>gradle</w>
|
||||
<w>intrinsics</w>
|
||||
|
||||
8
.idea/dictionaries/dzharkov.xml
generated
8
.idea/dictionaries/dzharkov.xml
generated
@@ -1,8 +0,0 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="dzharkov">
|
||||
<words>
|
||||
<w>checkcast</w>
|
||||
<w>insn</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
BIN
.idea/icon.png
generated
BIN
.idea/icon.png
generated
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
9
.idea/libraries/kotlin_reflect.xml
generated
9
.idea/libraries/kotlin_reflect.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="kotlin-reflect">
|
||||
<CLASSES>
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
3
.idea/libraries/kotlin_runtime.xml
generated
3
.idea/libraries/kotlin_runtime.xml
generated
@@ -2,12 +2,11 @@
|
||||
<library name="kotlin-runtime">
|
||||
<CLASSES>
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-runtime.jar!/" />
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="file://$PROJECT_DIR$/libraries/stdlib/src" />
|
||||
<root url="file://$PROJECT_DIR$/core/builtins/native" />
|
||||
<root url="file://$PROJECT_DIR$/core/builtins/src" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
13
.idea/libraries/kotlin_test.xml
generated
13
.idea/libraries/kotlin_test.xml
generated
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="kotlin-test">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/bootstrap-compiler/Kotlin/kotlinc/lib/kotlin-test.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/shared/src/main/kotlin" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/shared/src/main/kotlin.jvm" />
|
||||
<root url="file://$PROJECT_DIR$/libraries/kotlin.test/junit/src/main/kotlin" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
3
.idea/modules.xml
generated
3
.idea/modules.xml
generated
@@ -40,7 +40,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-core/idea-core.iml" filepath="$PROJECT_DIR$/idea/idea-core/idea-core.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" filepath="$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" filepath="$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea-runner/idea-runner.iml" filepath="$PROJECT_DIR$/idea-runner/idea-runner.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" filepath="$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" filepath="$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" group="compiler/cli" />
|
||||
@@ -62,7 +62,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/core/reflection.jvm/reflection.jvm.iml" filepath="$PROJECT_DIR$/core/reflection.jvm/reflection.jvm.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" filepath="$PROJECT_DIR$/core/runtime.jvm/runtime.jvm.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/serialization/serialization.iml" filepath="$PROJECT_DIR$/compiler/serialization/serialization.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/temp-jdk8/temp-jdk8.iml" filepath="$PROJECT_DIR$/temp-jdk8/temp-jdk8.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/util/util.iml" filepath="$PROJECT_DIR$/compiler/util/util.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/util.runtime/util.runtime.iml" filepath="$PROJECT_DIR$/core/util.runtime/util.runtime.iml" group="core" />
|
||||
</modules>
|
||||
|
||||
2
.idea/runConfigurations/IDEA__win_.xml
generated
2
.idea/runConfigurations/IDEA__win_.xml
generated
@@ -5,7 +5,7 @@
|
||||
<option name="VM_PARAMETERS" value="-Xmx800m -XX:ReservedCodeCacheSize=64m -XX:MaxPermSize=450m -XX:+HeapDumpOnOutOfMemoryError -ea -Didea.is.internal=true -Didea.debug.mode=true -Didea.system.path=../system-idea -Didea.config.path=../config-idea -Dapple.laf.useScreenMenuBar=true -Dapple.awt.graphics.UseQuartz=true -Dsun.io.useCanonCaches=false -Dplugin.path=$PROJECT_DIR$/out/artifacts/Kotlin -Dkotlin.internal.mode.enabled=true -Didea.additional.classpath=${JAVA_HOME}\lib\tools.jar,../idea-kotlin-runtime/kotlin-runtime.jar,../idea-kotlin-runtime/kotlin-reflect.jar" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/ideaSDK/bin" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="1.7" />
|
||||
<option name="ENABLE_SWING_INSPECTOR" value="false" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
|
||||
@@ -158,11 +158,11 @@
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-reflect.jar"/>
|
||||
|
||||
<print-file-size-statistic path="${kotlin-home}/lib" file-name="kotlin-jslib.jar"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="kotlin.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="builtins.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="builtins.meta.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="stdlib.js"/>
|
||||
<print-file-size-statistic path="${js.stdlib.output.dir}" file-name="stdlib.meta.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="kotlin.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="builtins.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="builtins.meta.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="stdlib.js"/>
|
||||
<print-file-size-statistic path="${output}" file-name="stdlib.meta.js"/>
|
||||
</target>
|
||||
|
||||
<target name="post_build" depends="zipArtifacts, revertTemplateFiles, printStatistics, remove_internal_artifacts, dont_remove_internal_artifacts"/>
|
||||
|
||||
@@ -88,12 +88,5 @@
|
||||
origin.version="${relay.origin.version}"
|
||||
plugin.subdir="BareKotlin"
|
||||
substituted.version="${relay.substitute.version}"/>
|
||||
|
||||
<substitudeVersionInPlugin
|
||||
plugin.jar.name="kotlin-android-extensions"
|
||||
plugin.path="${relay.plugins.dir}/kotlin-android-extensions-plugin-${relay.origin.version}.zip"
|
||||
origin.version="${relay.origin.version}"
|
||||
plugin.subdir="KotlinAndroidExtensions"
|
||||
substituted.version="${relay.substitute.version}"/>
|
||||
</target>
|
||||
</project>
|
||||
@@ -9,7 +9,6 @@
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="ant" level="project" />
|
||||
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||
<orderEntry type="library" name="kotlin-reflect" level="project" />
|
||||
<orderEntry type="module" module-name="preloader" />
|
||||
</component>
|
||||
</module>
|
||||
7
ant/src/org/jetbrains/jet/buildtools/ant/antlib.xml
Normal file
7
ant/src/org/jetbrains/jet/buildtools/ant/antlib.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<!-- NOTE: this Antlib is deprecated. Use org/jetbrains/kotlin/ant/antlib.xml instead -->
|
||||
<!-- TODO: delete this file -->
|
||||
<antlib>
|
||||
<taskdef name="kotlinc" classname="org.jetbrains.kotlin.ant.Kotlin2JvmTask"/>
|
||||
<taskdef name="kotlin2js" classname="org.jetbrains.kotlin.ant.Kotlin2JsTask"/>
|
||||
<typedef name="withKotlin" classname="org.jetbrains.kotlin.ant.KotlinCompilerAdapter"/>
|
||||
</antlib>
|
||||
@@ -70,7 +70,7 @@ class KotlinCompilerAdapter : Javac13() {
|
||||
// Javac13#execute passes everything in compileList to javac, which doesn't recognize .kt files
|
||||
val compileListForJavac = filterOutKotlinSources(compileList)
|
||||
|
||||
val hasKotlinFilesInSources = compileListForJavac.size < compileList.size
|
||||
val hasKotlinFilesInSources = compileListForJavac.size() < compileList.size()
|
||||
|
||||
if (hasKotlinFilesInSources) {
|
||||
kotlinc.execute()
|
||||
|
||||
@@ -54,7 +54,7 @@ public abstract class KotlinCompilerBaseTask : Task() {
|
||||
}
|
||||
|
||||
public fun setSrcRef(ref: Reference) {
|
||||
createSrc().refid = ref
|
||||
createSrc().setRefid(ref)
|
||||
}
|
||||
|
||||
public fun createCompilerArg(): Commandline.Argument {
|
||||
@@ -75,7 +75,7 @@ public abstract class KotlinCompilerBaseTask : Task() {
|
||||
if (verbose) args.add("-verbose")
|
||||
if (printVersion) args.add("-version")
|
||||
|
||||
args.addAll(additionalArguments.flatMap { it.parts.toList() })
|
||||
args.addAll(additionalArguments.flatMap { it.getParts().toList() })
|
||||
|
||||
fillSpecificArguments()
|
||||
}
|
||||
@@ -85,12 +85,12 @@ public abstract class KotlinCompilerBaseTask : Task() {
|
||||
|
||||
val compilerClass = KotlinAntTaskUtil.getOrCreateClassLoader().loadClass(compilerFqName)
|
||||
val compiler = compilerClass.newInstance()
|
||||
val exec = compilerClass.getMethod("execFullPathsInMessages", PrintStream::class.java, Array<String>::class.java)
|
||||
val exec = compilerClass.getMethod("execFullPathsInMessages", javaClass<PrintStream>(), javaClass<Array<String>>())
|
||||
|
||||
log("Compiling ${src!!.list().toList()} => [${output!!.canonicalPath}]");
|
||||
|
||||
val result = exec(compiler, System.err, args.toTypedArray())
|
||||
exitCode = (result as Enum<*>).ordinal
|
||||
exitCode = (result as Enum<*>).ordinal()
|
||||
|
||||
if (failOnError && exitCode != 0) {
|
||||
throw BuildException("Compile failed; see the compiler error output for details.")
|
||||
|
||||
57
build.xml
57
build.xml
@@ -12,10 +12,8 @@
|
||||
<property name="bootstrap.compiler.home" value="${bootstrap.home}/Kotlin/kotlinc"/>
|
||||
<property name="bootstrap.runtime" value="${bootstrap.compiler.home}/lib/kotlin-runtime.jar"/>
|
||||
<property name="bootstrap.reflect" value="${bootstrap.compiler.home}/lib/kotlin-reflect.jar"/>
|
||||
<property name="bootstrap.kotlin.test" value="${bootstrap.compiler.home}/lib/kotlin-test.jar" />
|
||||
|
||||
<property name="output" value="${basedir}/dist"/>
|
||||
<property name="js.stdlib.output.dir" value="${output}/js"/>
|
||||
<property name="intermediate-sources" value="out/src" />
|
||||
<property name="kotlin-home" value="${output}/kotlinc"/>
|
||||
<property name="build.number" value="snapshot"/>
|
||||
@@ -57,7 +55,6 @@
|
||||
|
||||
<path id="classpath">
|
||||
<file file="${bootstrap.runtime}"/>
|
||||
<file file="${bootstrap.kotlin.test}" />
|
||||
<file file="${bootstrap.reflect}"/>
|
||||
<fileset dir="${idea.sdk}" includes="core/*.jar"/>
|
||||
<pathelement location="${protobuf.jar}"/>
|
||||
@@ -180,33 +177,19 @@
|
||||
<sequential if:true="${bootstrap.or.local.build}">
|
||||
<copy file="${bootstrap.runtime}" tofile="${kotlin-home}/lib/kotlin-runtime-internal-bootstrap.jar"/>
|
||||
<copy file="${bootstrap.reflect}" tofile="${kotlin-home}/lib/kotlin-reflect-internal-bootstrap.jar"/>
|
||||
<copy file="${bootstrap.kotlin.test}" tofile="${kotlin-home}/lib/kotlin-test-internal-bootstrap.jar" failonerror="false"/>
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-reflect-internal-bootstrap.jar" update="true">
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="kotlin-runtime-internal-bootstrap.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
<jar destfile="${kotlin-home}/lib/kotlin-test-internal-bootstrap.jar" update="true">
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="kotlin-runtime-internal-bootstrap.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</sequential>
|
||||
|
||||
<sequential unless:true="${bootstrap.or.local.build}">
|
||||
<copy file="${bootstrap.runtime}" todir="${kotlin-home}/lib"/>
|
||||
<copy file="${bootstrap.reflect}" todir="${kotlin-home}/lib"/>
|
||||
<copy file="${bootstrap.kotlin.test}" todir="${kotlin-home}/lib"/>
|
||||
</sequential>
|
||||
</target>
|
||||
|
||||
<target name="copy-dist-to-bootstrap">
|
||||
<delete dir="${basedir}/dependencies/bootstrap-compiler/Kotlin/kotlinc" />
|
||||
<copy todir="${basedir}/dependencies/bootstrap-compiler/Kotlin/kotlinc">
|
||||
<fileset dir="${basedir}/dist/kotlinc" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="compiler-sources">
|
||||
<jar jarfile="${output}/kotlin-compiler-sources.jar">
|
||||
<!-- TODO How to convert it from pathset or dirset ? -->
|
||||
@@ -325,13 +308,13 @@
|
||||
|
||||
<kotlin-pp src="libraries/stdlib/src" output="${intermediate-sources}/stdlib/js" profile="JS" />
|
||||
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/${compiled.builtins.js}">
|
||||
<new-kotlin2js output="${output}/js/${compiled.builtins.js}">
|
||||
<src>
|
||||
<fileset refid="kotlin.builtin.files"/>
|
||||
</src>
|
||||
</new-kotlin2js>
|
||||
|
||||
<new-kotlin2js output="${js.stdlib.output.dir}/${compiled.stdlib.js}">
|
||||
<new-kotlin2js output="${output}/js/${compiled.stdlib.js}">
|
||||
<src>
|
||||
<resources refid="js.lib.files"/>
|
||||
</src>
|
||||
@@ -351,7 +334,7 @@
|
||||
prettyprint="true"
|
||||
languagein="ECMASCRIPT5_STRICT"
|
||||
warning="${warningLevel}"
|
||||
output="${js.stdlib.output.dir}/kotlin.js">
|
||||
output="${output}/js/kotlin.js">
|
||||
|
||||
<sources dir="${stdlib.js.dir}">
|
||||
<file name="kotlin_lib_ecma5.js"/>
|
||||
@@ -360,11 +343,11 @@
|
||||
<file name="long.js"/>
|
||||
</sources>
|
||||
|
||||
<sources dir="${js.stdlib.output.dir}">
|
||||
<sources dir="${output}/js">
|
||||
<file name="${compiled.builtins.js}"/>
|
||||
</sources>
|
||||
|
||||
<sources dir="${js.stdlib.output.dir}">
|
||||
<sources dir="${output}/js">
|
||||
<file name="${compiled.stdlib.js}"/>
|
||||
</sources>
|
||||
|
||||
@@ -379,7 +362,7 @@
|
||||
|
||||
<jar jarfile="${kotlin-home}/lib/kotlin-jslib.jar" duplicate="fail">
|
||||
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
|
||||
<zipfileset dir="${js.stdlib.output.dir}" prefix="">
|
||||
<zipfileset dir="${output}/js" prefix="">
|
||||
<include name="kotlin.js"/>
|
||||
<include name="${compiled.stdlib.meta.js}"/>
|
||||
<include name="stdlib/**"/>
|
||||
@@ -798,7 +781,7 @@
|
||||
</target>
|
||||
|
||||
<target name="stdlib">
|
||||
<new-kotlinc output="${output}/classes/stdlib" moduleName="kotlin-stdlib" additionalOptions="-Xmultifile-facades-open">
|
||||
<new-kotlinc output="${output}/classes/stdlib" moduleName="kotlin-stdlib">
|
||||
<src>
|
||||
<include name="libraries/stdlib/src"/>
|
||||
</src>
|
||||
@@ -808,20 +791,6 @@
|
||||
</new-kotlinc>
|
||||
</target>
|
||||
|
||||
<target name="kotlin.test">
|
||||
<new-kotlinc output="${output}/classes/kotlin.test" moduleName="kotlin-test">
|
||||
<src>
|
||||
<include name="libraries/kotlin.test/shared/src/main/kotlin" />
|
||||
<include name="libraries/kotlin.test/shared/src/main/kotlin.jvm" />
|
||||
<include name="libraries/kotlin.test/junit/src/main/kotlin" />
|
||||
</src>
|
||||
<class-path>
|
||||
<pathelement path="${output}/classes/builtins"/>
|
||||
<pathelement path="libraries/lib/junit-4.11.jar"/>
|
||||
</class-path>
|
||||
</new-kotlinc>
|
||||
</target>
|
||||
|
||||
<target name="core">
|
||||
<new-kotlinc output="${output}/classes/core" moduleName="kotlin-core">
|
||||
<src>
|
||||
@@ -966,23 +935,15 @@
|
||||
</pack-runtime-jar>
|
||||
</target>
|
||||
|
||||
<target name="pack-kotlin-test">
|
||||
<pack-runtime-jar jar-name="kotlin-test.jar" implementation-title="${manifest.impl.title.kotlin.test}">
|
||||
<jar-content>
|
||||
<fileset dir="${output}/classes/kotlin.test" includes="**/*" excludes="kotlin/internal/OnlyInputTypes*,kotlin/internal"/>
|
||||
</jar-content>
|
||||
</pack-runtime-jar>
|
||||
</target>
|
||||
|
||||
<target name="runtime"
|
||||
depends="builtins,stdlib,core,reflection,pack-runtime,pack-runtime-sources"/>
|
||||
|
||||
<target name="dist"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin.test,pack-kotlin-test,kotlin-js-stdlib,android-compiler-plugin,daemon-client"
|
||||
depends="clean,init,prepare-dist,preloader,runner,serialize-builtins,compiler,compiler-sources,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin-js-stdlib,android-compiler-plugin,daemon-client"
|
||||
description="Builds redistributables from sources"/>
|
||||
|
||||
<target name="dist-quick"
|
||||
depends="clean,init,prepare-dist,preloader,serialize-builtins,compiler-quick,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin.test,pack-kotlin-test,kotlin-js-stdlib,android-compiler-plugin"
|
||||
depends="clean,init,prepare-dist,preloader,serialize-builtins,compiler-quick,ant-tools,jdk-annotations,android-sdk-annotations,runtime,kotlin-js-stdlib,android-compiler-plugin"
|
||||
description="Builds everything, but classes are reused from project out dir, doesn't run proguard and javadoc"/>
|
||||
|
||||
<target name="dist-quick-compiler-only"
|
||||
|
||||
@@ -93,14 +93,14 @@ public class CodegenUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<FunctionDescriptor, FunctionDescriptor> getNonPrivateTraitMethods(ClassDescriptor descriptor) {
|
||||
public static Map<FunctionDescriptor, FunctionDescriptor> getTraitMethods(ClassDescriptor descriptor) {
|
||||
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>();
|
||||
for (DeclarationDescriptor declaration : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||
if (!(declaration instanceof CallableMemberDescriptor)) continue;
|
||||
|
||||
CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
|
||||
CallableMemberDescriptor traitMember = ImplKt.findTraitImplementation(inheritedMember);
|
||||
if (traitMember == null || Visibilities.isPrivate(traitMember.getVisibility())) continue;
|
||||
if (traitMember == null) continue;
|
||||
|
||||
assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
|
||||
|
||||
@@ -140,7 +140,7 @@ public class CodegenUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getSuperClassBySuperTypeListEntry(@NotNull KtSuperTypeListEntry specifier, @NotNull BindingContext bindingContext) {
|
||||
public static ClassDescriptor getSuperClassByDelegationSpecifier(@NotNull KtDelegationSpecifier specifier, @NotNull BindingContext bindingContext) {
|
||||
KotlinType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
assert superType != null : "superType should not be null: " + specifier.getText();
|
||||
|
||||
|
||||
@@ -31,43 +31,39 @@ public object CodegenUtilKt {
|
||||
|
||||
// class Foo : Bar by baz
|
||||
// descriptor = Foo
|
||||
// toInterface = Bar
|
||||
// toTrait = Bar
|
||||
// delegateExpressionType = typeof(baz)
|
||||
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
||||
@JvmStatic
|
||||
public fun getDelegates(
|
||||
descriptor: ClassDescriptor,
|
||||
toInterface: ClassDescriptor,
|
||||
toTrait: ClassDescriptor,
|
||||
delegateExpressionType: KotlinType? = null
|
||||
): Map<CallableMemberDescriptor, CallableDescriptor> {
|
||||
if (delegateExpressionType?.isDynamic() ?: false) return mapOf();
|
||||
|
||||
return descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
|
||||
return descriptor.getDefaultType().getMemberScope().getContributedDescriptors().asSequence()
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
|
||||
.filter { it.getKind() == CallableMemberDescriptor.Kind.DELEGATION }
|
||||
.asIterable()
|
||||
.sortedWith(MemberComparator.INSTANCE)
|
||||
.keysToMapExceptNulls {
|
||||
delegatingMember ->
|
||||
|
||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
||||
.mapNotNull {
|
||||
.filter { it.getContainingDeclaration() == toTrait }
|
||||
.map {
|
||||
overriddenDescriptor ->
|
||||
if (overriddenDescriptor.containingDeclaration == toInterface) {
|
||||
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
|
||||
val name = overriddenDescriptor.name
|
||||
val scope = (delegateExpressionType ?: toTrait.getDefaultType()).getMemberScope()
|
||||
val name = overriddenDescriptor.getName()
|
||||
|
||||
// this is the actual member of delegateExpressionType that we are delegating to
|
||||
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
|
||||
.firstOrNull {
|
||||
(listOf(it) + DescriptorUtils.getAllOverriddenDescriptors(it))
|
||||
.map { it.original }
|
||||
.contains(overriddenDescriptor.original)
|
||||
}
|
||||
}
|
||||
else null
|
||||
// this is the actual member of delegateExpressionType that we are delegating to
|
||||
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
|
||||
.first {
|
||||
(listOf(it) + DescriptorUtils.getAllOverriddenDescriptors(it)).map { it.getOriginal() }.contains(overriddenDescriptor.getOriginal())
|
||||
}
|
||||
}
|
||||
assert(actualDelegates.size <= 1) { "Many delegates found for $delegatingMember: $actualDelegates" }
|
||||
assert(actualDelegates.size() <= 1) { "Many delegates found for $delegatingMember: $actualDelegates" }
|
||||
|
||||
actualDelegates.firstOrNull()
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public fun <Function : FunctionHandle> findConcreteSuperDeclaration(function: Fu
|
||||
result.removeAll(toRemove)
|
||||
|
||||
val concreteRelevantDeclarations = result.filter { !it.isAbstract }
|
||||
if (concreteRelevantDeclarations.size != 1) {
|
||||
if (concreteRelevantDeclarations.size() != 1) {
|
||||
error("Concrete fake override $function should have exactly one concrete super-declaration: $concreteRelevantDeclarations")
|
||||
}
|
||||
|
||||
|
||||
@@ -90,9 +90,10 @@ public fun findImplementationFromInterface(descriptor: CallableMemberDescriptor)
|
||||
val overridden = OverrideResolver.getOverriddenDeclarations(descriptor)
|
||||
val filtered = OverrideResolver.filterOutOverridden(overridden)
|
||||
|
||||
val result = filtered.firstOrNull { it.modality != Modality.ABSTRACT } ?: return null
|
||||
val result = filtered.firstOrNull { it.getModality() != Modality.ABSTRACT } ?: return null
|
||||
|
||||
if (DescriptorUtils.isClassOrEnumClass(result.containingDeclaration)) return null
|
||||
val container = result.getContainingDeclaration()
|
||||
if (DescriptorUtils.isClass(container) || DescriptorUtils.isEnumClass(container)) return null
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -41,14 +41,6 @@ public class AccessorForConstructorDescriptor(
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor) = super.substitute(substitutor) as ConstructorDescriptor
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor?, modality: Modality?, visibility: Visibility?, kind: CallableMemberDescriptor.Kind?, copyOverrides: Boolean
|
||||
): AccessorForConstructorDescriptor {
|
||||
throw UnsupportedOperationException("Trying to copy synthetic accessor $this")
|
||||
}
|
||||
|
||||
override fun getOriginal(): AccessorForConstructorDescriptor = this
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||
|
||||
@@ -32,8 +32,8 @@ abstract class ArgumentGenerator {
|
||||
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
|
||||
*/
|
||||
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallMask {
|
||||
assert(valueArgumentsByIndex.size == actualArgs.size) {
|
||||
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
|
||||
assert(valueArgumentsByIndex.size() == actualArgs.size()) {
|
||||
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size()} != ${actualArgs.size()}"
|
||||
}
|
||||
|
||||
val arg2Index = valueArgumentsByIndex.mapToIndex()
|
||||
@@ -48,7 +48,7 @@ abstract class ArgumentGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
val masks = DefaultCallMask(valueArgumentsByIndex.size)
|
||||
val masks = DefaultCallMask(valueArgumentsByIndex.size())
|
||||
|
||||
for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
|
||||
val argument = argumentWithDeclIndex.arg
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
|
||||
import org.jetbrains.kotlin.resolve.DeprecationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
@@ -62,11 +61,11 @@ import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@@ -227,9 +226,9 @@ public class AsmUtil {
|
||||
int flags = getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= getVarargsFlag(functionDescriptor);
|
||||
flags |= getDeprecatedAccessFlag(functionDescriptor);
|
||||
if (DeprecationUtilKt.isHiddenInResolution(functionDescriptor)
|
||||
if (DeprecationUtilKt.isAnnotatedAsHidden(functionDescriptor)
|
||||
|| functionDescriptor instanceof PropertyAccessorDescriptor
|
||||
&& DeprecationUtilKt.isHiddenInResolution(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) {
|
||||
&& DeprecationUtilKt.isAnnotatedAsHidden(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) {
|
||||
flags |= ACC_SYNTHETIC;
|
||||
}
|
||||
return flags;
|
||||
@@ -300,6 +299,9 @@ public class AsmUtil {
|
||||
|
||||
public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) {
|
||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
if (((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty().isConst()) {
|
||||
return ACC_DEPRECATED;
|
||||
}
|
||||
return KotlinBuiltIns.isDeprecated(descriptor)
|
||||
? ACC_DEPRECATED
|
||||
: getDeprecatedAccessFlag(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty());
|
||||
@@ -323,6 +325,9 @@ public class AsmUtil {
|
||||
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
Visibility memberVisibility = memberDescriptor.getVisibility();
|
||||
if (isJvmInterface(containingDeclaration)) {
|
||||
return memberVisibility == Visibilities.PRIVATE ? NO_FLAG_PACKAGE_PRIVATE : ACC_PUBLIC;
|
||||
}
|
||||
|
||||
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
return ACC_PUBLIC;
|
||||
@@ -374,6 +379,11 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (memberDescriptor instanceof PropertyDescriptor &&
|
||||
((PropertyDescriptor) memberDescriptor).isConst() || hasJvmFieldAnnotation(memberDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -540,7 +550,7 @@ public class AsmUtil {
|
||||
if (opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ) {
|
||||
genInvertBoolean(v);
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -679,17 +689,28 @@ public class AsmUtil {
|
||||
}
|
||||
|
||||
public static boolean isInstancePropertyWithStaticBackingField(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
||||
isObject(propertyDescriptor.getContainingDeclaration());
|
||||
if (propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeclarationDescriptor container = propertyDescriptor.getContainingDeclaration();
|
||||
return isNonCompanionObject(container) ||
|
||||
isPropertyWithBackingFieldInOuterClass(propertyDescriptor) ||
|
||||
(isCompanionObject(container) && isInterface(container.getContainingDeclaration()));
|
||||
}
|
||||
|
||||
public static int getVisibilityForBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) {
|
||||
public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
||||
isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration());
|
||||
}
|
||||
|
||||
public static int getVisibilityForSpecialPropertyBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) {
|
||||
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
||||
if (isDelegate || isExtensionProperty) {
|
||||
return ACC_PRIVATE;
|
||||
}
|
||||
else {
|
||||
return propertyDescriptor.isLateInit() || isConstOrHasJvmFieldAnnotation(propertyDescriptor)
|
||||
return areBothAccessorDefault(propertyDescriptor)
|
||||
? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor))
|
||||
: ACC_PRIVATE;
|
||||
}
|
||||
@@ -705,10 +726,27 @@ public class AsmUtil {
|
||||
}
|
||||
|
||||
public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
||||
DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration();
|
||||
return propertyDescriptor.isConst()
|
||||
return !propertyDescriptor.isVar()
|
||||
&& !isExtensionProperty
|
||||
&& isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration())
|
||||
&& getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
||||
&& areBothAccessorDefault(propertyDescriptor)
|
||||
&& getVisibilityForSpecialPropertyBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
||||
}
|
||||
|
||||
public static boolean isCompanionObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) {
|
||||
DeclarationDescriptor containingClass = companionObject.getContainingDeclaration();
|
||||
return isCompanionObject(companionObject) && (isClass(containingClass) || isEnumClass(containingClass));
|
||||
}
|
||||
|
||||
private static boolean areBothAccessorDefault(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return isAccessorWithEmptyBody(propertyDescriptor.getGetter())
|
||||
&& (!propertyDescriptor.isVar() || isAccessorWithEmptyBody(propertyDescriptor.getSetter()));
|
||||
}
|
||||
|
||||
private static boolean isAccessorWithEmptyBody(@Nullable PropertyAccessorDescriptor accessorDescriptor) {
|
||||
return accessorDescriptor == null || !accessorDescriptor.hasBody();
|
||||
}
|
||||
|
||||
public static Type comparisonOperandType(Type left, Type right) {
|
||||
@@ -813,6 +851,13 @@ public class AsmUtil {
|
||||
return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String shortNameByAsmType(@NotNull Type type) {
|
||||
String internalName = type.getInternalName();
|
||||
int lastSlash = internalName.lastIndexOf('/');
|
||||
return lastSlash < 0 ? internalName : internalName.substring(lastSlash + 1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
|
||||
return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName));
|
||||
|
||||
@@ -90,7 +90,7 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex) {
|
||||
callGenerator.reorderArgumentsIfNeeded(actualArgsWithDeclIndex, valueParameterTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -52,19 +51,11 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
|
||||
@Override
|
||||
protected void generateBody() {
|
||||
List<KtObjectDeclaration> companions = new ArrayList<KtObjectDeclaration>();
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS) {
|
||||
//generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
|
||||
for (KtDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (shouldProcessFirst(declaration)) {
|
||||
//Generate companions after class body generation (need to record all synthetic accessors)
|
||||
if (declaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) declaration).isCompanion()) {
|
||||
companions.add((KtObjectDeclaration) declaration);
|
||||
CodegenUtilKt.populateCompanionBackingFieldNamesToOuterContextIfNeeded((KtObjectDeclaration) declaration, context, state);
|
||||
}
|
||||
else {
|
||||
generateDeclaration(declaration);
|
||||
}
|
||||
generateDeclaration(declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,14 +66,6 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
}
|
||||
}
|
||||
|
||||
generatePrimaryConstructorProperties();
|
||||
generateConstructors();
|
||||
generateDefaultImplsIfNeeded();
|
||||
|
||||
for (KtObjectDeclaration companion : companions) {
|
||||
generateDeclaration(companion);
|
||||
}
|
||||
|
||||
if (!DescriptorUtils.isInterface(descriptor)) {
|
||||
for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||
if (memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
@@ -105,14 +88,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateConstructors() {
|
||||
|
||||
}
|
||||
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
|
||||
generatePrimaryConstructorProperties();
|
||||
}
|
||||
|
||||
private static boolean shouldProcessFirst(KtDeclaration declaration) {
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
import org.jetbrains.kotlin.utils.FunctionsKt;
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
@@ -211,7 +212,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
this.constructor = generateConstructor();
|
||||
|
||||
if (isConst(closure)) {
|
||||
generateConstInstance(asmType, asmType);
|
||||
generateConstInstance(asmType, asmType, FunctionsKt.<InstructionAdapter>doNothing());
|
||||
}
|
||||
|
||||
genClosureFields(closure, v, typeMapper);
|
||||
@@ -258,7 +259,13 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
|
||||
}
|
||||
|
||||
return Unit.INSTANCE;
|
||||
if (functionReferenceTarget != null) {
|
||||
if (!"true".equalsIgnoreCase(System.getProperty("kotlin.jvm.optimize.callable.references"))) {
|
||||
v.invokestatic(REFLECTION, "function", Type.getMethodDescriptor(K_FUNCTION, FUNCTION_REFERENCE), false);
|
||||
}
|
||||
}
|
||||
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -108,13 +108,15 @@ class CollectionStubMethodGenerator(
|
||||
val genericSignatureInfo = overriddenMethod.getSpecialSignatureInfo()
|
||||
|
||||
val specialGenericSignature =
|
||||
genericSignatureInfo?.replaceValueParametersIn(overriddenMethodSignature.genericsSignature)
|
||||
?: overriddenMethodSignature.genericsSignature
|
||||
if (genericSignatureInfo != null)
|
||||
genericSignatureInfo.signature
|
||||
else
|
||||
overriddenMethodSignature.genericsSignature
|
||||
|
||||
val (asmMethod, valueParameters) =
|
||||
// if current method has special generic signature,
|
||||
// like `Collection.remove(E): Boolean` in Kotlin, use original signature to obtain `remove(Object)`
|
||||
if (genericSignatureInfo?.isObjectReplacedWithTypeParameter ?: false)
|
||||
// if remove(E) in Kotlin -> remove(Object) in Java
|
||||
// so choose original signature
|
||||
if (genericSignatureInfo == SpecialSignatureInfo.GENERIC_PARAMETER)
|
||||
Pair(originalSignature.asmMethod, originalSignature.valueParameters)
|
||||
else
|
||||
Pair(overriddenMethodSignature.asmMethod, overriddenMethodSignature.valueParameters)
|
||||
@@ -214,7 +216,7 @@ class CollectionStubMethodGenerator(
|
||||
private fun Collection<KotlinType>.findMostSpecificTypeForClass(klass: ClassDescriptor): KotlinType {
|
||||
val types = this.filter { it.getConstructor().getDeclarationDescriptor() == klass }
|
||||
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
|
||||
return types.first { type ->
|
||||
types.all { other -> KotlinTypeChecker.DEFAULT.isSubtypeOf(type, other) }
|
||||
@@ -227,7 +229,7 @@ class CollectionStubMethodGenerator(
|
||||
child.setModality(Modality.FINAL)
|
||||
child.setVisibility(Visibilities.PUBLIC)
|
||||
val typeParameters = descriptor.getTypeConstructor().getParameters()
|
||||
val newTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size)
|
||||
val newTypeParameters = ArrayList<TypeParameterDescriptor>(typeParameters.size())
|
||||
DescriptorSubstitutor.substituteTypeParameters(typeParameters, TypeSubstitution.EMPTY, child, newTypeParameters)
|
||||
child.setTypeParameterDescriptors(typeParameters)
|
||||
return Pair(child, newTypeParameters)
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicPropertyGetter;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics;
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -53,10 +54,10 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
||||
import org.jetbrains.kotlin.jvm.bindingContextSlices.BindingContextSlicesKt;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
@@ -92,13 +93,15 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.couldUseDirectAccessToProperty;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -478,7 +481,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
markLineNumber(expression, isStatement);
|
||||
v.mark(end);
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -666,7 +669,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
});
|
||||
}
|
||||
else {
|
||||
KtDestructuringDeclaration multiParameter = forExpression.getDestructuringParameter();
|
||||
KtMultiDeclaration multiParameter = forExpression.getMultiParameter();
|
||||
assert multiParameter != null;
|
||||
|
||||
// E tmp<e> = tmp<iterator>.next()
|
||||
@@ -684,15 +687,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
assignToLoopParameter();
|
||||
|
||||
if (forExpression.getLoopParameter() == null) {
|
||||
KtDestructuringDeclaration multiParameter = forExpression.getDestructuringParameter();
|
||||
KtMultiDeclaration multiParameter = forExpression.getMultiParameter();
|
||||
assert multiParameter != null;
|
||||
|
||||
generateMultiVariables(multiParameter.getEntries());
|
||||
}
|
||||
}
|
||||
|
||||
private void generateMultiVariables(List<KtDestructuringDeclarationEntry> entries) {
|
||||
for (KtDestructuringDeclarationEntry variableDeclaration : entries) {
|
||||
private void generateMultiVariables(List<KtMultiDeclarationEntry> entries) {
|
||||
for (KtMultiDeclarationEntry variableDeclaration : entries) {
|
||||
final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration);
|
||||
|
||||
@SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType());
|
||||
@@ -1292,7 +1295,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1329,7 +1332,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitLambdaExpression(@NotNull KtLambdaExpression expression, StackValue receiver) {
|
||||
public StackValue visitFunctionLiteralExpression(@NotNull KtFunctionLiteralExpression expression, StackValue receiver) {
|
||||
if (Boolean.TRUE.equals(bindingContext.get(BLOCK, expression))) {
|
||||
return gen(expression.getFunctionLiteral().getBodyExpression());
|
||||
}
|
||||
@@ -1431,7 +1434,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
JvmMethodSignature constructor = typeMapper.mapSignature(SamCodegenUtil.resolveSamAdapter(constructorDescriptor));
|
||||
v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor(), false);
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1549,7 +1552,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) {
|
||||
task.fun(value);
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1566,9 +1569,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
|
||||
private void putDescriptorIntoFrameMap(@NotNull KtElement statement) {
|
||||
if (statement instanceof KtDestructuringDeclaration) {
|
||||
KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement;
|
||||
for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
if (statement instanceof KtMultiDeclaration) {
|
||||
KtMultiDeclaration multiDeclaration = (KtMultiDeclaration) statement;
|
||||
for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
putLocalVariableIntoFrameMap(entry);
|
||||
}
|
||||
}
|
||||
@@ -1606,9 +1609,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull Label blockEnd,
|
||||
@NotNull List<Function<StackValue, Void>> leaveTasks
|
||||
) {
|
||||
if (statement instanceof KtDestructuringDeclaration) {
|
||||
KtDestructuringDeclaration multiDeclaration = (KtDestructuringDeclaration) statement;
|
||||
for (KtDestructuringDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
if (statement instanceof KtMultiDeclaration) {
|
||||
KtMultiDeclaration multiDeclaration = (KtMultiDeclaration) statement;
|
||||
for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
|
||||
addLeaveTaskToRemoveLocalVariableFromFrameMap(entry, blockEnd, leaveTasks);
|
||||
}
|
||||
}
|
||||
@@ -2069,10 +2072,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
PropertyGetterDescriptor getter = descriptor.getGetter();
|
||||
if (getter != null) {
|
||||
Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter);
|
||||
if (call != null) {
|
||||
assert call.getExplicitReceiver() != null : "No explicit receiver for call:" + call;
|
||||
return ((ReceiverValue) call.getExplicitReceiver()).getType();
|
||||
}
|
||||
return call != null ? ((ReceiverValue) call.getExplicitReceiver()).getType() : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -2116,11 +2116,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
|
||||
FieldAccessorKind fieldAccessorKind = FieldAccessorKind.NORMAL;
|
||||
boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
boolean isBackingFieldInClassCompanion = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
if (isBackingFieldInClassCompanion && forceField) {
|
||||
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if (syntheticBackingField && context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration) {
|
||||
else if (syntheticBackingField && context.getParentContext().getContextDescriptor() != containingDeclaration) {
|
||||
fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||
}
|
||||
boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) ||
|
||||
@@ -2140,7 +2140,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
PropertyDescriptor originalPropertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
|
||||
if (fieldAccessorKind != FieldAccessorKind.NORMAL) {
|
||||
int flags = AsmUtil.getVisibilityForBackingField(propertyDescriptor, isDelegatedProperty);
|
||||
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
||||
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || skipAccessorsForPrivateFieldInOuterClass;
|
||||
if (!skipPropertyAccessors) {
|
||||
//noinspection ConstantConditions
|
||||
@@ -2161,12 +2161,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) {
|
||||
propertyDescriptor = context.getAccessorForSuperCallIfNeeded(propertyDescriptor, superCallTarget);
|
||||
if (isSuper && !isJvmInterface(containingDeclaration)) {
|
||||
CodegenContext c = context.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
||||
if (c != context.getParentContext()) {
|
||||
propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor, superCallTarget);
|
||||
}
|
||||
}
|
||||
|
||||
propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superCallTarget);
|
||||
|
||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||
if (getter != null && !isConstOrHasJvmFieldAnnotation(propertyDescriptor)) {
|
||||
if (getter != null && !hasJvmFieldAnnotation(propertyDescriptor)) {
|
||||
callableGetter = typeMapper.mapToCallableMethod(getter, isSuper);
|
||||
}
|
||||
}
|
||||
@@ -2175,7 +2181,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||
if (setter != null &&
|
||||
!couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context) &&
|
||||
!isConstOrHasJvmFieldAnnotation(propertyDescriptor)) {
|
||||
!hasJvmFieldAnnotation(propertyDescriptor)) {
|
||||
callableSetter = typeMapper.mapToCallableMethod(setter, isSuper);
|
||||
}
|
||||
}
|
||||
@@ -2245,8 +2251,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
final SamType samType = bindingContext.get(SAM_VALUE, probablyParenthesizedExpression);
|
||||
if (samType == null || expression == null) return null;
|
||||
|
||||
if (expression instanceof KtLambdaExpression) {
|
||||
return genClosure(((KtLambdaExpression) expression).getFunctionLiteral(), samType);
|
||||
if (expression instanceof KtFunctionLiteralExpression) {
|
||||
return genClosure(((KtFunctionLiteralExpression) expression).getFunctionLiteral(), samType);
|
||||
}
|
||||
|
||||
if (expression instanceof KtNamedFunction) {
|
||||
@@ -2319,8 +2325,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
|
||||
FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall);
|
||||
ClassDescriptor superCallTarget = getSuperCallTarget(call);
|
||||
boolean superCall = superCallTarget != null;
|
||||
|
||||
fd = context.getAccessorForSuperCallIfNeeded(fd, superCallTarget);
|
||||
if (superCall && !isJvmInterface(fd.getContainingDeclaration())) {
|
||||
CodegenContext c = context.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + fd;
|
||||
if (c != context.getParentContext()) {
|
||||
fd = (FunctionDescriptor) c.getAccessor(fd, superCallTarget);
|
||||
}
|
||||
}
|
||||
|
||||
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
|
||||
if (!codegenExtensions.isEmpty()) {
|
||||
@@ -2331,7 +2344,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall);
|
||||
Callable callable = resolveToCallable(fd, superCall, resolvedCall);
|
||||
|
||||
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
}
|
||||
@@ -2420,12 +2433,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||
|
||||
KotlinType returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
|
||||
v.aconst(null);
|
||||
v.athrow();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -2476,8 +2483,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
else {
|
||||
mappings.addParameterMappingToNewParameter(
|
||||
key.getName().getIdentifier(), type,
|
||||
parameterDescriptor.getName().getIdentifier());
|
||||
key.getName().getIdentifier(),
|
||||
parameterDescriptor.getName().getIdentifier()
|
||||
);
|
||||
}
|
||||
}
|
||||
return getOrCreateCallGenerator(
|
||||
@@ -2486,7 +2494,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateReceiverValue(@Nullable ReceiverValue receiverValue, boolean isSuper) {
|
||||
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue, boolean isSuper) {
|
||||
if (receiverValue instanceof ImplicitClassReceiver) {
|
||||
ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
|
||||
@@ -2738,17 +2746,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||
if (variableDescriptor != null) {
|
||||
return generatePropertyReference(expression, variableDescriptor, resolvedCall);
|
||||
return generatePropertyReference(expression, variableDescriptor, (VariableDescriptor) resolvedCall.getResultingDescriptor(),
|
||||
resolvedCall.getDispatchReceiver());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generatePropertyReference(
|
||||
public StackValue generatePropertyReference(
|
||||
@NotNull KtElement element,
|
||||
@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull ResolvedCall<?> resolvedCall
|
||||
@NotNull VariableDescriptor target,
|
||||
@NotNull ReceiverValue dispatchReceiver
|
||||
) {
|
||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||
|
||||
@@ -2760,7 +2770,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
||||
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
||||
element, classBuilder, resolvedCall
|
||||
element, classBuilder, classDescriptor, target, dispatchReceiver
|
||||
);
|
||||
codegen.generate();
|
||||
|
||||
@@ -2785,13 +2795,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
"Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor;
|
||||
assert codegen != null :
|
||||
"Reference to member of reified type should be rejected by type checker " + typeParameterDescriptor;
|
||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS);
|
||||
codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME);
|
||||
}
|
||||
|
||||
putJavaLangClassInstance(v, classAsmType);
|
||||
wrapJavaClassIntoKClass(v);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3250,7 +3260,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
value.store(StackValue.onStack(storeType), v, true);
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3266,7 +3276,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, StackValue receiver) {
|
||||
public StackValue visitMultiDeclaration(@NotNull KtMultiDeclaration multiDeclaration, StackValue receiver) {
|
||||
KtExpression initializer = multiDeclaration.getInitializer();
|
||||
if (initializer == null) return StackValue.none();
|
||||
|
||||
@@ -3283,7 +3293,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
v.store(tempVarIndex, initializerAsmType);
|
||||
StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType);
|
||||
|
||||
for (KtDestructuringDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) {
|
||||
for (KtMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration);
|
||||
assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
|
||||
Call call = makeFakeCall(initializerAsReceiver);
|
||||
@@ -3375,7 +3385,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructor, false);
|
||||
invokeMethodWithArguments(method, resolvedCall, StackValue.none());
|
||||
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3391,7 +3401,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
gen(sizeExpression, Type.INT_TYPE);
|
||||
newArrayInstruction(arrayType);
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3399,9 +3409,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
public void newArrayInstruction(@NotNull KotlinType arrayType) {
|
||||
if (KotlinBuiltIns.isArray(arrayType)) {
|
||||
KotlinType elementJetType = arrayType.getArguments().get(0).getType();
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
putReifierMarkerIfTypeIsReifiedParameter(
|
||||
elementJetType,
|
||||
ReifiedTypeInliner.OperationKind.NEW_ARRAY
|
||||
ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME
|
||||
);
|
||||
v.newarray(boxType(asmType(elementJetType)));
|
||||
}
|
||||
@@ -3630,7 +3640,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
if (finallyBlock != null) {
|
||||
blockStackElements.pop();
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3678,19 +3688,28 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
StackValue.putUnitInstance(v);
|
||||
}
|
||||
|
||||
boolean safeAs = opToken == KtTokens.AS_SAFE;
|
||||
Type type = boxType(asmType(rightType));
|
||||
if (TypeUtils.isReifiedTypeParameter(rightType)) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(rightType,
|
||||
safeAs ? ReifiedTypeInliner.OperationKind.SAFE_AS
|
||||
: ReifiedTypeInliner.OperationKind.AS);
|
||||
v.checkcast(type);
|
||||
return Unit.INSTANCE;
|
||||
if (opToken != KtTokens.AS_SAFE) {
|
||||
if (!TypeUtils.isNullableType(rightType)) {
|
||||
v.dup();
|
||||
Label nonnull = new Label();
|
||||
v.ifnonnull(nonnull);
|
||||
genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " +
|
||||
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(rightType));
|
||||
v.mark(nonnull);
|
||||
}
|
||||
}
|
||||
else {
|
||||
v.dup();
|
||||
generateInstanceOfInstruction(rightType);
|
||||
Label ok = new Label();
|
||||
v.ifne(ok);
|
||||
v.pop();
|
||||
v.aconst(null);
|
||||
v.mark(ok);
|
||||
}
|
||||
|
||||
CodegenUtilKt.generateAsCast(v, rightType, type, safeAs);
|
||||
|
||||
return Unit.INSTANCE;
|
||||
generateCheckCastInstruction(rightType, opToken == KtTokens.AS_SAFE);
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3728,11 +3747,11 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
private StackValue generateIsCheck(StackValue expressionToMatch, KtTypeReference typeReference, boolean negated) {
|
||||
KotlinType jetType = bindingContext.get(TYPE, typeReference);
|
||||
markStartLineNumber(typeReference);
|
||||
StackValue value = generateIsCheck(expressionToMatch, jetType, false);
|
||||
StackValue value = generateInstanceOf(expressionToMatch, jetType, false);
|
||||
return negated ? StackValue.not(value) : value;
|
||||
}
|
||||
|
||||
private StackValue generateIsCheck(final StackValue expressionToGen, final KotlinType kotlinType, final boolean leaveExpressionOnStack) {
|
||||
private StackValue generateInstanceOf(final StackValue expressionToGen, final KotlinType kotlinType, final boolean leaveExpressionOnStack) {
|
||||
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
@@ -3740,35 +3759,46 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dup();
|
||||
}
|
||||
|
||||
Type type = boxType(asmType(kotlinType));
|
||||
if (TypeUtils.isReifiedTypeParameter(kotlinType)) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(kotlinType, ReifiedTypeInliner.OperationKind.IS);
|
||||
v.instanceOf(type);
|
||||
return null;
|
||||
}
|
||||
|
||||
CodegenUtilKt.generateIsCheck(v, kotlinType, type);
|
||||
CodegenUtilKt.generateIsCheck(v, kotlinType, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
generateInstanceOfInstruction(kotlinType);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
|
||||
) {
|
||||
private void generateInstanceOfInstruction(@NotNull KotlinType jetType) {
|
||||
Type type = boxType(asmType(jetType));
|
||||
putReifierMarkerIfTypeIsReifiedParameter(jetType, ReifiedTypeInliner.INSTANCEOF_MARKER_METHOD_NAME);
|
||||
TypeIntrinsics.instanceOf(v, jetType, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generateCheckCastInstruction(@NotNull KotlinType jetType, boolean safeAs) {
|
||||
Type type = boxType(asmType(jetType));
|
||||
putReifierMarkerIfTypeIsReifiedParameter(jetType,
|
||||
safeAs ? ReifiedTypeInliner.SAFE_CHECKCAST_MARKER_METHOD_NAME
|
||||
: ReifiedTypeInliner.CHECKCAST_MARKER_METHOD_NAME);
|
||||
TypeIntrinsics.checkcast(v, jetType, type, safeAs);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
|
||||
public void putReifierMarkerIfTypeIsReifiedParameter(@NotNull KotlinType type, @NotNull String markerMethodName) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
|
||||
if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) {
|
||||
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||
parentCodegen.getReifiedTypeParametersUsages().
|
||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||
}
|
||||
v.iconst(operationKind.getId());
|
||||
boolean putNullableFlag = operationKind.isTypeNullabilityAware() && type.isMarkedNullable();
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString() + (putNullableFlag ? "?" : ""));
|
||||
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.REIFIED_OPERATION_MARKER_METHOD_NAME,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.getType(String.class)), false
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3791,12 +3821,11 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return StackValue.operation(resultType, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
SwitchCodegen switchCodegen = SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, isExhaustive(expression, isStatement), ExpressionCodegen.this
|
||||
);
|
||||
SwitchCodegen switchCodegen =
|
||||
SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(expression, isStatement, ExpressionCodegen.this);
|
||||
if (switchCodegen != null) {
|
||||
switchCodegen.generate();
|
||||
return Unit.INSTANCE;
|
||||
return Unit.INSTANCE$;
|
||||
}
|
||||
|
||||
int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||
@@ -3839,7 +3868,9 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
if (!hasElse && nextCondition != null) {
|
||||
v.mark(nextCondition);
|
||||
putUnitInstanceOntoStackForNonExhaustiveWhen(expression, isStatement);
|
||||
if (!isStatement) {
|
||||
putUnitInstanceOntoStackForNonExhaustiveWhen(expression);
|
||||
}
|
||||
}
|
||||
|
||||
markLineNumber(expression, isStatement);
|
||||
@@ -3852,24 +3883,14 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isExhaustive(@NotNull KtWhenExpression whenExpression, boolean isStatement) {
|
||||
if (isStatement) {
|
||||
return Boolean.TRUE.equals(bindingContext.get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression));
|
||||
}
|
||||
else {
|
||||
return Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, whenExpression));
|
||||
}
|
||||
}
|
||||
|
||||
public void putUnitInstanceOntoStackForNonExhaustiveWhen(
|
||||
@NotNull KtWhenExpression whenExpression,
|
||||
boolean isStatement
|
||||
@NotNull KtWhenExpression expression
|
||||
) {
|
||||
if (isExhaustive(whenExpression, isStatement)) {
|
||||
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) {
|
||||
// when() is supposed to be exhaustive
|
||||
genThrow(v, "kotlin/NoWhenBranchMatchedException", null);
|
||||
}
|
||||
else if (!isStatement) {
|
||||
else {
|
||||
// non-exhaustive when() with no else -> Unit must be expected
|
||||
StackValue.putUnitInstance(v);
|
||||
}
|
||||
|
||||
@@ -33,12 +33,17 @@ public class FieldInfo {
|
||||
|
||||
@NotNull
|
||||
public static FieldInfo createForSingleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) {
|
||||
return createForSingleton(classDescriptor, typeMapper, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FieldInfo createForSingleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper, boolean oldSingleton) {
|
||||
if (!classDescriptor.getKind().isSingleton() || DescriptorUtils.isEnumEntry(classDescriptor)) {
|
||||
throw new UnsupportedOperationException("Can't create singleton field for class: " + classDescriptor);
|
||||
}
|
||||
|
||||
if (isNonCompanionObject(classDescriptor) || COMPANION_OBJECT_MAPPING.hasMappingToObject(classDescriptor)) {
|
||||
return createSingletonViaInstance(classDescriptor, typeMapper);
|
||||
return createSingletonViaInstance(classDescriptor, typeMapper, oldSingleton);
|
||||
}
|
||||
else {
|
||||
ClassDescriptor ownerDescriptor = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
|
||||
@@ -51,10 +56,11 @@ public class FieldInfo {
|
||||
@NotNull
|
||||
public static FieldInfo createSingletonViaInstance(
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull JetTypeMapper typeMapper
|
||||
@NotNull JetTypeMapper typeMapper,
|
||||
boolean oldSingleton
|
||||
) {
|
||||
Type type = typeMapper.mapType(classDescriptor);
|
||||
return new FieldInfo(type, type, JvmAbi.INSTANCE_FIELD, true);
|
||||
return new FieldInfo(type, type, oldSingleton ? JvmAbi.DEPRECATED_INSTANCE_FIELD : JvmAbi.INSTANCE_FIELD, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
|
||||
import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeKt;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -76,12 +77,11 @@ import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getSuperClassDescriptor;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -161,7 +161,7 @@ public class FunctionCodegen {
|
||||
int flags = getMethodAsmFlags(functionDescriptor, contextKind);
|
||||
boolean isNative = NativeKt.hasNativeAnnotation(functionDescriptor);
|
||||
|
||||
if (isNative && owner instanceof MultifileClassFacadeContext) {
|
||||
if (isNative && owner instanceof DelegatingFacadeContext) {
|
||||
// Native methods are only defined in facades and do not need package part implementations
|
||||
return;
|
||||
}
|
||||
@@ -172,6 +172,10 @@ public class FunctionCodegen {
|
||||
jvmSignature.getGenericsSignature(),
|
||||
getThrownExceptions(functionDescriptor, typeMapper));
|
||||
|
||||
String implClassName = CodegenContextUtil.getImplementationClassShortName(owner);
|
||||
if (implClassName != null) {
|
||||
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, functionDescriptor, implClassName);
|
||||
}
|
||||
if (CodegenContextUtil.isImplClassOwner(owner)) {
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
||||
}
|
||||
@@ -217,6 +221,8 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
endVisit(mv, null, origin.getElement());
|
||||
|
||||
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
||||
}
|
||||
|
||||
private void generateMethodAnnotations(
|
||||
@@ -233,6 +239,22 @@ public class FunctionCodegen {
|
||||
else {
|
||||
annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
|
||||
}
|
||||
|
||||
writePackageFacadeMethodAnnotationsIfNeeded(mv);
|
||||
}
|
||||
|
||||
private void writePackageFacadeMethodAnnotationsIfNeeded(MethodVisitor mv) {
|
||||
if (owner instanceof PackageFacadeContext) {
|
||||
PackageFacadeContext packageFacadeContext = (PackageFacadeContext) owner;
|
||||
Type delegateToClassType = packageFacadeContext.getPublicFacadeType();
|
||||
if (delegateToClassType != null) {
|
||||
String className = delegateToClassType.getClassName();
|
||||
AnnotationVisitor
|
||||
av = mv.visitAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_DELEGATED_METHOD), true);
|
||||
av.visit(JvmAnnotationNames.IMPLEMENTATION_CLASS_NAME_FIELD_NAME, className);
|
||||
av.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateParameterAnnotations(
|
||||
@@ -253,6 +275,9 @@ public class FunctionCodegen {
|
||||
|
||||
if (kind == JvmMethodParameterKind.VALUE) {
|
||||
ValueParameterDescriptor parameter = iterator.next();
|
||||
if (parameter.getIndex() != i) {
|
||||
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
|
||||
}
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
|
||||
|
||||
if (functionDescriptor instanceof PropertySetterDescriptor) {
|
||||
@@ -341,18 +366,18 @@ public class FunctionCodegen {
|
||||
int functionFakeIndex = -1;
|
||||
int lambdaFakeIndex = -1;
|
||||
|
||||
if (context.getParentContext() instanceof MultifileClassFacadeContext) {
|
||||
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
|
||||
if (context.getParentContext() instanceof DelegatingFacadeContext) {
|
||||
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (DelegatingFacadeContext) context.getParentContext());
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else {
|
||||
FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(),
|
||||
functionDescriptor));
|
||||
if (context.isInlineMethodContext()) {
|
||||
if (context.isInlineFunction()) {
|
||||
functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
if (context instanceof InlineLambdaContext) {
|
||||
if (context.isInliningLambda()) {
|
||||
lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
@@ -373,7 +398,7 @@ public class FunctionCodegen {
|
||||
Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
|
||||
generateLocalVariableTable(mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind());
|
||||
|
||||
if (context.isInlineMethodContext() && functionFakeIndex != -1) {
|
||||
if (context.isInlineFunction() && functionFakeIndex != -1) {
|
||||
mv.visitLocalVariable(
|
||||
JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + functionDescriptor.getName().asString(),
|
||||
Type.INT_TYPE.getDescriptor(), null,
|
||||
@@ -381,7 +406,7 @@ public class FunctionCodegen {
|
||||
functionFakeIndex);
|
||||
}
|
||||
|
||||
if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
|
||||
if (context.isInliningLambda() && thisType != null && lambdaFakeIndex != -1) {
|
||||
String name = thisType.getClassName();
|
||||
int indexOfLambdaOrdinal = name.lastIndexOf("$");
|
||||
if (indexOfLambdaOrdinal > 0) {
|
||||
@@ -445,9 +470,9 @@ public class FunctionCodegen {
|
||||
private static void generateFacadeDelegateMethodBody(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull MultifileClassFacadeContext context
|
||||
@NotNull DelegatingFacadeContext context
|
||||
) {
|
||||
generateDelegateToMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName());
|
||||
generateDelegateToMethodBody(true, mv, asmMethod, context.getDelegateToClassType().getInternalName());
|
||||
}
|
||||
|
||||
private static void generateDelegateToMethodBody(
|
||||
@@ -530,7 +555,7 @@ public class FunctionCodegen {
|
||||
// If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges
|
||||
if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return;
|
||||
|
||||
boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null;
|
||||
boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(descriptor) != null;
|
||||
|
||||
Set<Bridge<Method>> bridgesToGenerate;
|
||||
if (!isSpecial) {
|
||||
@@ -564,7 +589,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
|
||||
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
|
||||
CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(descriptor);
|
||||
assert overridden != null;
|
||||
|
||||
Method method = typeMapper.mapSignature(descriptor).getAsmMethod();
|
||||
@@ -670,9 +695,9 @@ public class FunctionCodegen {
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType());
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
if (this.owner instanceof MultifileClassFacadeContext) {
|
||||
if (this.owner instanceof DelegatingFacadeContext) {
|
||||
mv.visitCode();
|
||||
generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
|
||||
generateFacadeDelegateMethodBody(mv, defaultMethod, (DelegatingFacadeContext) this.owner);
|
||||
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else {
|
||||
@@ -886,7 +911,13 @@ public class FunctionCodegen {
|
||||
iv.ifnonnull(afterBarrier);
|
||||
}
|
||||
else {
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterType));
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
TypeIntrinsics.instanceOf(adapter, kotlinType, boxType(delegateParameterType));
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
iv.ifne(afterBarrier);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -36,6 +36,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
|
||||
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
|
||||
private final ResolvedCall<?> resolvedCall;
|
||||
private final FunctionDescriptor referencedFunction;
|
||||
@@ -80,13 +82,13 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public ReceiverValue getExtensionReceiver() {
|
||||
return extensionReceiver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public ReceiverValue getDispatchReceiver() {
|
||||
return dispatchReceiver;
|
||||
@@ -117,7 +119,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
}
|
||||
}
|
||||
else {
|
||||
Call call = CallMaker.makeCall(fakeExpression, null, null, fakeExpression, fakeArguments);
|
||||
Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
|
||||
result = codegen.invokeFunction(call, fakeResolvedCall, StackValue.none());
|
||||
}
|
||||
|
||||
@@ -155,13 +157,13 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
private ReceiverValue computeAndSaveReceiver(
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@Nullable ReceiverParameterDescriptor receiver
|
||||
) {
|
||||
if (receiver == null) return null;
|
||||
if (receiver == null) return NO_RECEIVER;
|
||||
|
||||
KtExpression receiverExpression = KtPsiFactoryKt
|
||||
.KtPsiFactory(state.getProject()).createExpression("callableReferenceFakeReceiver");
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
@@ -62,8 +62,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -98,8 +98,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
private List<PropertyAndDefaultValue> companionObjectPropertiesToCopy;
|
||||
|
||||
private final DelegationFieldsInfo delegationFieldsInfo;
|
||||
|
||||
private final List<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>> additionalTasks =
|
||||
new ArrayList<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>>();
|
||||
|
||||
@@ -114,7 +112,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
super(aClass, context, v, state, parentCodegen);
|
||||
this.classAsmType = typeMapper.mapClass(descriptor);
|
||||
this.isLocal = isLocal;
|
||||
delegationFieldsInfo = getDelegationFieldsInfo(myClass.getSuperTypeListEntries());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,7 +227,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
protected void generateBody() {
|
||||
super.generateBody();
|
||||
if (isInterface(descriptor) && !isLocal) {
|
||||
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
|
||||
ClassBuilder defaultImplsBuilder =
|
||||
@@ -239,7 +237,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
CodegenContext parentContext = context.getParentContext();
|
||||
assert parentContext != null : "Parent context of interface declaration should not be null";
|
||||
|
||||
ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
|
||||
ClassContext defaultImplsContext = parentContext.intoClass(descriptor, OwnerKind.DEFAULT_IMPLS, state);
|
||||
new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
|
||||
}
|
||||
}
|
||||
@@ -247,7 +245,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
if (!isTopLevelOrInnerClass(descriptor)) {
|
||||
v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_LOCAL_CLASS), true).visitEnd();
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(
|
||||
asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_LOCAL_CLASS), true
|
||||
);
|
||||
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray());
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
DescriptorSerializer serializer =
|
||||
@@ -369,31 +371,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateCompanionObjectBackingFieldCopies();
|
||||
|
||||
generateTraitMethods();
|
||||
|
||||
generateDelegates(delegationFieldsInfo);
|
||||
|
||||
if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
|
||||
generateSyntheticAccessors();
|
||||
}
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
new CollectionStubMethodGenerator(state, descriptor, functionCodegen, v).generate();
|
||||
|
||||
generateToArray();
|
||||
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
|
||||
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
|
||||
extension.generateClassSyntheticParts(v, state, myClass, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateConstructors() {
|
||||
DelegationFieldsInfo delegationFieldsInfo = getDelegationFieldsInfo(myClass.getDelegationSpecifiers());
|
||||
try {
|
||||
lookupConstructorExpressionsInClosureIfPresent();
|
||||
generatePrimaryConstructor(delegationFieldsInfo);
|
||||
@@ -410,6 +388,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error generating constructors of class " + myClass.getName() + " with kind " + kind, e);
|
||||
}
|
||||
|
||||
generateTraitMethods();
|
||||
|
||||
generateDelegates(delegationFieldsInfo);
|
||||
|
||||
generateSyntheticAccessors();
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
new CollectionStubMethodGenerator(state, descriptor, functionCodegen, v).generate();
|
||||
|
||||
generateToArray();
|
||||
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
|
||||
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
|
||||
extension.generateClassSyntheticParts(v, state, myClass, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGenericToArrayPresent() {
|
||||
@@ -836,16 +834,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateFieldForSingleton() {
|
||||
if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) return;
|
||||
if (isEnumEntry(descriptor)) return;
|
||||
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
boolean isCompanionObject = isCompanionObject(descriptor);
|
||||
if (isNonCompanionObject(descriptor) || isCompanionObject) {
|
||||
StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper);
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass),
|
||||
ACC_PUBLIC | ACC_STATIC | ACC_FINAL,
|
||||
ACC_PUBLIC | ACC_STATIC | ACC_FINAL | (isCompanionObject ? ACC_DEPRECATED : 0),
|
||||
field.name, field.type.getDescriptor(), null, null);
|
||||
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
StackValue.Field oldField = StackValue.oldSingleton(descriptor, typeMapper);
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass), ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_DEPRECATED, oldField.name, oldField.type.getDescriptor(), null, null);
|
||||
}
|
||||
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
// Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of <init>
|
||||
// Invoke the object constructor but ignore the result because INSTANCE$ will be initialized in the first line of <init>
|
||||
InstructionAdapter v = createOrGetClInitCodegen().v;
|
||||
markLineNumberForElement(element, v);
|
||||
v.anew(classAsmType);
|
||||
@@ -864,6 +868,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
|
||||
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
|
||||
if (!isCompanionObjectWithBackingFieldsInOuter(companionObjectDescriptor)) {
|
||||
generateCompanionObjectInitializer(companionObjectDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateCompanionObjectBackingFieldCopies() {
|
||||
@@ -873,10 +883,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
PropertyDescriptor property = info.descriptor;
|
||||
|
||||
Type type = typeMapper.mapType(property);
|
||||
int modifiers = ACC_STATIC | ACC_FINAL | ACC_PUBLIC;
|
||||
int modifiers = ACC_STATIC | ACC_FINAL | ACC_PUBLIC | (property.isConst() ? 0 : ACC_DEPRECATED);
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.Synthetic(DescriptorToSourceUtils.descriptorToDeclaration(property), property),
|
||||
modifiers, context.getFieldName(property, false),
|
||||
type.getDescriptor(), typeMapper.mapFieldSignature(property.getType(), property),
|
||||
type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
|
||||
info.defaultValue);
|
||||
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type);
|
||||
@@ -915,13 +925,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
|
||||
FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor(
|
||||
CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null
|
||||
);
|
||||
generateMethodCallTo(constructor, null, codegen.v);
|
||||
StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
||||
StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true);
|
||||
//TODO: uncomment when DEPRECATED INSTANCE is removed
|
||||
//FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor(
|
||||
// CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null
|
||||
//);
|
||||
//generateMethodCallTo(constructor, null, codegen.v);
|
||||
//StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
||||
StackValue.singleton(companionObject, typeMapper).store(StackValue.singletonViaInstance(companionObject, typeMapper), codegen.v, true);
|
||||
}
|
||||
|
||||
private void generatePrimaryConstructor(final DelegationFieldsInfo delegationFieldsInfo) {
|
||||
@@ -948,6 +958,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
DefaultParameterValueLoader.DEFAULT, null);
|
||||
|
||||
new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, kind, myClass);
|
||||
|
||||
if (isCompanionObject(descriptor)) {
|
||||
context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateSecondaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
||||
@@ -991,13 +1005,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
|
||||
getDelegationConstructorCall(bindingContext, constructorDescriptor));
|
||||
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
if (isObject(descriptor)) {
|
||||
StackValue.singletonViaInstance(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
|
||||
if (isNonCompanionObject(descriptor)) {
|
||||
StackValue.oldSingleton(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
|
||||
}
|
||||
}
|
||||
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo);
|
||||
for (KtDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatorByExpressionSpecifier) specifier, fieldsInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1016,13 +1033,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
curParam++;
|
||||
}
|
||||
|
||||
if (isCompanionObject(descriptor)) {
|
||||
ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
|
||||
parentCodegen.generateCompanionObjectInitializer(descriptor);
|
||||
}
|
||||
|
||||
if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
|
||||
if (isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
|
||||
final ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
|
||||
parentCodegen.generateCompanionObjectInitializer(descriptor);
|
||||
generateInitializers(new Function0<ExpressionCodegen>() {
|
||||
@Override
|
||||
public ExpressionCodegen invoke() {
|
||||
@@ -1140,41 +1153,41 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return StackValue.field(type, classAsmType, name, false, StackValue.none());
|
||||
}
|
||||
}
|
||||
private final Map<KtDelegatedSuperTypeEntry, Field> fields = new HashMap<KtDelegatedSuperTypeEntry, Field>();
|
||||
private final Map<KtDelegatorByExpressionSpecifier, Field> fields = new HashMap<KtDelegatorByExpressionSpecifier, Field>();
|
||||
|
||||
@NotNull
|
||||
public Field getInfo(KtDelegatedSuperTypeEntry specifier) {
|
||||
public Field getInfo(KtDelegatorByExpressionSpecifier specifier) {
|
||||
return fields.get(specifier);
|
||||
}
|
||||
|
||||
private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
|
||||
private void addField(KtDelegatorByExpressionSpecifier specifier, PropertyDescriptor propertyDescriptor) {
|
||||
fields.put(specifier,
|
||||
new Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false));
|
||||
}
|
||||
|
||||
private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name) {
|
||||
private void addField(KtDelegatorByExpressionSpecifier specifier, Type type, String name) {
|
||||
fields.put(specifier, new Field(type, name, true));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<KtSuperTypeListEntry> delegationSpecifiers) {
|
||||
private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<KtDelegationSpecifier> delegationSpecifiers) {
|
||||
DelegationFieldsInfo result = new DelegationFieldsInfo();
|
||||
int n = 0;
|
||||
for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
for (KtDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
KtExpression expression = ((KtDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext);
|
||||
|
||||
|
||||
if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
|
||||
result.addField((KtDelegatorByExpressionSpecifier) specifier, propertyDescriptor);
|
||||
}
|
||||
else {
|
||||
KotlinType expressionType = expression != null ? bindingContext.getType(expression) : null;
|
||||
Type asmType =
|
||||
expressionType != null ? typeMapper.mapType(expressionType) : typeMapper.mapType(getSuperClass(specifier));
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, "$delegate_" + n);
|
||||
result.addField((KtDelegatorByExpressionSpecifier) specifier, asmType, "$delegate_" + n);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
@@ -1183,14 +1196,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ClassDescriptor getSuperClass(@NotNull KtSuperTypeListEntry specifier) {
|
||||
return CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
|
||||
private ClassDescriptor getSuperClass(@NotNull KtDelegationSpecifier specifier) {
|
||||
return CodegenUtil.getSuperClassByDelegationSpecifier(specifier, bindingContext);
|
||||
}
|
||||
|
||||
private void genCallToDelegatorByExpressionSpecifier(
|
||||
InstructionAdapter iv,
|
||||
ExpressionCodegen codegen,
|
||||
KtDelegatedSuperTypeEntry specifier,
|
||||
KtDelegatorByExpressionSpecifier specifier,
|
||||
DelegationFieldsInfo fieldsInfo
|
||||
) {
|
||||
KtExpression expression = specifier.getDelegateExpression();
|
||||
@@ -1235,7 +1248,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void lookupReceiver(@Nullable ReceiverValue value) {
|
||||
private void lookupReceiver(@NotNull ReceiverValue value) {
|
||||
if (value instanceof ImplicitReceiver) {
|
||||
if (value instanceof ExtensionReceiver) {
|
||||
ReceiverParameterDescriptor parameter =
|
||||
@@ -1290,9 +1303,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
for (KtDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
KtExpression delegateExpression = ((KtDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
assert delegateExpression != null;
|
||||
delegateExpression.accept(visitor);
|
||||
}
|
||||
@@ -1318,7 +1331,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private void generateTraitMethods() {
|
||||
if (isInterface(descriptor)) return;
|
||||
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getTraitMethods(descriptor).entrySet()) {
|
||||
FunctionDescriptor traitFun = entry.getKey();
|
||||
//skip java 8 default methods
|
||||
if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
|
||||
@@ -1546,7 +1559,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> args) {
|
||||
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> args) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1558,8 +1571,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
for (KtEnumEntry enumEntry : enumEntries) {
|
||||
ClassDescriptor descriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
|
||||
int isDeprecated = KotlinBuiltIns.isDeprecated(descriptor) ? ACC_DEPRECATED : 0;
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL | isDeprecated,
|
||||
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL,
|
||||
descriptor.getName().asString(), classAsmType.getDescriptor(), null, null);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor, null);
|
||||
}
|
||||
@@ -1607,7 +1619,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.aconst(enumEntry.getName());
|
||||
iv.iconst(ordinal);
|
||||
|
||||
List<KtSuperTypeListEntry> delegationSpecifiers = enumEntry.getSuperTypeListEntries();
|
||||
List<KtDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers();
|
||||
if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
|
||||
|
||||
@@ -1625,11 +1637,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateDelegates(DelegationFieldsInfo delegationFieldsInfo) {
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatedSuperTypeEntry) specifier);
|
||||
for (KtDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier instanceof KtDelegatorByExpressionSpecifier) {
|
||||
DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatorByExpressionSpecifier) specifier);
|
||||
generateDelegateField(field);
|
||||
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
KtExpression delegateExpression = ((KtDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
KotlinType delegateExpressionType = delegateExpression != null ? bindingContext.getType(delegateExpression) : null;
|
||||
generateDelegates(getSuperClass(specifier), delegateExpressionType, field);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ public class InlineCycleReporter(val diagnostics: DiagnosticSink) {
|
||||
if (call != null) {
|
||||
val callElement = call.getCall().getCallElement()
|
||||
if (processingFunctions.contains(callElement)) {
|
||||
val cycle = processingFunctions.asSequence().dropWhile { it.key != callElement }
|
||||
val cycle = processingFunctions.asSequence().dropWhile { it.getKey() != callElement }
|
||||
cycle.forEach {
|
||||
diagnostics.report(Errors.INLINE_CALL_CYCLE.on(it.key, it.value))
|
||||
diagnostics.report(Errors.INLINE_CALL_CYCLE.on(it.getKey(), it.getValue()))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_INTERFACE_DEFAULT_IMPLS
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -62,7 +63,7 @@ public class InterfaceImplBodyCodegen(
|
||||
if (DescriptorUtils.isLocal(descriptor)) return null
|
||||
val classDescriptorImpl = ClassDescriptorImpl(
|
||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE)
|
||||
Modality.FINAL, Collections.emptyList(), SourceElement.NO_SOURCE)
|
||||
|
||||
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
||||
return classDescriptorImpl
|
||||
@@ -102,8 +103,6 @@ public class InterfaceImplBodyCodegen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generateSyntheticAccessors()
|
||||
}
|
||||
|
||||
private fun generateDelegationToSuperTraitImpl(descriptor: FunctionDescriptor, implementation: FunctionDescriptor) {
|
||||
@@ -123,7 +122,7 @@ public class InterfaceImplBodyCodegen(
|
||||
val myParameters = signature.getValueParameters()
|
||||
val calleeParameters = method.getValueParameters()
|
||||
|
||||
if (myParameters.size != calleeParameters.size) {
|
||||
if (myParameters.size() != calleeParameters.size()) {
|
||||
throw AssertionError(
|
||||
"Method from super interface has a different signature.\n" +
|
||||
"This method:\n%s\n%s\n%s\nSuper method:\n%s\n%s\n%s".format(
|
||||
@@ -150,7 +149,9 @@ public class InterfaceImplBodyCodegen(
|
||||
override fun generateKotlinAnnotation() {
|
||||
(v as InterfaceImplClassBuilder).stopCounting()
|
||||
|
||||
v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS), true).visitEnd()
|
||||
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS), true)
|
||||
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray())
|
||||
av.visitEnd()
|
||||
AsmUtil.writeKotlinSyntheticClassAnnotation(v, state)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.text.StringsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.StringsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -50,7 +50,6 @@ import java.io.File;
|
||||
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.ABSTRACT;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
|
||||
public class JvmCodegenUtil {
|
||||
|
||||
@@ -131,21 +130,16 @@ public class JvmCodegenUtil {
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean isConstOrHasJvmFieldAnnotation(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return propertyDescriptor.isConst() || hasJvmFieldAnnotation(propertyDescriptor);
|
||||
}
|
||||
|
||||
public static boolean couldUseDirectAccessToProperty(
|
||||
@NotNull PropertyDescriptor property,
|
||||
boolean forGetter,
|
||||
boolean isDelegated,
|
||||
@NotNull MethodContext contextBeforeInline
|
||||
@NotNull MethodContext context
|
||||
) {
|
||||
if (JetTypeMapper.isAccessor(property)) return false;
|
||||
|
||||
CodegenContext context = contextBeforeInline.getFirstCrossInlineOrNonInlineContext();
|
||||
// Inline functions can't use direct access because a field may not be visible at the call site
|
||||
if (context.isInlineMethodContext()) {
|
||||
if (context.isInlineFunction()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -170,7 +164,7 @@ public class JvmCodegenUtil {
|
||||
return Visibilities.isPrivate(property.getVisibility()) || accessor.getModality() == FINAL;
|
||||
}
|
||||
|
||||
private static boolean isDebuggerContext(@NotNull CodegenContext context) {
|
||||
private static boolean isDebuggerContext(@NotNull MethodContext context) {
|
||||
KtFile file = DescriptorToSourceUtils.getContainingFile(context.getContextDescriptor());
|
||||
return file != null && CodeFragmentUtilKt.getSuppressDiagnosticsInDebugMode(file);
|
||||
}
|
||||
@@ -224,6 +218,9 @@ public class JvmCodegenUtil {
|
||||
|
||||
public static void writeAbiVersion(@NotNull AnnotationVisitor av) {
|
||||
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray());
|
||||
|
||||
// TODO: drop after some time
|
||||
av.visit(JvmAnnotationNames.OLD_ABI_VERSION_FIELD_NAME, 32);
|
||||
}
|
||||
|
||||
public static void writeModuleName(@NotNull AnnotationVisitor av, @NotNull GenerationState state) {
|
||||
|
||||
@@ -40,7 +40,7 @@ public class JvmRuntimeTypes {
|
||||
|
||||
public JvmRuntimeTypes() {
|
||||
ModuleDescriptorImpl module = TargetPlatformKt.createModule(
|
||||
JvmPlatform.INSTANCE,
|
||||
JvmPlatform.INSTANCE$,
|
||||
Name.special("<jvm functions impl>"),
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
);
|
||||
|
||||
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
@@ -44,6 +46,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.storage.NotNullLazyValue;
|
||||
@@ -61,7 +65,8 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlag
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isStaticDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
|
||||
@@ -276,8 +281,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
|
||||
protected void writeOuterClassAndEnclosingMethod() {
|
||||
CodegenContext context = this.context.getParentContext();
|
||||
|
||||
while (context instanceof InlineLambdaContext) {
|
||||
while (context instanceof MethodContext && ((MethodContext) context).isInliningLambda()) {
|
||||
// If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
|
||||
//noinspection ConstantConditions
|
||||
context = context.getParentContext().getParentContext();
|
||||
@@ -302,7 +306,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
if (outermost instanceof ClassContext) {
|
||||
return typeMapper.mapType(((ClassContext) outermost).getContextDescriptor());
|
||||
}
|
||||
else if (outermost instanceof MultifileClassFacadeContext || outermost instanceof DelegatingToPartContext) {
|
||||
else if (outermost instanceof DelegatingFacadeContext || outermost instanceof DelegatingToPartContext) {
|
||||
Type implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(outermost);
|
||||
if (implementationOwnerType != null) {
|
||||
return implementationOwnerType;
|
||||
@@ -495,23 +499,37 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
|
||||
int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) +
|
||||
(property.getExtensionReceiverParameter() != null ? 1 : 0);
|
||||
Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
|
||||
iv.anew(implType);
|
||||
iv.dup();
|
||||
// TODO: generate the container once and save to a local field instead (KT-10495)
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
|
||||
iv.aconst(property.getName().asString());
|
||||
iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state));
|
||||
iv.invokespecial(
|
||||
implType.getInternalName(), "<init>",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
|
||||
);
|
||||
Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount);
|
||||
iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false);
|
||||
StackValue value;
|
||||
// TODO: remove this option and always generate PropertyReferenceNImpl creation
|
||||
if ("true".equalsIgnoreCase(System.getProperty("kotlin.jvm.optimize.delegated.properties"))) {
|
||||
int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) +
|
||||
(property.getExtensionReceiverParameter() != null ? 1 : 0);
|
||||
Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
|
||||
iv.anew(implType);
|
||||
iv.dup();
|
||||
// TODO: generate the container once and save to a local field instead
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
|
||||
iv.aconst(property.getName().asString());
|
||||
iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state));
|
||||
iv.invokespecial(
|
||||
implType.getInternalName(), "<init>",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
|
||||
);
|
||||
value = StackValue.onStack(implType);
|
||||
Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount);
|
||||
iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false);
|
||||
}
|
||||
else {
|
||||
ReceiverParameterDescriptor dispatchReceiver = property.getDispatchReceiverParameter();
|
||||
|
||||
StackValue.onStack(implType).put(K_PROPERTY_TYPE, iv);
|
||||
//noinspection ConstantConditions
|
||||
value = createOrGetClInitCodegen().generatePropertyReference(
|
||||
delegatedProperties.get(i).getDelegate(), property, property,
|
||||
dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER
|
||||
);
|
||||
}
|
||||
|
||||
value.put(K_PROPERTY_TYPE, iv);
|
||||
|
||||
iv.astore(K_PROPERTY_TYPE);
|
||||
}
|
||||
@@ -550,17 +568,20 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
return sourceMapper;
|
||||
}
|
||||
|
||||
protected void generateConstInstance(@NotNull Type thisAsmType, @NotNull Type fieldAsmType) {
|
||||
v.newField(
|
||||
JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD,
|
||||
fieldAsmType.getDescriptor(), null, null
|
||||
);
|
||||
protected void generateConstInstance(
|
||||
@NotNull Type thisAsmType,
|
||||
@NotNull Type fieldAsmType,
|
||||
@NotNull Function1<InstructionAdapter, Unit> initialization
|
||||
) {
|
||||
v.newField(JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor(),
|
||||
null, null);
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
InstructionAdapter iv = createOrGetClInitCodegen().v;
|
||||
iv.anew(thisAsmType);
|
||||
iv.dup();
|
||||
iv.invokespecial(thisAsmType.getInternalName(), "<init>", "()V", false);
|
||||
initialization.invoke(iv);
|
||||
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor());
|
||||
}
|
||||
}
|
||||
@@ -601,7 +622,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
|
||||
boolean forceField = (JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
boolean forceField = (AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration())) ||
|
||||
syntheticBackingField ||
|
||||
original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
|
||||
@@ -652,7 +673,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
protected StackValue generateMethodCallTo(
|
||||
private StackValue generateMethodCallTo(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@Nullable FunctionDescriptor accessorDescriptor,
|
||||
@NotNull InstructionAdapter iv
|
||||
@@ -663,7 +684,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
||||
);
|
||||
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration());
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor);
|
||||
int reg = hasDispatchReceiver ? 1 : 0;
|
||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClassPart
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
@@ -51,7 +50,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import java.util.*
|
||||
|
||||
public class MultifileClassCodegen(
|
||||
@@ -88,18 +86,12 @@ public class MultifileClassCodegen(
|
||||
|
||||
val singleSourceFile = if (previouslyCompiledCallables.isNotEmpty()) null else filesWithCallables.singleOrNull()
|
||||
|
||||
classBuilder.defineClass(singleSourceFile, Opcodes.V1_6,
|
||||
if (state.generateOpenMultifileClasses) OPEN_FACADE_CLASS_ATTRIBUTES else FACADE_CLASS_ATTRIBUTES,
|
||||
classBuilder.defineClass(singleSourceFile, Opcodes.V1_6, FACADE_CLASS_ATTRIBUTES,
|
||||
facadeClassType.internalName,
|
||||
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY)
|
||||
if (singleSourceFile != null) {
|
||||
classBuilder.visitSource(singleSourceFile.name, null)
|
||||
}
|
||||
|
||||
if (state.generateOpenMultifileClasses) {
|
||||
generateMultifileFacadeClassConstructor(classBuilder, originFile)
|
||||
}
|
||||
|
||||
classBuilder
|
||||
}
|
||||
|
||||
@@ -156,16 +148,6 @@ public class MultifileClassCodegen(
|
||||
MemberCodegen.genClassOrObject(packagePartContext, classOrObject, state, null)
|
||||
}
|
||||
|
||||
|
||||
private fun generateMultifileFacadeClassConstructor(classBuilder: ClassBuilder, originFile: KtFile?) {
|
||||
val mv = classBuilder.newMethod(JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_PUBLIC, "<init>", "()V", null, null)
|
||||
val v = InstructionAdapter(mv)
|
||||
v.load(0, facadeClassType)
|
||||
v.invokespecial("java/lang/Object", "<init>", "()V", false)
|
||||
v.visitInsn(Opcodes.RETURN)
|
||||
FunctionCodegen.endVisit(v, "multifile class constructor", originFile)
|
||||
}
|
||||
|
||||
private fun generatePart(
|
||||
file: KtFile,
|
||||
generateCallableMemberTasks: MutableMap<CallableMemberDescriptor, () -> Unit>,
|
||||
@@ -298,7 +280,6 @@ public class MultifileClassCodegen(
|
||||
|
||||
companion object {
|
||||
private val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL
|
||||
private val OPEN_FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC
|
||||
|
||||
private fun getOnlyPackageFragment(packageFqName: FqName, files: Collection<KtFile>, bindingContext: BindingContext): PackageFragmentDescriptor? {
|
||||
val fragments = SmartList<PackageFragmentDescriptor>()
|
||||
@@ -312,7 +293,7 @@ public class MultifileClassCodegen(
|
||||
fragments.add(fragment)
|
||||
}
|
||||
}
|
||||
if (fragments.size > 1) {
|
||||
if (fragments.size() > 1) {
|
||||
throw IllegalStateException("More than one package fragment, files: $files | fragments: $fragments")
|
||||
}
|
||||
return fragments.firstOrNull()
|
||||
|
||||
@@ -154,7 +154,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
|
||||
this.typeConstructor = TypeConstructorImpl.createForClass(
|
||||
this,
|
||||
Annotations.Companion.getEMPTY(),
|
||||
ModalityKt.isFinalClass(this),
|
||||
!getModality().isOverridable(),
|
||||
getName().asString(),
|
||||
typeParameters,
|
||||
supertypes
|
||||
|
||||
@@ -54,14 +54,10 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.FIELD_FOR_PROPERTY;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PROPERTY_TYPE;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
@@ -101,7 +97,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
public void generateInPackageFacade(@NotNull DeserializedPropertyDescriptor deserializedProperty) {
|
||||
assert context instanceof MultifileClassFacadeContext : "should be called only for generating facade: " + context;
|
||||
assert context instanceof DelegatingFacadeContext : "should be called only for generating facade: " + context;
|
||||
gen(null, deserializedProperty, null, null);
|
||||
}
|
||||
|
||||
@@ -114,6 +110,11 @@ public class PropertyCodegen {
|
||||
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
|
||||
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
|
||||
|
||||
String implClassName = CodegenContextUtil.getImplementationClassShortName(context);
|
||||
if (implClassName != null) {
|
||||
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, descriptor, implClassName);
|
||||
}
|
||||
|
||||
if (CodegenContextUtil.isImplClassOwner(context)) {
|
||||
assert declaration != null : "Declaration is null for different context: " + context;
|
||||
|
||||
@@ -126,6 +127,8 @@ public class PropertyCodegen {
|
||||
if (isAccessorNeeded(declaration, descriptor, setter)) {
|
||||
generateSetter(declaration, descriptor, setter);
|
||||
}
|
||||
|
||||
context.recordSyntheticAccessorIfNeeded(descriptor, bindingContext);
|
||||
}
|
||||
|
||||
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
|
||||
@@ -154,7 +157,7 @@ public class PropertyCodegen {
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@Nullable KtPropertyAccessor accessor
|
||||
) {
|
||||
if (isConstOrHasJvmFieldAnnotation(descriptor)) return false;
|
||||
if (hasJvmFieldAnnotation(descriptor)) return false;
|
||||
|
||||
boolean isDefaultAccessor = accessor == null || !accessor.hasBody();
|
||||
|
||||
@@ -264,6 +267,10 @@ public class PropertyCodegen {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitEnd();
|
||||
}
|
||||
else {
|
||||
Type tImplType = typeMapper.mapDefaultImpls((ClassDescriptor) context.getContextDescriptor());
|
||||
v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, descriptor, shortNameByAsmType(tImplType));
|
||||
}
|
||||
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS) {
|
||||
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, new Method(name, desc));
|
||||
@@ -302,17 +309,46 @@ public class PropertyCodegen {
|
||||
|
||||
ClassBuilder builder = v;
|
||||
|
||||
boolean hasJvmFieldAnnotation = hasJvmFieldAnnotation(propertyDescriptor);
|
||||
|
||||
FieldOwnerContext backingFieldContext = context;
|
||||
boolean takeVisibilityFromDescriptor = propertyDescriptor.isLateInit() || propertyDescriptor.isConst();
|
||||
if (AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor) ) {
|
||||
modifiers |= ACC_STATIC;
|
||||
|
||||
if (JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) {
|
||||
if (takeVisibilityFromDescriptor) {
|
||||
modifiers |= getVisibilityAccessFlag(propertyDescriptor);
|
||||
}
|
||||
else if (hasJvmFieldAnnotation && !isDelegate) {
|
||||
modifiers |= getDefaultVisibilityFlag(propertyDescriptor.getVisibility());
|
||||
}
|
||||
else {
|
||||
modifiers |= getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegate);
|
||||
}
|
||||
|
||||
if (AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) {
|
||||
ImplementationBodyCodegen codegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
|
||||
builder = codegen.v;
|
||||
backingFieldContext = codegen.context;
|
||||
v.getSerializationBindings().put(STATIC_FIELD_IN_OUTER_CLASS, propertyDescriptor);
|
||||
}
|
||||
|
||||
if (isObject(propertyDescriptor.getContainingDeclaration()) &&
|
||||
!hasJvmFieldAnnotation &&
|
||||
!propertyDescriptor.isConst() &&
|
||||
(modifiers & ACC_PRIVATE) == 0) {
|
||||
modifiers |= ACC_DEPRECATED;
|
||||
}
|
||||
}
|
||||
modifiers |= getVisibilityForBackingField(propertyDescriptor, isDelegate);
|
||||
else if (takeVisibilityFromDescriptor) {
|
||||
modifiers |= getVisibilityAccessFlag(propertyDescriptor);
|
||||
}
|
||||
else if (!isDelegate && hasJvmFieldAnnotation) {
|
||||
modifiers |= getDefaultVisibilityFlag(propertyDescriptor.getVisibility());
|
||||
}
|
||||
else {
|
||||
modifiers |= ACC_PRIVATE;
|
||||
}
|
||||
|
||||
if (AsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
|
||||
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
|
||||
@@ -324,7 +360,7 @@ public class PropertyCodegen {
|
||||
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
|
||||
|
||||
FieldVisitor fv = builder.newField(JvmDeclarationOriginKt.OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
typeMapper.mapFieldSignature(jetType, propertyDescriptor), defaultValue);
|
||||
typeMapper.mapFieldSignature(jetType), defaultValue);
|
||||
|
||||
Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(fieldAnnotated, type, AnnotationUseSiteTarget.FIELD);
|
||||
|
||||
@@ -28,11 +28,11 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -45,13 +45,14 @@ public class PropertyReferenceCodegen(
|
||||
context: ClassContext,
|
||||
expression: KtElement,
|
||||
classBuilder: ClassBuilder,
|
||||
resolvedCall: ResolvedCall<*>
|
||||
private val classDescriptor: ClassDescriptor,
|
||||
private val target: VariableDescriptor,
|
||||
dispatchReceiver: ReceiverValue
|
||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||
private val classDescriptor = context.contextDescriptor
|
||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||
|
||||
private val target = resolvedCall.resultingDescriptor as VariableDescriptor
|
||||
private val dispatchReceiverType = resolvedCall.dispatchReceiver?.type
|
||||
private val dispatchReceiverType = if (dispatchReceiver.exists()) dispatchReceiver.type else null
|
||||
|
||||
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
||||
|
||||
private val receiverCount =
|
||||
@@ -79,7 +80,11 @@ public class PropertyReferenceCodegen(
|
||||
|
||||
// TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
|
||||
override fun generateBody() {
|
||||
generateConstInstance(asmType, wrapperMethod.getReturnType())
|
||||
generateConstInstance(asmType, wrapperMethod.getReturnType()) { iv ->
|
||||
if (!"true".equals(System.getProperty("kotlin.jvm.optimize.callable.references"), ignoreCase = true)) {
|
||||
iv.invokestatic(REFLECTION, wrapperMethod.getName(), wrapperMethod.getDescriptor(), false)
|
||||
}
|
||||
}
|
||||
|
||||
generateMethod("property reference init", 0, method("<init>", Type.VOID_TYPE)) {
|
||||
load(0, OBJECT_TYPE)
|
||||
|
||||
@@ -70,7 +70,6 @@ public class SamWrapperCodegen {
|
||||
samType.getJavaClassDescriptor().getContainingDeclaration(),
|
||||
fqName.shortName(),
|
||||
Modality.FINAL,
|
||||
ClassKind.CLASS,
|
||||
Collections.singleton(samType.getType()),
|
||||
SourceElement.NO_SOURCE
|
||||
);
|
||||
|
||||
@@ -67,7 +67,7 @@ public abstract class SignatureCollectingClassBuilderFactory(
|
||||
|
||||
override fun done() {
|
||||
for ((signature, elementsAndDescriptors) in signatures.entrySet()) {
|
||||
if (elementsAndDescriptors.size == 1) continue // no clash
|
||||
if (elementsAndDescriptors.size() == 1) continue // no clash
|
||||
handleClashingSignatures(ConflictingJvmDeclarationsData(
|
||||
classInternalName,
|
||||
classCreatedFor,
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.ArraysKt;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty;
|
||||
@@ -46,7 +45,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
@@ -504,19 +502,19 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
ReceiverValue callExtensionReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver();
|
||||
if (callDispatchReceiver != null || callExtensionReceiver != null
|
||||
if (callDispatchReceiver.exists() || callExtensionReceiver.exists()
|
||||
|| isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) {
|
||||
ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter();
|
||||
ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter();
|
||||
|
||||
if (descriptor.getOriginal() instanceof SamAdapterExtensionFunctionDescriptor) {
|
||||
callDispatchReceiver = callExtensionReceiver;
|
||||
callExtensionReceiver = null;
|
||||
callExtensionReceiver = ReceiverValue.NO_RECEIVER;
|
||||
dispatchReceiverParameter = extensionReceiverParameter;
|
||||
extensionReceiverParameter = null;
|
||||
}
|
||||
|
||||
boolean hasExtensionReceiver = callExtensionReceiver != null;
|
||||
boolean hasExtensionReceiver = callExtensionReceiver.exists();
|
||||
StackValue dispatchReceiver = platformStaticCallIfPresent(
|
||||
genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, callDispatchReceiver, false),
|
||||
descriptor
|
||||
@@ -534,11 +532,11 @@ public abstract class StackValue {
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull ResolvedCall resolvedCall,
|
||||
@Nullable Callable callableMethod,
|
||||
@Nullable ReceiverValue receiverValue,
|
||||
ReceiverValue receiverValue,
|
||||
boolean isExtension
|
||||
) {
|
||||
if (receiver == none()) {
|
||||
if (receiverValue != null) {
|
||||
if (receiverValue.exists()) {
|
||||
return codegen.generateReceiverValue(receiverValue, false);
|
||||
}
|
||||
else if (isLocalFunCall(callableMethod) && !isExtension) {
|
||||
@@ -550,7 +548,7 @@ public abstract class StackValue {
|
||||
return singleton(((ImportedFromObjectCallableDescriptor) resolvedCall.getResultingDescriptor()).getContainingObject(), codegen.typeMapper);
|
||||
}
|
||||
}
|
||||
else if (receiverValue != null) {
|
||||
else if (receiverValue.exists()) {
|
||||
return receiver;
|
||||
}
|
||||
return none();
|
||||
@@ -599,7 +597,11 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
public static Field singletonViaInstance(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
|
||||
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper), none());
|
||||
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false), none());
|
||||
}
|
||||
|
||||
public static Field oldSingleton(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
|
||||
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true), none());
|
||||
}
|
||||
|
||||
public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) {
|
||||
@@ -832,7 +834,7 @@ public abstract class StackValue {
|
||||
|
||||
ReceiverValue receiverParameter = (ReceiverValue) resolvedGetCall.getExtensionReceiver();
|
||||
int receiverIndex = -1;
|
||||
if (receiverParameter != null) {
|
||||
if (receiverParameter.exists()) {
|
||||
Type type = codegen.typeMapper.mapType(receiverParameter.getType());
|
||||
receiverIndex = frame.enterTemp(type);
|
||||
v.store(receiverIndex, type);
|
||||
@@ -840,7 +842,7 @@ public abstract class StackValue {
|
||||
|
||||
ReceiverValue dispatchReceiver = resolvedGetCall.getDispatchReceiver();
|
||||
int thisIndex = -1;
|
||||
if (dispatchReceiver != null) {
|
||||
if (dispatchReceiver.exists()) {
|
||||
thisIndex = frame.enterTemp(OBJECT_TYPE);
|
||||
v.store(thisIndex, OBJECT_TYPE);
|
||||
}
|
||||
@@ -861,14 +863,14 @@ public abstract class StackValue {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
if (resolvedSetCall.getDispatchReceiver() != null) {
|
||||
if (resolvedSetCall.getExtensionReceiver() != null) {
|
||||
if (resolvedSetCall.getDispatchReceiver().exists()) {
|
||||
if (resolvedSetCall.getExtensionReceiver().exists()) {
|
||||
codegen.generateReceiverValue(resolvedSetCall.getDispatchReceiver(), false).put(OBJECT_TYPE, v);
|
||||
}
|
||||
v.load(realReceiverIndex, realReceiverType);
|
||||
}
|
||||
else {
|
||||
if (resolvedSetCall.getExtensionReceiver() != null) {
|
||||
if (resolvedSetCall.getExtensionReceiver().exists()) {
|
||||
v.load(realReceiverIndex, realReceiverType);
|
||||
}
|
||||
else {
|
||||
@@ -968,8 +970,8 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.getDispatchReceiver() != null) {
|
||||
if (call.getExtensionReceiver() != null) {
|
||||
if (call.getDispatchReceiver().exists()) {
|
||||
if (call.getExtensionReceiver().exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1088,12 +1090,6 @@ public abstract class StackValue {
|
||||
else {
|
||||
getter.genInvokeInstruction(v);
|
||||
coerce(getter.getReturnType(), type, v);
|
||||
|
||||
KotlinType returnType = descriptor.getReturnType();
|
||||
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
|
||||
v.aconst(null);
|
||||
v.athrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,6 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
correctContainerForLambda(callableDescriptor, element),
|
||||
Name.special("<closure-" + simpleName + ">"),
|
||||
Modality.FINAL,
|
||||
ClassKind.CLASS,
|
||||
supertypes,
|
||||
KotlinSourceElementKt.toSourceElement(element)
|
||||
);
|
||||
@@ -129,7 +128,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
if (element instanceof KtObjectDeclaration &&
|
||||
element.getParent() instanceof KtObjectLiteralExpression &&
|
||||
child instanceof KtSuperTypeList) {
|
||||
child instanceof KtDelegationSpecifierList) {
|
||||
// If we're passing an anonymous object's super call, it means "container" is ConstructorDescriptor of that object.
|
||||
// To reach outer context, we should call getContainingDeclaration() twice
|
||||
// TODO: this is probably not entirely correct, mostly because DECLARATION_TO_DESCRIPTOR can return null
|
||||
@@ -178,7 +177,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
@Override
|
||||
public void visitEnumEntry(@NotNull KtEnumEntry enumEntry) {
|
||||
if (enumEntry.getDeclarations().isEmpty()) {
|
||||
for (KtSuperTypeListEntry specifier : enumEntry.getSuperTypeListEntries()) {
|
||||
for (KtDelegationSpecifier specifier : enumEntry.getDelegationSpecifiers()) {
|
||||
specifier.accept(this);
|
||||
}
|
||||
return;
|
||||
@@ -248,7 +247,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
String name = inventAnonymousClassName();
|
||||
recordClosure(classDescriptor, name);
|
||||
|
||||
KtSuperTypeList delegationSpecifierList = object.getSuperTypeList();
|
||||
KtDelegationSpecifierList delegationSpecifierList = object.getDelegationSpecifierList();
|
||||
if (delegationSpecifierList != null) {
|
||||
delegationSpecifierList.accept(this);
|
||||
}
|
||||
@@ -264,8 +263,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambdaExpression(@NotNull KtLambdaExpression lambdaExpression) {
|
||||
KtFunctionLiteral functionLiteral = lambdaExpression.getFunctionLiteral();
|
||||
public void visitFunctionLiteralExpression(@NotNull KtFunctionLiteralExpression expression) {
|
||||
KtFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
FunctionDescriptor functionDescriptor =
|
||||
(FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, functionLiteral);
|
||||
// working around a problem with shallow analysis
|
||||
@@ -278,7 +277,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name);
|
||||
super.visitLambdaExpression(lambdaExpression);
|
||||
super.visitFunctionLiteralExpression(expression);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
@@ -432,8 +431,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSuperTypeCallEntry(@NotNull KtSuperTypeCallEntry call) {
|
||||
super.visitSuperTypeCallEntry(call);
|
||||
public void visitDelegationToSuperCallSpecifier(@NotNull KtDelegatorToSuperCall call) {
|
||||
super.visitDelegationToSuperCallSpecifier(call);
|
||||
checkSamCall(call);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,9 +61,6 @@ public final class PsiCodegenPredictor {
|
||||
// TODO: Method won't work for declarations inside companion objects
|
||||
// TODO: Method won't give correct class name for traits implementations
|
||||
|
||||
if (declaration instanceof KtPropertyAccessor) {
|
||||
return getPredefinedJvmInternalName(((KtPropertyAccessor) declaration).getProperty(), fileClassesProvider);
|
||||
}
|
||||
KtDeclaration parentDeclaration = KtStubbedPsiUtil.getContainingDeclaration(declaration);
|
||||
|
||||
String parentInternalName;
|
||||
@@ -76,8 +73,8 @@ public final class PsiCodegenPredictor {
|
||||
else {
|
||||
KtFile containingFile = declaration.getContainingKtFile();
|
||||
|
||||
if (declaration instanceof KtNamedFunction || declaration instanceof KtProperty) {
|
||||
Name name = ((KtNamedDeclaration) declaration).getNameAsName();
|
||||
if (declaration instanceof KtNamedFunction) {
|
||||
Name name = ((KtNamedFunction) declaration).getNameAsName();
|
||||
return name == null ? null : FileClasses.getFileClassInternalName(fileClassesProvider, containingFile) + "$" + name.asString();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,20 +19,16 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.backend.common.bridges.DescriptorBasedFunctionHandle
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.*
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
import java.util.*
|
||||
|
||||
@@ -51,7 +47,7 @@ object BuiltinSpecialBridgesUtil {
|
||||
|
||||
val functionHandle = DescriptorBasedFunctionHandle(function)
|
||||
val fake = !functionHandle.isDeclaration
|
||||
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
|
||||
val overriddenBuiltin = function.getOverriddenBuiltinWithDifferentJvmDescriptor()!!
|
||||
|
||||
val reachableDeclarations = findAllReachableDeclarations(function)
|
||||
|
||||
@@ -99,7 +95,7 @@ object BuiltinSpecialBridgesUtil {
|
||||
): Boolean {
|
||||
if (BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(this) == null) return false
|
||||
|
||||
val builtin = getOverriddenBuiltinReflectingJvmDescriptor()!!
|
||||
val builtin = getOverriddenBuiltinWithDifferentJvmDescriptor()!!
|
||||
return signatureByDescriptor(this) == signatureByDescriptor(builtin)
|
||||
}
|
||||
}
|
||||
@@ -134,7 +130,7 @@ private fun <Signature> needGenerateSpecialBridge(
|
||||
|| originalOverridden.containingDeclaration is JavaClassDescriptor
|
||||
|| DescriptorUtils.isInterface(originalOverridden.containingDeclaration)) return@firstOverridden false
|
||||
|
||||
val overriddenSpecial = originalOverridden.getOverriddenBuiltinReflectingJvmDescriptor()?.original ?: return@firstOverridden false
|
||||
val overriddenSpecial = originalOverridden.getOverriddenBuiltinWithDifferentJvmDescriptor()?.original ?: return@firstOverridden false
|
||||
|
||||
signatureByDescriptor(originalOverridden) != signatureByDescriptor(overriddenSpecial)
|
||||
} != null) return false
|
||||
@@ -153,7 +149,12 @@ public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
|
||||
if (KtPsiUtil.deparenthesize(argumentExpression) !== element) return false
|
||||
|
||||
val candidateDescriptor = parentCall.getResolvedCall(bindingContext)?.candidateDescriptor as CallableMemberDescriptor?
|
||||
?: return false
|
||||
?: return false
|
||||
|
||||
return candidateDescriptor.getSpecialSignatureInfo()?.isObjectReplacedWithTypeParameter ?: false
|
||||
|
||||
if (candidateDescriptor.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ private fun List<PackageParts>.addCompiledParts(state: GenerationState): List<Pa
|
||||
mapping.findPackageParts(qualifier)?.run { parts.remove(name) }
|
||||
}
|
||||
|
||||
return (this + mapping.packageFqName2Parts.values)
|
||||
return (this + mapping.packageFqName2Parts.values())
|
||||
.groupBy { it.packageFqName }
|
||||
.map {
|
||||
val (packageFqName, packageParts) = it
|
||||
|
||||
@@ -17,29 +17,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
fun generateIsCheck(
|
||||
v: InstructionAdapter,
|
||||
kotlinType: KotlinType,
|
||||
asmType: Type
|
||||
type: KotlinType,
|
||||
generateInstanceOfInstruction: (InstructionAdapter) -> Unit
|
||||
) {
|
||||
if (TypeUtils.isNullableType(kotlinType)) {
|
||||
if (type.isMarkedNullable) {
|
||||
val nope = Label()
|
||||
val end = Label()
|
||||
|
||||
@@ -48,8 +35,7 @@ fun generateIsCheck(
|
||||
|
||||
ifnull(nope)
|
||||
|
||||
TypeIntrinsics.instanceOf(this, kotlinType, asmType)
|
||||
|
||||
generateInstanceOfInstruction(this)
|
||||
goTo(end)
|
||||
|
||||
mark(nope)
|
||||
@@ -60,69 +46,6 @@ fun generateIsCheck(
|
||||
}
|
||||
}
|
||||
else {
|
||||
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
|
||||
generateInstanceOfInstruction(v)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateAsCast(
|
||||
v: InstructionAdapter,
|
||||
kotlinType: KotlinType,
|
||||
asmType: Type,
|
||||
isSafe: Boolean
|
||||
) {
|
||||
if (!isSafe) {
|
||||
if (!TypeUtils.isNullableType(kotlinType)) {
|
||||
generateNullCheckForNonSafeAs(v, kotlinType)
|
||||
}
|
||||
}
|
||||
else {
|
||||
with(v) {
|
||||
dup()
|
||||
TypeIntrinsics.instanceOf(v, kotlinType, asmType)
|
||||
val ok = Label()
|
||||
ifne(ok)
|
||||
pop()
|
||||
aconst(null)
|
||||
mark(ok)
|
||||
}
|
||||
}
|
||||
|
||||
TypeIntrinsics.checkcast(v, kotlinType, asmType, isSafe)
|
||||
}
|
||||
|
||||
private fun generateNullCheckForNonSafeAs(
|
||||
v: InstructionAdapter,
|
||||
type: KotlinType
|
||||
) {
|
||||
with(v) {
|
||||
dup()
|
||||
val nonnull = Label()
|
||||
ifnonnull(nonnull)
|
||||
AsmUtil.genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type))
|
||||
mark(nonnull)
|
||||
}
|
||||
}
|
||||
|
||||
public fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String?
|
||||
= valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
||||
|
||||
fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObjectDeclaration, outerContext: FieldOwnerContext<*>, state: GenerationState) {
|
||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, companion)
|
||||
|
||||
if (descriptor == null || ErrorUtils.isError(descriptor)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
|
||||
return
|
||||
}
|
||||
val properties = companion.declarations.filterIsInstance<KtProperty>()
|
||||
|
||||
properties.forEach {
|
||||
val variableDescriptor = state.bindingContext.get(BindingContext.VARIABLE, it)
|
||||
if (variableDescriptor is PropertyDescriptor) {
|
||||
outerContext.getFieldName(variableDescriptor, it.hasDelegate())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.context;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -28,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
||||
@@ -37,7 +37,7 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.NEED_SYNTHETIC_ACCESSOR;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
|
||||
|
||||
@@ -267,10 +267,6 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return new MultifileClassFacadeContext(descriptor, this, multifileClassType, filePartType);
|
||||
}
|
||||
|
||||
public ClassContext intoDefaultImplsClass(ClassDescriptor descriptor, ClassContext interfaceContext, GenerationState state) {
|
||||
return new DefaultImplsClassContext(state.getTypeMapper(), descriptor, OwnerKind.DEFAULT_IMPLS, this, null, interfaceContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
||||
if (descriptor.isCompanionObject()) {
|
||||
@@ -283,7 +279,11 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
ClassContext classContext = new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
||||
|
||||
if (descriptor.getCompanionObjectDescriptor() != null) {
|
||||
//We can't call descriptor.getCompanionObjectDescriptor() on light class generation
|
||||
// because it triggers companion light class generation via putting it to BindingContext.CLASS
|
||||
// (so MemberCodegen doesn't skip it in genClassOrObject).
|
||||
if (state.getTypeMapper().getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES &&
|
||||
descriptor.getCompanionObjectDescriptor() != null) {
|
||||
//We need to create companion object context ahead of time
|
||||
// because otherwise we can't generate synthetic accessor for private members in companion object
|
||||
classContext.intoClass(descriptor.getCompanionObjectDescriptor(), OwnerKind.IMPLEMENTATION, state);
|
||||
@@ -298,12 +298,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
@NotNull
|
||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this, null);
|
||||
return new MethodContext(descriptor, getContextKind(), this, null, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) {
|
||||
return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline);
|
||||
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this, null, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -365,24 +365,11 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
public <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D getAccessorForSuperCallIfNeeded(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
if (superCallTarget != null && !isJvmInterface(descriptor.getContainingDeclaration())) {
|
||||
CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext();
|
||||
CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + descriptor;
|
||||
if (c != afterInline.getParentContext()) {
|
||||
return (D) c.getAccessor(descriptor, superCallTarget);
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D getAccessor(
|
||||
@NotNull D possiblySubstitutedDescriptor,
|
||||
@@ -515,27 +502,32 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ReadOnly
|
||||
public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() {
|
||||
return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
public <D extends CallableMemberDescriptor> D accessibleDescriptor(
|
||||
@NotNull D descriptor,
|
||||
@Nullable ClassDescriptor superCallTarget
|
||||
) {
|
||||
CodegenContext properContext = getFirstCrossInlineOrNonInlineContext();
|
||||
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
|
||||
boolean isInliningContext = properContext.isInlineMethodContext();
|
||||
boolean isInliningContext = isInlineMethodContext();
|
||||
if (!isInliningContext && (
|
||||
!properContext.hasThisDescriptor() ||
|
||||
enclosing == properContext.getThisDescriptor() ||
|
||||
enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) {
|
||||
!hasThisDescriptor() ||
|
||||
enclosing == getThisDescriptor() ||
|
||||
enclosing == getClassOrPackageParentContext().getContextDescriptor())) {
|
||||
return descriptor;
|
||||
}
|
||||
return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext);
|
||||
|
||||
return accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext);
|
||||
}
|
||||
|
||||
public void recordSyntheticAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
||||
if (hasThisDescriptor() && Boolean.TRUE.equals(bindingContext.get(NEED_SYNTHETIC_ACCESSOR, descriptor))) {
|
||||
// Not a super call because neither constructors nor private members can be targets of super calls
|
||||
accessibleDescriptorIfNeeded(descriptor, /* superCallTarget = */ null, false);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -640,7 +632,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
||||
public CodegenContext findChildContext(@NotNull DeclarationDescriptor child) {
|
||||
return childContexts == null ? null : childContexts.get(child);
|
||||
}
|
||||
|
||||
@@ -648,12 +640,18 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return value instanceof StackValue.Field && ((StackValue.Field) value).isStaticPut;
|
||||
}
|
||||
|
||||
public boolean isInlineMethodContext() {
|
||||
private boolean isInsideInliningContext() {
|
||||
CodegenContext current = this;
|
||||
while (current != null) {
|
||||
if (current instanceof MethodContext && ((MethodContext) current).isInlineFunction()) {
|
||||
return true;
|
||||
}
|
||||
current = current.getParentContext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CodegenContext getFirstCrossInlineOrNonInlineContext() {
|
||||
return this;
|
||||
private boolean isInlineMethodContext() {
|
||||
return this instanceof MethodContext && ((MethodContext) this).isInlineFunction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,24 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
|
||||
public object CodegenContextUtil {
|
||||
@JvmStatic
|
||||
public fun getImplementationOwnerClassType(owner: CodegenContext<*>): Type? =
|
||||
when (owner) {
|
||||
is MultifileClassFacadeContext -> owner.filePartType
|
||||
is DelegatingFacadeContext -> owner.delegateToClassType
|
||||
is DelegatingToPartContext -> owner.implementationOwnerClassType
|
||||
else -> null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun getImplementationClassShortName(owner: CodegenContext<*>): String? =
|
||||
getImplementationOwnerClassType(owner)?.let { AsmUtil.shortNameByAsmType(it) }
|
||||
|
||||
@JvmStatic
|
||||
public fun isImplClassOwner(owner: CodegenContext<*>): Boolean =
|
||||
owner !is MultifileClassFacadeContext
|
||||
}
|
||||
owner !is DelegatingFacadeContext
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class ConstructorContext extends MethodContext {
|
||||
@NotNull CodegenContext parent,
|
||||
@Nullable MutableClosure closure
|
||||
) {
|
||||
super(contextDescriptor, kind, parent, closure);
|
||||
super(contextDescriptor, kind, parent, closure, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AccessorForCallableDescriptor
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
|
||||
class DefaultImplsClassContext(
|
||||
typeMapper: JetTypeMapper,
|
||||
contextDescriptor: ClassDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>?,
|
||||
localLookup: ((DeclarationDescriptor) -> Boolean)?,
|
||||
val interfaceContext: ClassContext
|
||||
) : ClassContext(typeMapper, contextDescriptor, contextKind, parentContext, localLookup) {
|
||||
|
||||
override fun getCompanionObjectContext(): CodegenContext<*>? {
|
||||
return interfaceContext.companionObjectContext
|
||||
}
|
||||
|
||||
override fun getAccessors(): Collection<AccessorForCallableDescriptor<*>> {
|
||||
val accessors = super.getAccessors()
|
||||
val alreadyExistKeys = accessors.map ({ Pair(it.calleeDescriptor, it.superCallTarget) })
|
||||
val filtered = interfaceContext.accessors.toMapBy({ Pair(it.calleeDescriptor, it.superCallTarget) }, { it }) - alreadyExistKeys
|
||||
return accessors + filtered.values
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.renderer
|
||||
package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
public interface Renderer<in O> {
|
||||
fun render(obj: O): String
|
||||
}
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
fun <O> Renderer(block: (O) -> String) = object : Renderer<O> {
|
||||
override fun render(obj: O) = block(obj)
|
||||
public interface DelegatingFacadeContext {
|
||||
@Nullable
|
||||
Type getDelegateToClassType();
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
|
||||
class InlineLambdaContext(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>,
|
||||
closure: MutableClosure?,
|
||||
val isCrossInline: Boolean
|
||||
) : MethodContext(functionDescriptor, contextKind, parentContext, closure) {
|
||||
|
||||
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
|
||||
if (isCrossInline) return this
|
||||
|
||||
val parent = parentContext as? ClosureContext ?:
|
||||
throw AssertionError("Parent of inlining lambda body should be ClosureContext, but: $parentContext")
|
||||
|
||||
val grandParent = parent.parentContext ?:
|
||||
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
|
||||
return grandParent.firstCrossInlineOrNonInlineContext
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
private final boolean isInliningLambda;
|
||||
private Label methodStartLabel;
|
||||
private Label methodEndLabel;
|
||||
|
||||
@@ -43,10 +44,12 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull OwnerKind contextKind,
|
||||
@NotNull CodegenContext parentContext,
|
||||
@Nullable MutableClosure closure
|
||||
@Nullable MutableClosure closure,
|
||||
boolean isInliningLambda
|
||||
) {
|
||||
super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure,
|
||||
parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
|
||||
this.isInliningLambda = isInliningLambda;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
}
|
||||
|
||||
@@ -114,10 +117,14 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
||||
return "Method: " + getContextDescriptor();
|
||||
}
|
||||
|
||||
public boolean isInlineMethodContext() {
|
||||
public boolean isInlineFunction() {
|
||||
return InlineUtil.isInline(getContextDescriptor());
|
||||
}
|
||||
|
||||
public boolean isInliningLambda() {
|
||||
return isInliningLambda;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FunctionDescriptor getFunctionDescriptor() {
|
||||
return functionDescriptor;
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class MultifileClassFacadeContext extends MultifileClassContextBase {
|
||||
public class MultifileClassFacadeContext extends MultifileClassContextBase implements DelegatingFacadeContext {
|
||||
public MultifileClassFacadeContext(
|
||||
PackageFragmentDescriptor descriptor,
|
||||
CodegenContext parent,
|
||||
@@ -28,4 +29,10 @@ public class MultifileClassFacadeContext extends MultifileClassContextBase {
|
||||
) {
|
||||
super(descriptor, parent, multifileClassType, filePartType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Type getDelegateToClassType() {
|
||||
return getFilePartType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class PackageContext extends FieldOwnerContext<PackageFragmentDescriptor> implements DelegatingToPartContext, FacadePartWithSourceFile {
|
||||
private final Type packagePartType;
|
||||
private final KtFile sourceFile;
|
||||
@Nullable private KtFile sourceFile;
|
||||
|
||||
public PackageContext(
|
||||
@NotNull PackageFragmentDescriptor contextDescriptor,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class PackageFacadeContext extends PackageContext implements DelegatingFacadeContext {
|
||||
private final Type publicFacadeType;
|
||||
|
||||
public PackageFacadeContext(
|
||||
@NotNull PackageFragmentDescriptor contextDescriptor,
|
||||
@NotNull CodegenContext parent,
|
||||
@NotNull Type packagePartType
|
||||
) {
|
||||
this(contextDescriptor, parent, packagePartType, packagePartType);
|
||||
}
|
||||
|
||||
public PackageFacadeContext(
|
||||
@NotNull PackageFragmentDescriptor contextDescriptor,
|
||||
@NotNull CodegenContext parent,
|
||||
@NotNull Type packagePartType,
|
||||
@NotNull Type publicFacadeType
|
||||
) {
|
||||
super(contextDescriptor, parent, packagePartType, null);
|
||||
|
||||
this.publicFacadeType = publicFacadeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Type getDelegateToClassType() {
|
||||
return getPackagePartType();
|
||||
}
|
||||
|
||||
public Type getPublicFacadeType() {
|
||||
return publicFacadeType;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.FieldInfo;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,7 +28,10 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.tree.*;
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -62,6 +66,8 @@ public class AnonymousObjectTransformer {
|
||||
|
||||
private final Map<String, List<String>> fieldNames = new HashMap<String, List<String>>();
|
||||
|
||||
private final TypeRemapper typeRemapper;
|
||||
|
||||
public AnonymousObjectTransformer(
|
||||
@NotNull String objectInternalName,
|
||||
@NotNull InliningContext inliningContext,
|
||||
@@ -76,20 +82,18 @@ public class AnonymousObjectTransformer {
|
||||
this.newLambdaType = newLambdaType;
|
||||
|
||||
reader = InlineCodegenUtil.buildClassReaderByInternalName(state, objectInternalName);
|
||||
typeRemapper = new TypeRemapper(inliningContext.typeMapping);
|
||||
transformationResult = InlineResult.create();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public InlineResult doTransform(@NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper) {
|
||||
final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>();
|
||||
ClassBuilder classBuilder = createClassBuilder();
|
||||
final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();
|
||||
|
||||
reader.accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
|
||||
@Override
|
||||
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
||||
InlineCodegenUtil.assertVersionNotGreaterThanJava6(version);
|
||||
|
||||
if (signature != null) {
|
||||
ReifiedTypeInliner.SignatureReificationResult signatureResult = inliningContext.reifedTypeInliner.reifySignature(signature);
|
||||
signature = signatureResult.getNewSignature();
|
||||
@@ -98,11 +102,6 @@ public class AnonymousObjectTransformer {
|
||||
super.visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(@NotNull String name, String outerName, String innerName, int access) {
|
||||
innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, String name, String desc) {
|
||||
InliningContext parent = inliningContext.getParent();
|
||||
@@ -164,7 +163,7 @@ public class AnonymousObjectTransformer {
|
||||
}
|
||||
else {
|
||||
//seems we can't do any clever mapping cause we don't know any about original class name
|
||||
sourceMapper = IdenticalSourceMapper.INSTANCE;
|
||||
sourceMapper = IdenticalSourceMapper.INSTANCE$;
|
||||
}
|
||||
if (sourceInfo != null && !InlineCodegenUtil.GENERATE_SMAP) {
|
||||
classBuilder.visitSource(sourceInfo, debugInfo);
|
||||
@@ -174,7 +173,7 @@ public class AnonymousObjectTransformer {
|
||||
if (sourceInfo != null) {
|
||||
classBuilder.visitSource(sourceInfo, debugInfo);
|
||||
}
|
||||
sourceMapper = IdenticalSourceMapper.INSTANCE;
|
||||
sourceMapper = IdenticalSourceMapper.INSTANCE$;
|
||||
}
|
||||
|
||||
ParametersBuilder allCapturedParamBuilder = ParametersBuilder.newBuilder();
|
||||
@@ -182,7 +181,7 @@ public class AnonymousObjectTransformer {
|
||||
List<CapturedParamInfo> additionalFakeParams =
|
||||
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
|
||||
anonymousObjectGen, parentRemapper);
|
||||
List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();
|
||||
List<MethodVisitor> deferringMethods = new ArrayList();
|
||||
|
||||
for (MethodNode next : methodsToTransform) {
|
||||
MethodVisitor deferringVisitor = newMethod(classBuilder, next);
|
||||
@@ -194,7 +193,7 @@ public class AnonymousObjectTransformer {
|
||||
String oldFunReturnType = returnType.getInternalName();
|
||||
String newFunReturnType = funResult.getChangedTypes().get(oldFunReturnType);
|
||||
if (newFunReturnType != null) {
|
||||
inliningContext.typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType);
|
||||
typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType);
|
||||
}
|
||||
}
|
||||
deferringMethods.add(deferringVisitor);
|
||||
@@ -208,10 +207,6 @@ public class AnonymousObjectTransformer {
|
||||
|
||||
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
|
||||
|
||||
for (InnerClassNode node : innerClassNodes) {
|
||||
classBuilder.getVisitor().visitInnerClass(node.name, node.outerName, node.innerName, node.access);
|
||||
}
|
||||
|
||||
classBuilder.done();
|
||||
|
||||
anonymousObjectGen.setNewLambdaType(newLambdaType);
|
||||
@@ -242,7 +237,7 @@ public class AnonymousObjectTransformer {
|
||||
@NotNull ParametersBuilder capturedBuilder,
|
||||
boolean isConstructor
|
||||
) {
|
||||
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode);
|
||||
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
|
||||
Parameters parameters = isConstructor ? capturedBuilder.buildParameters() : getMethodParametersWithCaptured(capturedBuilder, sourceNode);
|
||||
|
||||
RegeneratedLambdaFieldRemapper remapper =
|
||||
@@ -350,7 +345,7 @@ public class AnonymousObjectTransformer {
|
||||
@NotNull
|
||||
private ClassBuilder createClassBuilder() {
|
||||
ClassBuilder classBuilder = state.getFactory().newVisitor(NO_ORIGIN, newLambdaType, inliningContext.getRoot().callElement.getContainingFile());
|
||||
return new RemappingClassBuilder(classBuilder, inliningContext.typeRemapper);
|
||||
return new RemappingClassBuilder(classBuilder, typeRemapper);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -33,11 +33,9 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents;
|
||||
import org.jetbrains.kotlin.modules.TargetId;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
@@ -193,15 +191,11 @@ public class InlineCodegen extends CallGenerator {
|
||||
JetTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable(
|
||||
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
||||
|
||||
ClassId containerId = containingClasses.getImplClassId();
|
||||
VirtualFile file = InlineCodegenUtil.findVirtualFile(state, containerId);
|
||||
if (file == null) {
|
||||
throw new IllegalStateException("Couldn't find declaration file for " + containerId);
|
||||
}
|
||||
|
||||
nodeAndSMAP = InlineCodegenUtil.getMethodNode(
|
||||
file.contentsToByteArray(), asmMethod.getName(), asmMethod.getDescriptor(), containingClasses.getFacadeClassId()
|
||||
);
|
||||
VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable(containingClasses.getImplClassId(), state);
|
||||
nodeAndSMAP = InlineCodegenUtil.getMethodNode(file.contentsToByteArray(),
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
containingClasses.getFacadeClassId());
|
||||
|
||||
if (nodeAndSMAP == null) {
|
||||
throw new RuntimeException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
|
||||
@@ -251,7 +245,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) {
|
||||
MethodNode node = nodeAndSmap.getNode();
|
||||
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node);
|
||||
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions);
|
||||
generateClosuresBodies();
|
||||
|
||||
//through generation captured parameters will be added to invocationParamBuilder
|
||||
@@ -315,7 +309,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
MethodContext parentContext = codegen.getContext();
|
||||
|
||||
MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor, info.isCrossInline);
|
||||
MethodContext context = parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor);
|
||||
|
||||
JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor);
|
||||
Method asmMethod = jvmMethodSignature.getAsmMethod();
|
||||
@@ -544,34 +538,26 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
/*lambda or callable reference*/
|
||||
public boolean isInliningParameter(KtExpression expression, ValueParameterDescriptor valueParameterDescriptor) {
|
||||
public static boolean isInliningParameter(KtExpression expression, ValueParameterDescriptor valueParameterDescriptor) {
|
||||
//TODO deparenthisise typed
|
||||
KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression);
|
||||
|
||||
if (deparenthesized instanceof KtCallableReferenceExpression) {
|
||||
// TODO: support inline of property references passed to inlinable function parameters
|
||||
SimpleFunctionDescriptor functionReference = state.getBindingContext().get(BindingContext.FUNCTION, deparenthesized);
|
||||
if (functionReference == null) return false;
|
||||
}
|
||||
|
||||
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
|
||||
isInlinableParameterExpression(deparenthesized);
|
||||
}
|
||||
|
||||
protected static boolean isInlinableParameterExpression(KtExpression deparenthesized) {
|
||||
return deparenthesized instanceof KtLambdaExpression ||
|
||||
return deparenthesized instanceof KtFunctionLiteralExpression ||
|
||||
deparenthesized instanceof KtNamedFunction ||
|
||||
deparenthesized instanceof KtCallableReferenceExpression;
|
||||
}
|
||||
|
||||
public void rememberClosure(KtExpression expression, Type type, ValueParameterDescriptor parameter) {
|
||||
public void rememberClosure(KtExpression expression, Type type, int parameterIndex) {
|
||||
KtExpression lambda = KtPsiUtil.deparenthesize(expression);
|
||||
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
|
||||
|
||||
LambdaInfo info = new LambdaInfo(lambda, typeMapper);
|
||||
|
||||
LambdaInfo info = new LambdaInfo(lambda, typeMapper, parameter.isCrossinline());
|
||||
|
||||
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
|
||||
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameterIndex);
|
||||
closureInfo.setLambda(info);
|
||||
expressionMap.put(closureInfo.getIndex(), info);
|
||||
}
|
||||
@@ -644,7 +630,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
int parameterIndex
|
||||
) {
|
||||
if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
|
||||
rememberClosure(argumentExpression, parameterType, valueParameterDescriptor);
|
||||
rememberClosure(argumentExpression, parameterType, valueParameterDescriptor.getIndex());
|
||||
}
|
||||
else {
|
||||
StackValue value = codegen.gen(argumentExpression);
|
||||
@@ -792,7 +778,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void reorderArgumentsIfNeeded(
|
||||
@NotNull List<ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
|
||||
@NotNull List<? extends ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import kotlin.text.StringsKt;
|
||||
import kotlin.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
@@ -28,7 +29,6 @@ import org.jetbrains.kotlin.codegen.MemberCodegen;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -75,7 +75,6 @@ public class InlineCodegenUtil {
|
||||
public static final String INLINE_MARKER_FINALLY_END = "finallyEnd";
|
||||
public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined";
|
||||
public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun";
|
||||
public static final String INLINE_FUN_VAR_SUFFIX = "$iv";
|
||||
|
||||
@Nullable
|
||||
public static SMAPAndMethodNode getMethodNode(
|
||||
@@ -91,10 +90,6 @@ public class InlineCodegenUtil {
|
||||
lines[0] = Integer.MAX_VALUE;
|
||||
lines[1] = Integer.MIN_VALUE;
|
||||
cr.accept(new ClassVisitor(API) {
|
||||
@Override
|
||||
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
||||
assertVersionNotGreaterThanJava6(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(String source, String debug) {
|
||||
@@ -130,44 +125,40 @@ public class InlineCodegenUtil {
|
||||
return new SMAPAndMethodNode(node[0], smap);
|
||||
}
|
||||
|
||||
public static void assertVersionNotGreaterThanJava6(int version) {
|
||||
// TODO: report a proper diagnostic
|
||||
if (version > Opcodes.V1_6) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot inline bytecode of version " + version + ". " +
|
||||
"This compiler can only inline Java 1.6 bytecode (version " + Opcodes.V1_6 + ")"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initDefaultSourceMappingIfNeeded(
|
||||
@NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state
|
||||
) {
|
||||
if (!state.isInlineEnabled()) return;
|
||||
|
||||
CodegenContext<?> parentContext = context.getParentContext();
|
||||
while (parentContext != null) {
|
||||
if (parentContext.isInlineMethodContext()) {
|
||||
//just init default one to one mapping
|
||||
codegen.getOrCreateSourceMapper();
|
||||
break;
|
||||
public static void initDefaultSourceMappingIfNeeded(@NotNull CodegenContext context, @NotNull MemberCodegen codegen, @NotNull GenerationState state) {
|
||||
if (state.isInlineEnabled()) {
|
||||
CodegenContext<?> parentContext = context.getParentContext();
|
||||
while (parentContext != null) {
|
||||
if (parentContext instanceof MethodContext) {
|
||||
if (((MethodContext) parentContext).isInlineFunction()) {
|
||||
//just init default one to one mapping
|
||||
codegen.getOrCreateSourceMapper();
|
||||
break;
|
||||
}
|
||||
}
|
||||
parentContext = parentContext.getParentContext();
|
||||
}
|
||||
parentContext = parentContext.getParentContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile findVirtualFile(@NotNull GenerationState state, @NotNull ClassId classId) {
|
||||
return JvmVirtualFileFinder.SERVICE.getInstance(state.getProject()).findVirtualFileWithHeader(classId);
|
||||
@NotNull
|
||||
public static VirtualFile getVirtualFileForCallable(@NotNull ClassId containerClassId, @NotNull GenerationState state) {
|
||||
JvmVirtualFileFinder fileFinder = JvmVirtualFileFinder.SERVICE.getInstance(state.getProject());
|
||||
VirtualFile file = fileFinder.findVirtualFileWithHeader(containerClassId);
|
||||
if (file == null) {
|
||||
throw new IllegalStateException("Couldn't find declaration file for " + containerClassId);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile findVirtualFileImprecise(@NotNull GenerationState state, @NotNull String internalClassName) {
|
||||
public static VirtualFile findVirtualFile(@NotNull Project project, @NotNull String internalClassName) {
|
||||
FqName packageFqName = JvmClassName.byInternalName(internalClassName).getPackageFqName();
|
||||
String classNameWithDollars = StringsKt.substringAfterLast(internalClassName, "/", internalClassName);
|
||||
JvmVirtualFileFinder fileFinder = JvmVirtualFileFinder.SERVICE.getInstance(project);
|
||||
//TODO: we cannot construct proper classId at this point, we need to read InnerClasses info from class file
|
||||
// we construct valid.package.name/RelativeClassNameAsSingleName that should work in compiler, but fails for inner classes in IDE
|
||||
return findVirtualFile(state, new ClassId(packageFqName, Name.identifier(classNameWithDollars)));
|
||||
return fileFinder.findVirtualFileWithHeader(new ClassId(packageFqName, Name.identifier(classNameWithDollars)));
|
||||
}
|
||||
|
||||
public static String getInlineName(
|
||||
@@ -319,7 +310,8 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull InsnList instructions, @NotNull AbstractInsnNode beforeNode) {
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) {
|
||||
InsnList instructions = to.instructions;
|
||||
ListIterator<AbstractInsnNode> iterator = from.instructions.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
AbstractInsnNode next = iterator.next();
|
||||
@@ -327,10 +319,6 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) {
|
||||
insertNodeBefore(from, to.instructions, beforeNode);
|
||||
}
|
||||
|
||||
|
||||
public static MethodNode createEmptyMethodNode() {
|
||||
return new MethodNode(API, 0, "fake", "()V", null, null);
|
||||
@@ -369,9 +357,8 @@ public class InlineCodegenUtil {
|
||||
OutputFile outputFile = state.getFactory().get(internalName + ".class");
|
||||
if (outputFile != null) {
|
||||
return new ClassReader(outputFile.asByteArray());
|
||||
}
|
||||
else {
|
||||
VirtualFile file = findVirtualFileImprecise(state, internalName);
|
||||
} else {
|
||||
VirtualFile file = findVirtualFile(state.getProject(), internalName);
|
||||
if (file == null) {
|
||||
throw new RuntimeException("Couldn't find virtual file for " + internalName);
|
||||
}
|
||||
@@ -407,7 +394,7 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
|
||||
public static boolean isFinallyMarkerRequired(@NotNull MethodContext context) {
|
||||
return context.isInlineMethodContext() || context instanceof InlineLambdaContext;
|
||||
return context.isInlineFunction() || context.isInliningLambda();
|
||||
}
|
||||
|
||||
public static int getConstant(AbstractInsnNode ins) {
|
||||
|
||||
@@ -35,7 +35,7 @@ public class InliningContext {
|
||||
|
||||
public final NameGenerator nameGenerator;
|
||||
|
||||
public final TypeRemapper typeRemapper;
|
||||
public final Map<String, String> typeMapping;
|
||||
|
||||
public final ReifiedTypeInliner reifedTypeInliner;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class InliningContext {
|
||||
@NotNull Map<Integer, LambdaInfo> map,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull NameGenerator nameGenerator,
|
||||
@NotNull TypeRemapper typeRemapper,
|
||||
@NotNull Map<String, String> typeMapping,
|
||||
@NotNull ReifiedTypeInliner reifedTypeInliner,
|
||||
boolean isInliningLambda,
|
||||
boolean classRegeneration
|
||||
@@ -57,7 +57,7 @@ public class InliningContext {
|
||||
expressionMap = map;
|
||||
this.state = state;
|
||||
this.nameGenerator = nameGenerator;
|
||||
this.typeRemapper = typeRemapper;
|
||||
this.typeMapping = typeMapping;
|
||||
this.reifedTypeInliner = reifedTypeInliner;
|
||||
this.isInliningLambda = isInliningLambda;
|
||||
this.classRegeneration = classRegeneration;
|
||||
@@ -78,12 +78,13 @@ public class InliningContext {
|
||||
}
|
||||
|
||||
public InliningContext subInlineWithClassRegeneration(@NotNull NameGenerator generator,
|
||||
@NotNull Map<String, String> newTypeMappings,
|
||||
@NotNull Map<String, String> additionalTypeMappings,
|
||||
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
|
||||
) {
|
||||
Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
|
||||
newTypeMappings.putAll(additionalTypeMappings);
|
||||
return new RegeneratedClassContext(this, expressionMap, state, generator,
|
||||
new TypeRemapper(typeRemapper, newTypeMappings),
|
||||
reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
|
||||
newTypeMappings, reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
|
||||
}
|
||||
|
||||
public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) {
|
||||
@@ -96,8 +97,10 @@ public class InliningContext {
|
||||
boolean isInliningLambda,
|
||||
boolean isRegeneration
|
||||
) {
|
||||
Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
|
||||
newTypeMappings.putAll(additionalTypeMappings);
|
||||
return new InliningContext(this, expressionMap, state, generator,
|
||||
new TypeRemapper(typeRemapper, additionalTypeMappings), reifedTypeInliner, isInliningLambda, isRegeneration);
|
||||
newTypeMappings, reifedTypeInliner, isInliningLambda, isRegeneration);
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteralExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
@@ -50,8 +50,6 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner {
|
||||
|
||||
private final CalculatedClosure closure;
|
||||
|
||||
public final boolean isCrossInline;
|
||||
|
||||
private SMAPAndMethodNode node;
|
||||
|
||||
private List<CapturedParamDesc> capturedVars;
|
||||
@@ -62,10 +60,9 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner {
|
||||
|
||||
private final Type closureClassType;
|
||||
|
||||
LambdaInfo(@NotNull KtExpression expr, @NotNull JetTypeMapper typeMapper, boolean isCrossInline) {
|
||||
this.isCrossInline = isCrossInline;
|
||||
this.expression = expr instanceof KtLambdaExpression ?
|
||||
((KtLambdaExpression) expr).getFunctionLiteral() : expr;
|
||||
LambdaInfo(@NotNull KtExpression expr, @NotNull JetTypeMapper typeMapper) {
|
||||
this.expression = expr instanceof KtFunctionLiteralExpression ?
|
||||
((KtFunctionLiteralExpression) expr).getFunctionLiteral() : expr;
|
||||
|
||||
this.typeMapper = typeMapper;
|
||||
BindingContext bindingContext = typeMapper.getBindingContext();
|
||||
|
||||
@@ -97,6 +97,10 @@ public class LocalVarRemapper {
|
||||
//add entries only for shifted vars
|
||||
if (SHIFT == info.status) {
|
||||
int newIndex = ((StackValue.Local) info.value).index;
|
||||
if (newIndex != 0 && "this".equals(name)) {
|
||||
/*skip additional this for now*/
|
||||
return;
|
||||
}
|
||||
mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class MethodInliner {
|
||||
public MethodInliner(
|
||||
@NotNull MethodNode node,
|
||||
@NotNull Parameters parameters,
|
||||
@NotNull InliningContext inliningContext,
|
||||
@NotNull InliningContext parent,
|
||||
@NotNull FieldRemapper nodeRemapper,
|
||||
boolean isSameModule,
|
||||
@NotNull String errorPrefix,
|
||||
@@ -86,12 +86,12 @@ public class MethodInliner {
|
||||
) {
|
||||
this.node = node;
|
||||
this.parameters = parameters;
|
||||
this.inliningContext = inliningContext;
|
||||
this.inliningContext = parent;
|
||||
this.nodeRemapper = nodeRemapper;
|
||||
this.isSameModule = isSameModule;
|
||||
this.errorPrefix = errorPrefix;
|
||||
this.sourceMapper = sourceMapper;
|
||||
this.typeMapper = inliningContext.state.getTypeMapper();
|
||||
this.typeMapper = parent.state.getTypeMapper();
|
||||
this.result = InlineResult.create();
|
||||
}
|
||||
|
||||
@@ -153,9 +153,8 @@ public class MethodInliner {
|
||||
|
||||
final Iterator<AnonymousObjectGeneration> iterator = anonymousObjectGenerations.iterator();
|
||||
|
||||
final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping);
|
||||
RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode,
|
||||
remapper);
|
||||
new TypeRemapper(currentTypeMapping));
|
||||
|
||||
final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
|
||||
InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) {
|
||||
@@ -168,7 +167,7 @@ public class MethodInliner {
|
||||
//TODO: need poping of type but what to do with local funs???
|
||||
String oldClassName = anonymousObjectGen.getOwnerInternalName();
|
||||
String newClassName = inliningContext.nameGenerator.genLambdaClassName();
|
||||
remapper.addMapping(oldClassName, newClassName);
|
||||
currentTypeMapping.put(oldClassName, newClassName);
|
||||
AnonymousObjectTransformer transformer =
|
||||
new AnonymousObjectTransformer(oldClassName,
|
||||
inliningContext
|
||||
@@ -262,14 +261,7 @@ public class MethodInliner {
|
||||
visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(),
|
||||
"$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor());
|
||||
}
|
||||
String newInternalName = anonymousObjectGen.getNewLambdaType().getInternalName();
|
||||
super.visitMethodInsn(opcode, newInternalName, name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
|
||||
|
||||
//TODO: add new inner class also for other contexts
|
||||
if (inliningContext.getParent() instanceof RegeneratedClassContext) {
|
||||
inliningContext.getParent().typeRemapper.addAdditionalMappings(anonymousObjectGen.getOwnerInternalName(), newInternalName);
|
||||
}
|
||||
|
||||
super.visitMethodInsn(opcode, anonymousObjectGen.getNewLambdaType().getInternalName(), name, anonymousObjectGen.getNewConstructorDescriptor(), itf);
|
||||
anonymousObjectGen = null;
|
||||
} else {
|
||||
super.visitMethodInsn(opcode, changeOwnerForExternalPackage(owner, opcode), name, desc, itf);
|
||||
@@ -361,9 +353,7 @@ public class MethodInliner {
|
||||
@NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index
|
||||
) {
|
||||
if (isInliningLambda || InlineCodegenUtil.GENERATE_SMAP) {
|
||||
String varSuffix = inliningContext.isRoot() && !InlineCodegenUtil.isFakeLocalVariableForInline(name) ? INLINE_FUN_VAR_SUFFIX : "";
|
||||
String varName = !varSuffix.isEmpty() && name.equals("this") ? name + "_" : name;
|
||||
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index));
|
||||
super.visitLocalVariable(name, desc, signature, start, end, getNewIndex(index));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -559,7 +549,7 @@ public class MethodInliner {
|
||||
}
|
||||
|
||||
private boolean isAlreadyRegenerated(@NotNull String owner) {
|
||||
return inliningContext.typeRemapper.hasNoAdditionalMapping(owner);
|
||||
return inliningContext.typeMapping.containsKey(owner);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -54,10 +54,10 @@ internal class Parameters(val real: List<ParameterInfo>, val captured: List<Capt
|
||||
}
|
||||
|
||||
private fun get(index: Int): ParameterInfo {
|
||||
if (index < real.size) {
|
||||
if (index < real.size()) {
|
||||
return real.get(index)
|
||||
}
|
||||
return captured.get(index - real.size)
|
||||
return captured.get(index - real.size())
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<ParameterInfo> {
|
||||
|
||||
@@ -35,18 +35,18 @@ internal class ParametersBuilder private constructor(){
|
||||
private var nextCaptured = 0
|
||||
|
||||
fun addThis(type: Type, skipped: Boolean): ParameterInfo {
|
||||
val info = ParameterInfo(type, skipped, nextValueParameterIndex, -1, valueAndHiddenParams.size)
|
||||
val info = ParameterInfo(type, skipped, nextValueParameterIndex, -1, valueAndHiddenParams.size())
|
||||
addParameter(info)
|
||||
return info
|
||||
}
|
||||
|
||||
fun addNextParameter(type: Type, skipped: Boolean, remapValue: StackValue?): ParameterInfo {
|
||||
return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue, valueAndHiddenParams.size))
|
||||
return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue, valueAndHiddenParams.size()))
|
||||
}
|
||||
|
||||
fun addNextValueParameter(type: Type, skipped: Boolean, remapValue: StackValue?, parameterIndex: Int): ParameterInfo {
|
||||
return addParameter(ParameterInfo(type, skipped, nextValueParameterIndex, remapValue,
|
||||
if (parameterIndex == -1) valueAndHiddenParams.size else { parameterIndex + valueParamStart }))
|
||||
if (parameterIndex == -1) valueAndHiddenParams.size() else { parameterIndex + valueParamStart }))
|
||||
}
|
||||
|
||||
fun addCapturedParam(
|
||||
@@ -102,7 +102,7 @@ internal class ParametersBuilder private constructor(){
|
||||
}
|
||||
|
||||
fun markValueParametesStart(){
|
||||
this.valueParamStart = valueAndHiddenParams.size
|
||||
this.valueParamStart = valueAndHiddenParams.size()
|
||||
}
|
||||
|
||||
fun listCaptured(): List<CapturedParamInfo> {
|
||||
|
||||
@@ -30,12 +30,12 @@ public class RegeneratedClassContext extends InliningContext {
|
||||
@NotNull Map<Integer, LambdaInfo> map,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull NameGenerator nameGenerator,
|
||||
@NotNull TypeRemapper typeRemapper,
|
||||
@NotNull Map<String, String> typeMapping,
|
||||
@NotNull ReifiedTypeInliner reifiedTypeInliner,
|
||||
boolean isInliningLambda,
|
||||
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
|
||||
) {
|
||||
super(parent, map, state, nameGenerator, typeRemapper, reifiedTypeInliner, isInliningLambda, true);
|
||||
super(parent, map, state, nameGenerator, typeMapping, reifiedTypeInliner, isInliningLambda, true);
|
||||
this.anonymousObjectGeneration = anonymousObjectGeneration;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,40 +16,36 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.generateAsCast
|
||||
import org.jetbrains.kotlin.codegen.generateIsCheck
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.signature.SignatureReader
|
||||
import org.jetbrains.org.objectweb.asm.signature.SignatureWriter
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
|
||||
private class ParameterNameAndNullability(val name: String, val nullable: Boolean)
|
||||
|
||||
public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) {
|
||||
|
||||
enum class OperationKind {
|
||||
NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS;
|
||||
|
||||
val id: Int get() = ordinal
|
||||
val isTypeNullabilityAware: Boolean get() = this == AS || this == IS
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
public val REIFIED_OPERATION_MARKER_METHOD_NAME = "reifiedOperationMarker"
|
||||
@JvmField
|
||||
public val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME = "needClassReification"
|
||||
public val NEW_ARRAY_MARKER_METHOD_NAME: String = "reifyNewArray"
|
||||
public val CHECKCAST_MARKER_METHOD_NAME: String = "reifyCheckcast"
|
||||
public val SAFE_CHECKCAST_MARKER_METHOD_NAME: String = "reifySafeCheckcast"
|
||||
public val INSTANCEOF_MARKER_METHOD_NAME: String = "reifyInstanceof"
|
||||
public val JAVA_CLASS_MARKER_METHOD_NAME: String = "reifyJavaClass"
|
||||
public val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME: String = "needClassReification"
|
||||
|
||||
private fun isOperationReifiedMarker(insn: AbstractInsnNode) =
|
||||
isReifiedMarker(insn) { it == REIFIED_OPERATION_MARKER_METHOD_NAME }
|
||||
private val PARAMETRISED_MARKERS = ImmutableSet.of(
|
||||
NEW_ARRAY_MARKER_METHOD_NAME,
|
||||
CHECKCAST_MARKER_METHOD_NAME, SAFE_CHECKCAST_MARKER_METHOD_NAME,
|
||||
INSTANCEOF_MARKER_METHOD_NAME, JAVA_CLASS_MARKER_METHOD_NAME
|
||||
)
|
||||
|
||||
private fun isParametrisedReifiedMarker(insn: AbstractInsnNode) =
|
||||
isReifiedMarker(insn) { PARAMETRISED_MARKERS.contains(it) }
|
||||
|
||||
private fun isReifiedMarker(insn: AbstractInsnNode, namePredicate: (String) -> Boolean): Boolean {
|
||||
if (insn.getOpcode() != Opcodes.INVOKESTATIC || insn !is MethodInsnNode) return false
|
||||
@@ -70,20 +66,16 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
}
|
||||
}
|
||||
|
||||
private var maxStackSize = 0
|
||||
|
||||
/**
|
||||
* @return set of type parameters' identifiers contained in markers that should be reified further
|
||||
* e.g. when we're generating inline function containing reified T
|
||||
* and another function containing reifiable parts is inlined into that function
|
||||
*/
|
||||
public fun reifyInstructions(node: MethodNode): ReifiedTypeParametersUsages {
|
||||
public fun reifyInstructions(instructions: InsnList): ReifiedTypeParametersUsages {
|
||||
if (parametersMapping == null) return ReifiedTypeParametersUsages()
|
||||
val instructions = node.instructions
|
||||
maxStackSize = 0
|
||||
var result = ReifiedTypeParametersUsages()
|
||||
for (insn in instructions.toArray()) {
|
||||
if (isOperationReifiedMarker(insn)) {
|
||||
if (isParametrisedReifiedMarker(insn)) {
|
||||
val newName: String? = processReifyMarker(insn as MethodInsnNode, instructions)
|
||||
if (newName != null) {
|
||||
result.addUsedReifiedParameter(newName)
|
||||
@@ -91,7 +83,6 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
}
|
||||
}
|
||||
|
||||
node.maxStack = node.maxStack + maxStackSize
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -136,37 +127,30 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
* or null if it shouldn't
|
||||
*/
|
||||
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? {
|
||||
val operationKind = insn.operationKind ?: return null
|
||||
val parameter = insn.parameterNameAndNullability ?: return null
|
||||
val mapping = parametersMapping?.get(parameter.name) ?: return null
|
||||
val kotlinType =
|
||||
if (operationKind.isTypeNullabilityAware && parameter.nullable)
|
||||
TypeUtils.makeNullable(mapping.type)
|
||||
else
|
||||
mapping.type
|
||||
|
||||
val mapping = getTypeParameterMapping(insn) ?: return null
|
||||
|
||||
val asmType = mapping.asmType
|
||||
if (asmType != null) {
|
||||
val jetType = mapping.type ?: return null
|
||||
|
||||
// process* methods return false if marker should be reified further
|
||||
// or it's invalid (may be emitted explicitly in code)
|
||||
// they return true if instruction is reified and marker can be deleted
|
||||
if (when (operationKind) {
|
||||
OperationKind.NEW_ARRAY -> processNewArray(insn, asmType)
|
||||
OperationKind.AS -> processAs(insn, instructions, kotlinType, asmType, safe = false)
|
||||
OperationKind.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true)
|
||||
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
||||
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
|
||||
if (when (insn.name) {
|
||||
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType)
|
||||
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = false)
|
||||
SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = true)
|
||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, jetType, asmType)
|
||||
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
|
||||
else -> false
|
||||
}) {
|
||||
instructions.remove(insn.previous.previous!!) // PUSH operation ID
|
||||
instructions.remove(insn.previous!!) // PUSH type parameter
|
||||
instructions.remove(insn) // INVOKESTATIC marker method
|
||||
instructions.remove(insn.getPrevious()!!)
|
||||
instructions.remove(insn)
|
||||
}
|
||||
|
||||
return null
|
||||
} else {
|
||||
val nullableSuffix = if (operationKind.isTypeNullabilityAware && kotlinType.isMarkedNullable) "?" else ""
|
||||
instructions.set(insn.previous!!, LdcInsnNode(mapping.newName + nullableSuffix))
|
||||
instructions.set(insn.getPrevious()!!, LdcInsnNode(mapping.newName))
|
||||
return mapping.newName
|
||||
}
|
||||
}
|
||||
@@ -174,41 +158,17 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
private fun processNewArray(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY)
|
||||
|
||||
private fun processAs(insn: MethodInsnNode,
|
||||
instructions: InsnList,
|
||||
kotlinType: KotlinType,
|
||||
asmType: Type,
|
||||
safe: Boolean) =
|
||||
rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { stubCheckcast: AbstractInsnNode ->
|
||||
if (stubCheckcast !is TypeInsnNode) return false
|
||||
|
||||
val newMethodNode = MethodNode(InlineCodegenUtil.API)
|
||||
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe)
|
||||
|
||||
instructions.insert(insn, newMethodNode.instructions)
|
||||
instructions.remove(stubCheckcast)
|
||||
|
||||
// TODO: refine max stack calculation (it's not always as big as +4)
|
||||
maxStackSize = Math.max(maxStackSize, 4)
|
||||
|
||||
private fun processCheckcast(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type, safe: Boolean) =
|
||||
rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { instanceofInsn: AbstractInsnNode ->
|
||||
if (instanceofInsn !is TypeInsnNode) return false
|
||||
TypeIntrinsics.checkcast(instanceofInsn, instructions, jetType, asmType, safe)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processIs(insn: MethodInsnNode,
|
||||
instructions: InsnList,
|
||||
kotlinType: KotlinType,
|
||||
asmType: Type) =
|
||||
rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { stubInstanceOf: AbstractInsnNode ->
|
||||
if (stubInstanceOf !is TypeInsnNode) return false
|
||||
|
||||
val newMethodNode = MethodNode(InlineCodegenUtil.API)
|
||||
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType)
|
||||
|
||||
instructions.insert(insn, newMethodNode.instructions)
|
||||
instructions.remove(stubInstanceOf)
|
||||
|
||||
// TODO: refine max stack calculation (it's not always as big as +2)
|
||||
maxStackSize = Math.max(maxStackSize, 2)
|
||||
private fun processInstanceof(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type) =
|
||||
rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { instanceofInsn: AbstractInsnNode ->
|
||||
if (instanceofInsn !is TypeInsnNode) return false
|
||||
TypeIntrinsics.instanceOf(instanceofInsn, instructions, jetType, asmType)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -235,25 +195,19 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
private fun getParameterName(insn: MethodInsnNode): String? {
|
||||
val prev = insn.getPrevious()!!
|
||||
|
||||
private val MethodInsnNode.parameterNameAndNullability: ParameterNameAndNullability?
|
||||
get() {
|
||||
val prev = previous!!
|
||||
|
||||
val parameterNameWithFlag = when (prev.opcode) {
|
||||
return when (prev.getOpcode()) {
|
||||
Opcodes.LDC -> (prev as LdcInsnNode).cst as String
|
||||
else -> return null
|
||||
else -> null
|
||||
}
|
||||
|
||||
val parameterName = if (parameterNameWithFlag.endsWith("?")) parameterNameWithFlag.dropLast(1) else parameterNameWithFlag
|
||||
return ParameterNameAndNullability(parameterName, parameterName !== parameterNameWithFlag)
|
||||
}
|
||||
|
||||
private val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
|
||||
previous?.previous?.intConstant?.let {
|
||||
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
||||
private fun getTypeParameterMapping(insn: MethodInsnNode): ReifiedTypeParameterMapping? {
|
||||
return parametersMapping?.get(getParameterName(insn) ?: return null)
|
||||
}
|
||||
}
|
||||
|
||||
public class ReifiedTypeParameterMappings() {
|
||||
private val mappingsByName = hashMapOf<String, ReifiedTypeParameterMapping>()
|
||||
@@ -262,8 +216,8 @@ public class ReifiedTypeParameterMappings() {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type, asmType, newName = null, signature = signature)
|
||||
}
|
||||
|
||||
public fun addParameterMappingToNewParameter(name: String, type: KotlinType, newName: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = type, asmType = null, newName = newName, signature = null)
|
||||
public fun addParameterMappingToNewParameter(name: String, newName: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = null, asmType = null, newName = newName, signature = null)
|
||||
}
|
||||
|
||||
operator fun get(name: String): ReifiedTypeParameterMapping? {
|
||||
@@ -272,7 +226,7 @@ public class ReifiedTypeParameterMappings() {
|
||||
}
|
||||
|
||||
public 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 {
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class RootInliningContext extends InliningContext {
|
||||
@@ -37,7 +38,7 @@ public class RootInliningContext extends InliningContext {
|
||||
@NotNull String classNameToInline,
|
||||
@NotNull ReifiedTypeInliner inliner
|
||||
) {
|
||||
super(null, map, state, nameGenerator, TypeRemapper.createEmpty(), inliner, false, false);
|
||||
super(null, map, state, nameGenerator, Collections.<String, String>emptyMap(), inliner, false, false);
|
||||
this.callElement = callElement;
|
||||
this.startContext = startContext;
|
||||
this.classNameToInline = classNameToInline;
|
||||
|
||||
@@ -202,7 +202,7 @@ public open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val p
|
||||
private fun createKey(name: String, path: String) = "$name#$path"
|
||||
|
||||
override val resultMappings: List<FileMapping>
|
||||
get() = fileMappings.values.map { it.toFileMapping() }
|
||||
get() = fileMappings.values().map { it.toFileMapping() }
|
||||
|
||||
override fun visitSource(name: String, path: String) {
|
||||
lastVisited = fileMappings.getOrPut(createKey(name, path), { RawFileMapping(name, path) })
|
||||
|
||||
@@ -44,7 +44,7 @@ object SMAPParser {
|
||||
public fun parse(mappingInfo: String): SMAP {
|
||||
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()
|
||||
val lineSectionAnchor = mappingInfo.indexOf(SMAP.LINE_SECTION)
|
||||
val files = mappingInfo.substring(fileSectionStart, lineSectionAnchor)
|
||||
|
||||
@@ -63,7 +63,7 @@ object SMAPParser {
|
||||
}
|
||||
|
||||
|
||||
val lines = mappingInfo.substring(lineSectionAnchor + SMAP.LINE_SECTION.length, mappingInfo.indexOf(SMAP.END)).trim().split('\n')
|
||||
val lines = mappingInfo.substring(lineSectionAnchor + SMAP.LINE_SECTION.length(), mappingInfo.indexOf(SMAP.END)).trim().split('\n')
|
||||
for (lineMapping in lines) {
|
||||
/*only simple mapping now*/
|
||||
val targetSplit = lineMapping.indexOf(':')
|
||||
@@ -79,6 +79,6 @@ object SMAPParser {
|
||||
fileMappings[fileIndex]!!.addRangeMapping(RangeMapping(originalIndex, targetIndex, range))
|
||||
}
|
||||
|
||||
return SMAP(fileMappings.values.toList())
|
||||
return SMAP(fileMappings.values().toList())
|
||||
}
|
||||
}
|
||||
@@ -97,5 +97,5 @@ fun <T : IntervalWithHandler> doClustering(blocks: List<T>): List<TryBlockCluste
|
||||
cluster.blocks.add(block)
|
||||
}
|
||||
|
||||
return clusters.values.toList()
|
||||
return clusters.values().toList()
|
||||
}
|
||||
|
||||
@@ -23,43 +23,14 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TypeRemapper extends Remapper {
|
||||
//typeMapping field could be changed outside through method processing
|
||||
private final Map<String, String> typeMapping;
|
||||
|
||||
private Map<String, String> additionalMappings;
|
||||
|
||||
//typeMapping field could be changed outside through method processing
|
||||
private TypeRemapper(@NotNull Map<String, String> typeMapping) {
|
||||
//typeMapping could be changed outside through method processing
|
||||
public TypeRemapper(@NotNull Map<String, String> typeMapping) {
|
||||
this.typeMapping = typeMapping;
|
||||
}
|
||||
|
||||
public TypeRemapper(@NotNull TypeRemapper remapper, @NotNull Map<String, String> newTypeMappings) {
|
||||
this(createNewAndMerge(remapper, newTypeMappings));
|
||||
}
|
||||
|
||||
public static TypeRemapper createEmpty() {
|
||||
return new TypeRemapper(new HashMap<String, String>());
|
||||
}
|
||||
|
||||
public static TypeRemapper createFrom(Map<String, String> mappings) {
|
||||
return new TypeRemapper(mappings);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<String, String> createNewAndMerge(@NotNull TypeRemapper remapper, @NotNull Map<String, String> additionalTypeMappings) {
|
||||
Map<String, String> map = new HashMap<String, String>(remapper.typeMapping);
|
||||
map.putAll(additionalTypeMappings);
|
||||
return map;
|
||||
}
|
||||
|
||||
public void addMapping(String type, String newType) {
|
||||
typeMapping.put(type, newType);
|
||||
}
|
||||
|
||||
public boolean hasNoAdditionalMapping(String type) {
|
||||
return typeMapping.containsKey(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String map(String type) {
|
||||
String newType = typeMapping.get(type);
|
||||
|
||||
@@ -31,7 +31,7 @@ public class BinaryOp(private val opcode: Int) : IntrinsicMethod() {
|
||||
|
||||
override fun toCallable(method: CallableMethod): Callable {
|
||||
val returnType = method.returnType
|
||||
assert(method.getValueParameters().size == 1)
|
||||
assert(method.getValueParameters().size() == 1)
|
||||
val operandType = numberFunctionOperandType(returnType)
|
||||
val paramType = if (shift()) Type.INT_TYPE else operandType
|
||||
|
||||
|
||||
@@ -17,27 +17,25 @@
|
||||
package org.jetbrains.kotlin.codegen.intrinsics;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class IntrinsicMethods {
|
||||
public static final String INTRINSICS_CLASS_NAME = "kotlin/jvm/internal/Intrinsics";
|
||||
|
||||
private static final FqName KOTLIN_JVM = new FqName("kotlin.jvm");
|
||||
/* package */ static final FqNameUnsafe RECEIVER_PARAMETER_FQ_NAME = new FqNameUnsafe("T");
|
||||
|
||||
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
|
||||
private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus();
|
||||
private static final IntrinsicMethod NUMBER_CAST = new NumberCast();
|
||||
@@ -57,21 +55,18 @@ public class IntrinsicMethods {
|
||||
private static final ToString TO_STRING = new ToString();
|
||||
private static final Clone CLONE = new Clone();
|
||||
|
||||
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
|
||||
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
||||
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
|
||||
|
||||
public IntrinsicMethods() {
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "javaClass", 0, new JavaClassFunction());
|
||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, new JavaClassProperty());
|
||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty());
|
||||
intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorEnter", 1, MonitorInstruction.MONITOR_ENTER);
|
||||
intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorExit", 1, MonitorInstruction.MONITOR_EXIT);
|
||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.array, "isArrayOf", 0, new IsArrayOf());
|
||||
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOf", 1, new JavaClassArray());
|
||||
|
||||
// TODO: drop when deprecated kotlin.javaClass property is gone
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, new JavaClassProperty());
|
||||
namedMethods.put("kotlin.javaClass.function", new JavaClassFunction());
|
||||
namedMethods.put("kotlin.javaClass.property", new JavaClassProperty());
|
||||
namedMethods.put("kotlin.KClass.java.property", new KClassJavaProperty());
|
||||
namedMethods.put("kotlin.arrays.array", new JavaClassArray());
|
||||
namedMethods.put("kotlin.jvm.internal.unsafe.monitorEnter", MonitorInstruction.MONITOR_ENTER);
|
||||
namedMethods.put("kotlin.jvm.internal.unsafe.monitorExit", MonitorInstruction.MONITOR_EXIT);
|
||||
namedMethods.put("kotlin.jvm.isArrayOf", new IsArrayOf());
|
||||
|
||||
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
||||
for (Name method : primitiveCastMethods) {
|
||||
@@ -99,10 +94,6 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction(typeName, "equals", 1, EQUALS);
|
||||
declareIntrinsicFunction(typeName, "hashCode", 0, HASH_CODE);
|
||||
declareIntrinsicFunction(typeName, "toString", 0, TO_STRING);
|
||||
|
||||
intrinsicsMap.registerIntrinsic(
|
||||
BUILT_INS_PACKAGE_FQ_NAME, null, StringsKt.decapitalize(type.getArrayTypeName().asString()) + "Of", 1, new JavaClassArray()
|
||||
);
|
||||
}
|
||||
|
||||
declareBinaryOp("plus", IADD);
|
||||
@@ -182,6 +173,16 @@ public class IntrinsicMethods {
|
||||
|
||||
@Nullable
|
||||
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
||||
return intrinsicsMap.getIntrinsic(descriptor);
|
||||
IntrinsicMethod intrinsicMethod = intrinsicsMap.getIntrinsic(descriptor);
|
||||
if (intrinsicMethod != null) {
|
||||
return intrinsicMethod;
|
||||
}
|
||||
|
||||
String value = CompileTimeConstantUtils.getIntrinsicAnnotationArgument(descriptor);
|
||||
if (value != null) {
|
||||
return namedMethods.get(value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,10 @@ package org.jetbrains.kotlin.codegen.intrinsics;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
@@ -109,10 +112,6 @@ class IntrinsicsMap {
|
||||
ClassifierDescriptor classifier = receiverParameter.getType().getConstructor().getDeclarationDescriptor();
|
||||
if (classifier == null) return null;
|
||||
|
||||
if (classifier instanceof TypeParameterDescriptor) {
|
||||
return IntrinsicMethods.RECEIVER_PARAMETER_FQ_NAME;
|
||||
}
|
||||
|
||||
return DescriptorUtils.getFqName(classifier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class IsArrayOf : IntrinsicMethod() {
|
||||
val method = typeMapper.mapToCallableMethod(fd, false)
|
||||
|
||||
val builtIns = fd.module.builtIns
|
||||
val elementType = typeArguments.values.first()
|
||||
val elementType = typeArguments.values().first()
|
||||
val arrayKtType = builtIns.getArrayType(Variance.INVARIANT, elementType)
|
||||
val arrayType = typeMapper.mapType(arrayKtType)
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
public class JavaClassFunction : IntrinsicMethod() {
|
||||
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
||||
val javaClass = resolvedCall.getResultingDescriptor().getReturnType()!!.getArguments().first().getType()
|
||||
return object : IntrinsicCallable(getType(Class::class.java), listOf(), null, null) {
|
||||
return object : IntrinsicCallable(getType(javaClass<Class<Any>>()), listOf(), null, null) {
|
||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(javaClass, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
|
||||
codegen.putReifierMarkerIfTypeIsReifiedParameter(javaClass, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME)
|
||||
putJavaLangClassInstance(v, codegen.getState().typeMapper.mapType(javaClass))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,12 +54,12 @@ public class JavaClassProperty : IntrinsicPropertyGetter() {
|
||||
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
|
||||
}
|
||||
|
||||
return getType(Class::class.java)
|
||||
return getType(javaClass<Class<Any>>())
|
||||
}
|
||||
|
||||
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
|
||||
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver()!!.getType())
|
||||
return object : IntrinsicCallable(getType(Class::class.java), listOf(), classType, null) {
|
||||
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver().getType())
|
||||
return object : IntrinsicCallable(getType(javaClass<Class<Any>>()), listOf(), classType, null) {
|
||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||
if (isPrimitive(classType)) {
|
||||
v.getstatic(boxType(classType).getInternalName(), "TYPE", "Ljava/lang/Class;")
|
||||
|
||||
@@ -39,7 +39,7 @@ public class KClassJavaProperty : IntrinsicPropertyGetter() {
|
||||
return when {
|
||||
isReifiedTypeParameter(type) -> {
|
||||
StackValue.operation(returnType) { iv ->
|
||||
codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
|
||||
codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME)
|
||||
AsmUtil.putJavaLangClassInstance(iv, asmType)
|
||||
coerceToJavaLangClass(iv, returnType)
|
||||
}
|
||||
|
||||
@@ -23,13 +23,10 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class MonitorInstruction private constructor(private val opcode: Int) : IntrinsicMethod() {
|
||||
public class MonitorInstruction private constructor(private val opcode: Int) : IntrinsicMethod() {
|
||||
companion object {
|
||||
@JvmField
|
||||
val MONITOR_ENTER: MonitorInstruction = MonitorInstruction(Opcodes.MONITORENTER)
|
||||
|
||||
@JvmField
|
||||
val MONITOR_EXIT: MonitorInstruction = MonitorInstruction(Opcodes.MONITOREXIT)
|
||||
public val MONITOR_ENTER: MonitorInstruction = MonitorInstruction(Opcodes.MONITORENTER)
|
||||
public val MONITOR_EXIT: MonitorInstruction = MonitorInstruction(Opcodes.MONITOREXIT)
|
||||
}
|
||||
|
||||
override fun toCallable(method: CallableMethod): Callable {
|
||||
|
||||
@@ -78,28 +78,26 @@ public object TypeIntrinsics {
|
||||
instanceofInsn.desc = asmType.internalName
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun checkcast(
|
||||
v: InstructionAdapter,
|
||||
kotlinType: KotlinType, asmType: Type,
|
||||
// This parameter is just for sake of optimization:
|
||||
// when we generate 'as?' we do necessary intrinsic checks
|
||||
// when calling TypeIntrinsics.instanceOf, so here we can just make checkcast
|
||||
safe: Boolean) {
|
||||
public @JvmStatic fun checkcast(v: InstructionAdapter, jetType: KotlinType, asmType: Type, safe: Boolean) {
|
||||
if (safe) {
|
||||
v.checkcast(asmType)
|
||||
return
|
||||
}
|
||||
|
||||
val functionTypeArity = getFunctionTypeArity(kotlinType)
|
||||
val functionTypeArity = getFunctionTypeArity(jetType)
|
||||
if (functionTypeArity >= 0) {
|
||||
v.iconst(functionTypeArity)
|
||||
v.typeIntrinsic(BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY, BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR)
|
||||
if (safe) {
|
||||
v.typeIntrinsic(BEFORE_SAFE_CHECKCAST_TO_FUNCTION_OF_ARITY, BEFORE_SAFE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR)
|
||||
}
|
||||
else {
|
||||
v.typeIntrinsic(BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY, BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR)
|
||||
}
|
||||
v.checkcast(asmType)
|
||||
return
|
||||
}
|
||||
|
||||
val asMutableCollectionMethodName = getAsMutableCollectionMethodName(kotlinType)
|
||||
val asMutableCollectionMethodName = getAsMutableCollectionMethodName(jetType)
|
||||
if (asMutableCollectionMethodName != null) {
|
||||
v.typeIntrinsic(asMutableCollectionMethodName, getAsMutableCollectionDescriptor(asmType))
|
||||
return
|
||||
@@ -108,6 +106,38 @@ public object TypeIntrinsics {
|
||||
v.checkcast(asmType)
|
||||
}
|
||||
|
||||
public @JvmStatic fun checkcast(checkcastInsn: TypeInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type, safe: Boolean) {
|
||||
if (safe) {
|
||||
checkcastInsn.desc = asmType.internalName
|
||||
return
|
||||
}
|
||||
|
||||
val functionTypeArity = getFunctionTypeArity(jetType)
|
||||
if (functionTypeArity >= 0) {
|
||||
instructions.insertBefore(checkcastInsn, iconstNode(functionTypeArity))
|
||||
|
||||
val beforeCheckcast = if (safe)
|
||||
typeIntrinsicNode(BEFORE_SAFE_CHECKCAST_TO_FUNCTION_OF_ARITY, BEFORE_SAFE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR)
|
||||
else
|
||||
typeIntrinsicNode(BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY, BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR)
|
||||
instructions.insertBefore(checkcastInsn, beforeCheckcast)
|
||||
|
||||
instructions.insertBefore(checkcastInsn, TypeInsnNode(Opcodes.CHECKCAST, asmType.internalName))
|
||||
instructions.remove(checkcastInsn)
|
||||
return
|
||||
}
|
||||
|
||||
val asMutableCollectionMethodName = getAsMutableCollectionMethodName(jetType)
|
||||
if (asMutableCollectionMethodName != null) {
|
||||
instructions.insertBefore(checkcastInsn,
|
||||
typeIntrinsicNode(asMutableCollectionMethodName, getAsMutableCollectionDescriptor(asmType)))
|
||||
instructions.remove(checkcastInsn)
|
||||
return
|
||||
}
|
||||
|
||||
checkcastInsn.desc = asmType.internalName
|
||||
}
|
||||
|
||||
private val INTRINSICS_CLASS = "kotlin/jvm/internal/TypeIntrinsics"
|
||||
|
||||
private val IS_FUNCTON_OF_ARITY_METHOD_NAME = "isFunctionOfArity"
|
||||
@@ -181,4 +211,9 @@ public object TypeIntrinsics {
|
||||
|
||||
private val BEFORE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR =
|
||||
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, Type.INT_TYPE)
|
||||
|
||||
private val BEFORE_SAFE_CHECKCAST_TO_FUNCTION_OF_ARITY = "beforeSafeCheckcastToFunctionOfArity"
|
||||
|
||||
private val BEFORE_SAFE_CHECKCAST_TO_FUNCTION_OF_ARITY_DESCRIPTOR =
|
||||
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, Type.INT_TYPE)
|
||||
}
|
||||
@@ -110,10 +110,10 @@ public open class MethodAnalyzer<V : Value>(
|
||||
|
||||
}
|
||||
catch (e: AnalyzerException) {
|
||||
throw AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.message, e)
|
||||
throw AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
throw AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.message, e)
|
||||
throw AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -91,28 +91,27 @@ public class OptimizationBasicInterpreter extends BasicInterpreter {
|
||||
public BasicValue merge(
|
||||
@NotNull BasicValue v, @NotNull BasicValue w
|
||||
) {
|
||||
if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) {
|
||||
if (!v.equals(w)) {
|
||||
if (v == BasicValue.UNINITIALIZED_VALUE || w == BasicValue.UNINITIALIZED_VALUE) {
|
||||
return BasicValue.UNINITIALIZED_VALUE;
|
||||
}
|
||||
|
||||
// if merge of two references then `lub` is java/lang/Object
|
||||
// arrays also are BasicValues with reference type's
|
||||
if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) {
|
||||
return BasicValue.REFERENCE_VALUE;
|
||||
}
|
||||
|
||||
assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays";
|
||||
|
||||
// if merge of something can be stored in int var (int, char, boolean, byte, character)
|
||||
if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE &&
|
||||
w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) {
|
||||
return BasicValue.INT_VALUE;
|
||||
}
|
||||
|
||||
return BasicValue.UNINITIALIZED_VALUE;
|
||||
}
|
||||
// Objects must be equal, others can just have the same sort
|
||||
if (v.getType().getSort() == w.getType().getSort() && (v.getType().getSort() != Type.OBJECT || v.equals(w))) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// if merge of two references then `lub` is java/lang/Object
|
||||
// arrays also are BasicValues with reference type's
|
||||
if (v.getType().getSort() == Type.OBJECT && w.getType().getSort() == Type.OBJECT) {
|
||||
return BasicValue.REFERENCE_VALUE;
|
||||
}
|
||||
|
||||
assert v.getType().getSort() != Type.ARRAY && w.getType().getSort() != Type.ARRAY : "There should not be arrays";
|
||||
|
||||
// if merge of something can be stored in int var (int, char, boolean, byte, character)
|
||||
if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE &&
|
||||
w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) {
|
||||
return BasicValue.INT_VALUE;
|
||||
}
|
||||
|
||||
return BasicValue.UNINITIALIZED_VALUE;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.optimization.common
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
|
||||
val AbstractInsnNode.isMeaningful: Boolean get() =
|
||||
@@ -96,24 +97,3 @@ inline fun AbstractInsnNode.findPreviousOrNull(predicate: (AbstractInsnNode) ->
|
||||
|
||||
fun AbstractInsnNode.hasOpcode(): Boolean =
|
||||
getOpcode() >= 0
|
||||
|
||||
// See InstructionAdapter
|
||||
//
|
||||
// public void iconst(final int cst) {
|
||||
// if (cst >= -1 && cst <= 5) {
|
||||
// mv.visitInsn(Opcodes.ICONST_0 + cst);
|
||||
// } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
|
||||
// mv.visitIntInsn(Opcodes.BIPUSH, cst);
|
||||
// } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
|
||||
// mv.visitIntInsn(Opcodes.SIPUSH, cst);
|
||||
// } else {
|
||||
// mv.visitLdcInsn(new Integer(cst));
|
||||
// }
|
||||
// }
|
||||
val AbstractInsnNode.intConstant: Int? get() =
|
||||
when (opcode) {
|
||||
in ICONST_M1..ICONST_5 -> opcode - ICONST_0
|
||||
BIPUSH, SIPUSH -> (this as IntInsnNode).operand
|
||||
LDC -> (this as LdcInsnNode).cst as? Int
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ private fun insertSaveRestoreStackMarkers(
|
||||
val doneTryStartLabels = hashSetOf<LabelNode>()
|
||||
val doneHandlerLabels = hashSetOf<LabelNode>()
|
||||
|
||||
for (decompiledTryDescriptor in decompiledTryDescriptorForStart.values) {
|
||||
for (decompiledTryDescriptor in decompiledTryDescriptorForStart.values()) {
|
||||
with(decompiledTryDescriptor) {
|
||||
if (!doneTryStartLabels.contains(tryStartLabel)) {
|
||||
doneTryStartLabels.add(tryStartLabel)
|
||||
|
||||
@@ -96,7 +96,7 @@ internal class FixStackAnalyzer(
|
||||
}
|
||||
else {
|
||||
extraStack.add(value)
|
||||
maxExtraStackSize = Math.max(maxExtraStackSize, extraStack.size)
|
||||
maxExtraStackSize = Math.max(maxExtraStackSize, extraStack.size())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ internal class FixStackContext(val methodNode: MethodNode) {
|
||||
if (saveNodes.isEmpty()) {
|
||||
throw AssertionError("${indexOf(insnNode)}: in handler ${indexOf(restoreLabel)} restore is not matched with save")
|
||||
}
|
||||
else if (saveNodes.size > 1) {
|
||||
else if (saveNodes.size() > 1) {
|
||||
throw AssertionError("${indexOf(insnNode)}: in handler ${indexOf(restoreLabel)} restore is matched with several saves")
|
||||
}
|
||||
val saveNode = saveNodes.first()
|
||||
|
||||
@@ -39,7 +39,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
|
||||
}
|
||||
|
||||
fun allocateVariablesForSaveStackMarker(saveStackMarker: AbstractInsnNode, savedStackValues: List<BasicValue>): SavedStackDescriptor {
|
||||
val numRestoreStackMarkers = context.restoreStackMarkersForSaveMarker[saveStackMarker]!!.size
|
||||
val numRestoreStackMarkers = context.restoreStackMarkersForSaveMarker[saveStackMarker]!!.size()
|
||||
return allocateNewHandle(numRestoreStackMarkers, saveStackMarker, savedStackValues)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
|
||||
}
|
||||
|
||||
private fun getFirstUnusedLocalVariableIndex(): Int =
|
||||
allocatedHandles.values.fold(initialMaxLocals) {
|
||||
allocatedHandles.values().fold(initialMaxLocals) {
|
||||
index, handle -> Math.max(index, handle.savedStackDescriptor.firstUnusedLocalVarIndex)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.codegen.serialization;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice;
|
||||
import org.jetbrains.kotlin.util.slicedMap.MutableSlicedMap;
|
||||
import org.jetbrains.kotlin.util.slicedMap.SlicedMapImpl;
|
||||
@@ -35,6 +37,12 @@ public final class JvmSerializationBindings {
|
||||
SerializationMappingSlice.create();
|
||||
public static final SerializationMappingSlice<PropertyDescriptor, Method> SYNTHETIC_METHOD_FOR_PROPERTY =
|
||||
SerializationMappingSlice.create();
|
||||
public static final SerializationMappingSlice<CallableMemberDescriptor, String> IMPL_CLASS_NAME_FOR_CALLABLE =
|
||||
SerializationMappingSlice.create();
|
||||
public static final SerializationMappingSetSlice<PropertyDescriptor> STATIC_FIELD_IN_OUTER_CLASS =
|
||||
SerializationMappingSetSlice.create();
|
||||
public static final SerializationMappingSlice<ValueParameterDescriptor, Integer> INDEX_FOR_VALUE_PARAMETER =
|
||||
SerializationMappingSlice.create();
|
||||
|
||||
private static final class SerializationMappingSlice<K, V> extends BasicWritableSlice<K, V> {
|
||||
public SerializationMappingSlice() {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.serialization;
|
||||
|
||||
import com.google.protobuf.MessageLite;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -60,6 +61,14 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
return useTypeTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeValueParameter(@NotNull ValueParameterDescriptor descriptor, @NotNull ProtoBuf.ValueParameter.Builder proto) {
|
||||
Integer index = bindings.get(INDEX_FOR_VALUE_PARAMETER, descriptor);
|
||||
if (index != null) {
|
||||
proto.setExtension(JvmProtoBuf.index, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeType(@NotNull KotlinType type, @NotNull ProtoBuf.Type.Builder proto) {
|
||||
// TODO: don't store type annotations in our binary metadata on Java 8, use *TypeAnnotations attributes instead
|
||||
@@ -90,6 +99,8 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
proto.setExtension(JvmProtoBuf.constructorSignature, signature);
|
||||
}
|
||||
}
|
||||
|
||||
saveImplClassName(descriptor, proto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,6 +112,8 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
proto.setExtension(JvmProtoBuf.methodSignature, signature);
|
||||
}
|
||||
}
|
||||
|
||||
saveImplClassName(descriptor, proto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,18 +126,45 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
Method setterMethod = setter == null ? null : bindings.get(METHOD_FOR_FUNCTION, setter);
|
||||
|
||||
Pair<Type, String> field = bindings.get(FIELD_FOR_PROPERTY, descriptor);
|
||||
String fieldName;
|
||||
String fieldDesc;
|
||||
boolean isStaticInOuter;
|
||||
if (field != null) {
|
||||
fieldName = field.second;
|
||||
fieldDesc = field.first.getDescriptor();
|
||||
isStaticInOuter = bindings.get(STATIC_FIELD_IN_OUTER_CLASS, descriptor);
|
||||
}
|
||||
else {
|
||||
fieldName = null;
|
||||
fieldDesc = null;
|
||||
isStaticInOuter = false;
|
||||
}
|
||||
|
||||
Method syntheticMethod = bindings.get(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor);
|
||||
|
||||
JvmProtoBuf.JvmPropertySignature signature = signatureSerializer.propertySignature(
|
||||
descriptor,
|
||||
field != null ? field.second : null,
|
||||
field != null ? field.first.getDescriptor() : null,
|
||||
descriptor, fieldName, fieldDesc, isStaticInOuter,
|
||||
syntheticMethod != null ? signatureSerializer.methodSignature(null, syntheticMethod) : null,
|
||||
getterMethod != null ? signatureSerializer.methodSignature(null, getterMethod) : null,
|
||||
setterMethod != null ? signatureSerializer.methodSignature(null, setterMethod) : null
|
||||
);
|
||||
|
||||
proto.setExtension(JvmProtoBuf.propertySignature, signature);
|
||||
|
||||
saveImplClassName(descriptor, proto);
|
||||
}
|
||||
|
||||
private void saveImplClassName(@NotNull CallableMemberDescriptor callable, @NotNull MessageLite.Builder proto) {
|
||||
String name = bindings.get(IMPL_CLASS_NAME_FOR_CALLABLE, callable);
|
||||
if (name == null) return;
|
||||
|
||||
int index = stringTable.getStringIndex(name);
|
||||
if (proto instanceof ProtoBuf.Function.Builder) {
|
||||
((ProtoBuf.Function.Builder) proto).setExtension(JvmProtoBuf.methodImplClassName, index);
|
||||
}
|
||||
else if (proto instanceof ProtoBuf.Property.Builder) {
|
||||
((ProtoBuf.Property.Builder) proto).setExtension(JvmProtoBuf.propertyImplClassName, index);
|
||||
}
|
||||
}
|
||||
|
||||
private class SignatureSerializer {
|
||||
@@ -200,6 +240,7 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@Nullable String fieldName,
|
||||
@Nullable String fieldDesc,
|
||||
boolean isStaticInOuter,
|
||||
@Nullable JvmProtoBuf.JvmMethodSignature syntheticMethod,
|
||||
@Nullable JvmProtoBuf.JvmMethodSignature getter,
|
||||
@Nullable JvmProtoBuf.JvmMethodSignature setter
|
||||
@@ -208,7 +249,7 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
|
||||
if (fieldDesc != null) {
|
||||
assert fieldName != null : "Field name shouldn't be null when there's a field type: " + fieldDesc;
|
||||
signature.setField(fieldSignature(descriptor, fieldName, fieldDesc));
|
||||
signature.setField(fieldSignature(descriptor, fieldName, fieldDesc, isStaticInOuter));
|
||||
}
|
||||
|
||||
if (syntheticMethod != null) {
|
||||
@@ -229,7 +270,8 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
public JvmProtoBuf.JvmFieldSignature fieldSignature(
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@NotNull String name,
|
||||
@NotNull String desc
|
||||
@NotNull String desc,
|
||||
boolean isStaticInOuter
|
||||
) {
|
||||
JvmProtoBuf.JvmFieldSignature.Builder builder = JvmProtoBuf.JvmFieldSignature.newBuilder();
|
||||
if (!descriptor.getName().asString().equals(name)) {
|
||||
@@ -238,6 +280,9 @@ public class JvmSerializerExtension extends SerializerExtension {
|
||||
if (requiresSignature(descriptor, desc)) {
|
||||
builder.setDesc(stringTable.getStringIndex(desc));
|
||||
}
|
||||
if (isStaticInOuter) {
|
||||
builder.setIsStaticInOuter(true);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class JvmStringTable(private val typeMapper: JetTypeMapper) : StringTable {
|
||||
|
||||
override fun getStringIndex(string: String): Int =
|
||||
map.getOrPut(string) {
|
||||
strings.size.apply {
|
||||
strings.size().apply {
|
||||
strings.add(string)
|
||||
|
||||
val lastRecord = records.lastOrNull()
|
||||
@@ -78,7 +78,7 @@ class JvmStringTable(private val typeMapper: JetTypeMapper) : StringTable {
|
||||
}
|
||||
}
|
||||
|
||||
val index = strings.size
|
||||
val index = strings.size()
|
||||
if (classId.isLocal) {
|
||||
localNames.add(index)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
@@ -52,18 +53,8 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
|
||||
// Avoid errors when some classes are not loaded for some reason
|
||||
private val typeMapper = JetTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES, fileClassesProvider, incrementalCache, moduleName)
|
||||
private val reportDiagnosticsTasks = ArrayList<() -> Unit>()
|
||||
|
||||
fun reportDiagnostics() {
|
||||
reportDiagnosticsTasks.forEach { it() }
|
||||
reportDiagnosticsTasks.clear()
|
||||
}
|
||||
|
||||
override fun handleClashingSignatures(data: ConflictingJvmDeclarationsData) {
|
||||
reportDiagnosticsTasks.add { reportConflictingJvmSignatures(data) }
|
||||
}
|
||||
|
||||
private fun reportConflictingJvmSignatures(data: ConflictingJvmDeclarationsData) {
|
||||
val noOwnImplementations = data.signatureOrigins.all { it.originKind in EXTERNAL_SOURCES_KINDS }
|
||||
|
||||
val elements = LinkedHashSet<PsiElement>()
|
||||
@@ -91,14 +82,6 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
classOrigin: JvmDeclarationOrigin,
|
||||
classInternalName: String?,
|
||||
signatures: MultiMap<RawSignature, JvmDeclarationOrigin>
|
||||
) {
|
||||
reportDiagnosticsTasks.add { reportClashingSignaturesInHierarchy(classOrigin, classInternalName, signatures) }
|
||||
}
|
||||
|
||||
private fun reportClashingSignaturesInHierarchy(
|
||||
classOrigin: JvmDeclarationOrigin,
|
||||
classInternalName: String?,
|
||||
signatures: MultiMap<RawSignature, JvmDeclarationOrigin>
|
||||
) {
|
||||
val descriptor = classOrigin.descriptor
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
@@ -174,7 +157,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
descriptor.getParentJavaStaticClassScope()?.run {
|
||||
getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
.filter {
|
||||
it is FunctionDescriptor && Visibilities.isVisibleWithIrrelevantReceiver(it, descriptor)
|
||||
it is FunctionDescriptor && Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, it, descriptor)
|
||||
}
|
||||
.forEach(::processMember)
|
||||
}
|
||||
@@ -182,7 +165,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
return groupedBySignature
|
||||
}
|
||||
|
||||
private fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean {
|
||||
public fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean {
|
||||
if (descriptor is SamAdapterDescriptor<*>) return true
|
||||
|
||||
return descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.`when`.MappingsClassesForWhenByEnum
|
||||
@@ -30,7 +28,6 @@ import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.OptimizationClassBuilderFactory
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
@@ -66,21 +63,19 @@ public class GenerationState @JvmOverloads constructor(
|
||||
// TODO: get rid of it with the proper module infrastructure
|
||||
public val outDirectory: File? = null,
|
||||
public val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
|
||||
public val generateOpenMultifileClasses: Boolean = false,
|
||||
public val progress: Progress = Progress.DEAF
|
||||
) {
|
||||
public abstract class GenerateClassFilter {
|
||||
public abstract fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldAnnotateClass(classOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldGenerateClass(classOrObject: KtClassOrObject): Boolean
|
||||
public abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
|
||||
public abstract fun shouldGenerateScript(script: KtScript): Boolean
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
public val GENERATE_ALL: GenerateClassFilter = object : GenerateClassFilter() {
|
||||
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
||||
override fun shouldAnnotateClass(classOrObject: KtClassOrObject): Boolean = true
|
||||
|
||||
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean = true
|
||||
override fun shouldGenerateClass(classOrObject: KtClassOrObject): Boolean = true
|
||||
|
||||
override fun shouldGenerateScript(script: KtScript): Boolean = true
|
||||
|
||||
@@ -101,10 +96,7 @@ public class GenerationState @JvmOverloads constructor(
|
||||
private var used = false
|
||||
|
||||
public val diagnostics: DiagnosticSink get() = extraJvmDiagnosticsTrace
|
||||
public val collectedExtraJvmDiagnostics: Diagnostics = LazyJvmDiagnostics {
|
||||
duplicateSignatureFactory.reportDiagnostics()
|
||||
extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
||||
}
|
||||
public val collectedExtraJvmDiagnostics: Diagnostics get() = extraJvmDiagnosticsTrace.bindingContext.diagnostics
|
||||
|
||||
public val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
|
||||
public val classBuilderMode: ClassBuilderMode = builderFactory.getClassBuilderMode()
|
||||
@@ -118,7 +110,6 @@ public class GenerationState @JvmOverloads constructor(
|
||||
public val reflectionTypes: ReflectionTypes = ReflectionTypes(module)
|
||||
public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes()
|
||||
public val factory: ClassFileFactory
|
||||
private val duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics
|
||||
|
||||
public val replSpecific = ForRepl()
|
||||
|
||||
@@ -144,13 +135,12 @@ public class GenerationState @JvmOverloads constructor(
|
||||
|
||||
init {
|
||||
val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization)
|
||||
duplicateSignatureFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
var interceptedBuilderFactory: ClassBuilderFactory = BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
optimizationClassBuilderFactory, this.bindingContext, diagnostics, fileClassesProvider,
|
||||
getIncrementalCacheForThisTarget(),
|
||||
this.moduleName)
|
||||
|
||||
var interceptedBuilderFactory: ClassBuilderFactory
|
||||
= BuilderFactoryForDuplicateClassNameDiagnostics(duplicateSignatureFactory, diagnostics)
|
||||
interceptedBuilderFactory = BuilderFactoryForDuplicateClassNameDiagnostics(interceptedBuilderFactory, diagnostics);
|
||||
|
||||
val interceptExtensions = ClassBuilderInterceptorExtension.getInstances(project)
|
||||
|
||||
@@ -178,20 +168,3 @@ public class GenerationState @JvmOverloads constructor(
|
||||
interceptedBuilderFactory.close()
|
||||
}
|
||||
}
|
||||
|
||||
private class LazyJvmDiagnostics(compute: () -> Diagnostics): Diagnostics {
|
||||
private val delegate by lazy(LazyThreadSafetyMode.SYNCHRONIZED, compute)
|
||||
|
||||
override val modificationTracker: ModificationTracker
|
||||
get() = delegate.modificationTracker
|
||||
|
||||
override fun all(): Collection<Diagnostic> = delegate.all()
|
||||
|
||||
override fun forElement(psiElement: PsiElement) = delegate.forElement(psiElement)
|
||||
|
||||
override fun isEmpty() = delegate.isEmpty()
|
||||
|
||||
override fun noSuppression() = delegate.noSuppression()
|
||||
|
||||
override fun iterator() = delegate.iterator()
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@ package org.jetbrains.kotlin.codegen.state;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Pair;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment;
|
||||
@@ -49,7 +50,7 @@ import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral;
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFunctionLiteralExpression;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
||||
@@ -111,6 +112,40 @@ public class JetTypeMapper {
|
||||
return bindingContext;
|
||||
}
|
||||
|
||||
private enum JetTypeMapperMode {
|
||||
/**
|
||||
* foo.Bar is mapped to Lfoo/Bar;
|
||||
*/
|
||||
IMPL,
|
||||
/**
|
||||
* kotlin.Int is mapped to I
|
||||
*/
|
||||
VALUE,
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
*/
|
||||
TYPE_PARAMETER,
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
* No projections allowed in immediate arguments
|
||||
*/
|
||||
SUPER_TYPE,
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as VALUE
|
||||
*/
|
||||
VALUE_FOR_ANNOTATION,
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as TYPE_PARAMETER
|
||||
*/
|
||||
TYPE_PARAMETER_FOR_ANNOTATION;
|
||||
|
||||
boolean isForAnnotation() {
|
||||
return this == VALUE_FOR_ANNOTATION || this == TYPE_PARAMETER_FOR_ANNOTATION;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapOwner(@NotNull DeclarationDescriptor descriptor) {
|
||||
return mapOwner(descriptor, true);
|
||||
@@ -320,53 +355,42 @@ public class JetTypeMapper {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
else if (descriptor instanceof FunctionDescriptor && forceBoxedReturnType((FunctionDescriptor) descriptor)) {
|
||||
// GENERIC_TYPE is a hack to automatically box the return type
|
||||
// TYPE_PARAMETER is a hack to automatically box the return type
|
||||
//noinspection ConstantConditions
|
||||
return mapType(descriptor.getReturnType(), sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
}
|
||||
else if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
|
||||
//noinspection ConstantConditions
|
||||
return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
|
||||
}
|
||||
else {
|
||||
return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE);
|
||||
}
|
||||
|
||||
return mapReturnType(descriptor, sw, returnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw, @NotNull KotlinType returnType) {
|
||||
boolean isAnnotationMethod = DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration());
|
||||
TypeMappingMode typeMappingModeFromAnnotation =
|
||||
TypeMappingUtil.extractTypeMappingModeFromAnnotation(descriptor, returnType, isAnnotationMethod);
|
||||
if (typeMappingModeFromAnnotation != null) {
|
||||
return mapType(returnType, sw, typeMappingModeFromAnnotation);
|
||||
}
|
||||
|
||||
TypeMappingMode mappingMode = TypeMappingMode.getOptimalModeForReturnType(
|
||||
returnType,
|
||||
/* isAnnotationMethod = */ isAnnotationMethod);
|
||||
|
||||
return mapType(returnType, sw, mappingMode);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapType(@NotNull KotlinType jetType, @NotNull TypeMappingMode mode) {
|
||||
private Type mapType(@NotNull KotlinType jetType, @NotNull JetTypeMapperMode mode) {
|
||||
return mapType(jetType, null, mode);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapSupertype(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor) {
|
||||
return mapType(jetType, signatureVisitor, TypeMappingMode.SUPER_TYPE);
|
||||
return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapTypeParameter(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor) {
|
||||
return mapType(jetType, signatureVisitor, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
return mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapClass(@NotNull ClassifierDescriptor classifier) {
|
||||
return mapType(classifier.getDefaultType(), null, TypeMappingMode.DEFAULT);
|
||||
return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type mapType(@NotNull KotlinType jetType) {
|
||||
return mapType(jetType, null, TypeMappingMode.DEFAULT);
|
||||
return mapType(jetType, null, JetTypeMapperMode.VALUE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -379,7 +403,7 @@ public class JetTypeMapper {
|
||||
public JvmMethodSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
|
||||
sw.writeReturnType();
|
||||
mapType(descriptor.getType(), sw, TypeMappingMode.VALUE_FOR_ANNOTATION);
|
||||
mapType(descriptor.getType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
|
||||
sw.writeReturnTypeEnd();
|
||||
return sw.makeJvmMethodSignature(descriptor.getName().asString(), false);
|
||||
}
|
||||
@@ -389,26 +413,44 @@ public class JetTypeMapper {
|
||||
return mapType(descriptor.getDefaultType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapType(@NotNull KotlinType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
|
||||
return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type mapType(
|
||||
@NotNull KotlinType jetType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull TypeMappingMode mode
|
||||
@NotNull JetTypeMapperMode kind,
|
||||
@NotNull Variance howThisTypeIsUsed
|
||||
) {
|
||||
Type builtinType = mapBuiltinType(jetType);
|
||||
Type known = mapBuiltinType(jetType);
|
||||
|
||||
if (builtinType != null) {
|
||||
Type asmType = mode.getNeedPrimitiveBoxing() ? boxType(builtinType) : builtinType;
|
||||
writeGenericType(jetType, asmType, signatureVisitor, mode);
|
||||
return asmType;
|
||||
boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
|
||||
if (known != null) {
|
||||
if (kind == JetTypeMapperMode.VALUE || kind == JetTypeMapperMode.VALUE_FOR_ANNOTATION) {
|
||||
return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
|
||||
}
|
||||
else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE ||
|
||||
kind == JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION) {
|
||||
return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, projectionsAllowed);
|
||||
}
|
||||
else if (kind == JetTypeMapperMode.IMPL) {
|
||||
// TODO: enable and fix tests
|
||||
//throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
|
||||
return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("unknown kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
TypeConstructor constructor = jetType.getConstructor();
|
||||
DeclarationDescriptor descriptor = constructor.getDeclarationDescriptor();
|
||||
if (constructor instanceof IntersectionTypeConstructor) {
|
||||
jetType = CommonSupertypes.commonSupertype(new ArrayList<KotlinType>(constructor.getSupertypes()));
|
||||
constructor = jetType.getConstructor();
|
||||
}
|
||||
DeclarationDescriptor descriptor = constructor.getDeclarationDescriptor();
|
||||
|
||||
if (descriptor == null) {
|
||||
throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
|
||||
@@ -442,10 +484,13 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
else {
|
||||
arrayElementType = boxType(mapType(memberType, mode));
|
||||
arrayElementType = boxType(mapType(memberType, kind));
|
||||
if (signatureVisitor != null) {
|
||||
signatureVisitor.writeArrayType();
|
||||
mapType(memberType, signatureVisitor, mode.toGenericArgumentMode(memberProjection.getProjectionKind()));
|
||||
JetTypeMapperMode newMode = kind.isForAnnotation() ?
|
||||
JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION :
|
||||
JetTypeMapperMode.TYPE_PARAMETER;
|
||||
mapType(memberType, signatureVisitor, newMode, memberProjection.getProjectionKind());
|
||||
signatureVisitor.writeArrayEnd();
|
||||
}
|
||||
}
|
||||
@@ -454,15 +499,15 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
Type asmType = mode.isForAnnotationParameter() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
|
||||
Type asmType = kind.isForAnnotation() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
|
||||
AsmTypes.JAVA_CLASS_TYPE :
|
||||
computeAsmType((ClassDescriptor) descriptor.getOriginal());
|
||||
writeGenericType(jetType, asmType, signatureVisitor, mode);
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
|
||||
return asmType;
|
||||
}
|
||||
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
Type type = mapType(getRepresentativeUpperBound((TypeParameterDescriptor) descriptor), mode);
|
||||
Type type = mapType(getRepresentativeUpperBound((TypeParameterDescriptor) descriptor), kind);
|
||||
if (signatureVisitor != null) {
|
||||
signatureVisitor.writeTypeVariable(descriptor.getName(), type);
|
||||
}
|
||||
@@ -575,20 +620,14 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
private void writeGenericType(
|
||||
@NotNull KotlinType type,
|
||||
@NotNull Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull TypeMappingMode mode
|
||||
BothSignatureWriter signatureVisitor,
|
||||
Type asmType,
|
||||
KotlinType type,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
|
||||
// Nothing mapping rules:
|
||||
// Map<Nothing, Foo> -> Map
|
||||
// Map<Foo, List<Nothing>> -> Map<Foo, List>
|
||||
// In<Nothing, Foo> == In<*, Foo> -> In<?, Foo>
|
||||
// In<Nothing, Nothing> -> In
|
||||
// Inv<in Nothing, Foo> -> Inv
|
||||
if (hasNothingInNonContravariantPosition(type) || type.getArguments().isEmpty()) {
|
||||
if (hasNothingInArguments(type) || type.getArguments().isEmpty()) {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
return;
|
||||
}
|
||||
@@ -611,14 +650,17 @@ public class JetTypeMapper {
|
||||
|
||||
writeGenericArguments(
|
||||
signatureVisitor,
|
||||
outermostInnerType.getArguments(), outermostClass.getDeclaredTypeParameters(), mode);
|
||||
outermostInnerType.getArguments(), outermostClass.getDeclaredTypeParameters(),
|
||||
howThisTypeIsUsed, projectionsAllowed);
|
||||
|
||||
for (PossiblyInnerType innerPart : innerTypesAsList.subList(1, innerTypesAsList.size())) {
|
||||
ClassDescriptor classDescriptor = innerPart.getClassDescriptor();
|
||||
signatureVisitor.writeInnerClass(getJvmShortName(classDescriptor));
|
||||
writeGenericArguments(
|
||||
signatureVisitor, innerPart.getArguments(),
|
||||
classDescriptor.getDeclaredTypeParameters(), mode);
|
||||
classDescriptor.getDeclaredTypeParameters(),
|
||||
howThisTypeIsUsed, projectionsAllowed
|
||||
);
|
||||
}
|
||||
|
||||
signatureVisitor.writeClassEnd();
|
||||
@@ -636,83 +678,61 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
private void writeGenericArguments(
|
||||
@NotNull BothSignatureWriter signatureVisitor,
|
||||
@NotNull List<? extends TypeProjection> arguments,
|
||||
@NotNull List<? extends TypeParameterDescriptor> parameters,
|
||||
@NotNull TypeMappingMode mode
|
||||
BothSignatureWriter signatureVisitor,
|
||||
List<? extends TypeProjection> arguments,
|
||||
List<? extends TypeParameterDescriptor> parameters,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
for (Pair<? extends TypeParameterDescriptor, ? extends TypeProjection> item : CollectionsKt.zip(parameters, arguments)) {
|
||||
TypeParameterDescriptor parameter = item.getFirst();
|
||||
TypeProjection argument = item.getSecond();
|
||||
|
||||
if (
|
||||
argument.isStarProjection() ||
|
||||
// In<Nothing, Foo> == In<*, Foo> -> In<?, Foo>
|
||||
KotlinBuiltIns.isNothing(argument.getType()) && parameter.getVariance() == Variance.IN_VARIANCE
|
||||
) {
|
||||
if (projectionsAllowed && argument.isStarProjection()) {
|
||||
signatureVisitor.writeUnboundedWildcard();
|
||||
}
|
||||
else {
|
||||
TypeMappingMode argumentMode = TypeMappingUtil.updateArgumentModeFromAnnotations(mode, argument.getType());
|
||||
Variance projectionKind = getVarianceForWildcard(parameter, argument, argumentMode);
|
||||
|
||||
Variance projectionKind = projectionsAllowed
|
||||
? getEffectiveVariance(
|
||||
parameter.getVariance(),
|
||||
argument.getProjectionKind(),
|
||||
howThisTypeIsUsed
|
||||
)
|
||||
: Variance.INVARIANT;
|
||||
signatureVisitor.writeTypeArgument(projectionKind);
|
||||
|
||||
mapType(argument.getType(), signatureVisitor,
|
||||
argumentMode.toGenericArgumentMode(
|
||||
TypeMappingUtil.getEffectiveVariance(parameter.getVariance(), argument.getProjectionKind())));
|
||||
|
||||
mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
signatureVisitor.writeTypeArgumentEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasNothingInNonContravariantPosition(KotlinType kotlinType) {
|
||||
List<TypeParameterDescriptor> parameters = kotlinType.getConstructor().getParameters();
|
||||
List<TypeProjection> arguments = kotlinType.getArguments();
|
||||
private static boolean hasNothingInArguments(KotlinType jetType) {
|
||||
boolean hasNothingInArguments = CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(TypeProjection projection) {
|
||||
return KotlinBuiltIns.isNothingOrNullableNothing(projection.getType());
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < arguments.size(); i++) {
|
||||
TypeProjection projection = arguments.get(i);
|
||||
if (hasNothingInArguments) return true;
|
||||
|
||||
if (projection.isStarProjection()) continue;
|
||||
|
||||
KotlinType type = projection.getType();
|
||||
|
||||
if (KotlinBuiltIns.isNullableNothing(type) ||
|
||||
KotlinBuiltIns.isNothing(type) && parameters.get(i).getVariance() != Variance.IN_VARIANCE) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(TypeProjection projection) {
|
||||
return !projection.isStarProjection() && hasNothingInArguments(projection.getType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Variance getVarianceForWildcard(
|
||||
@NotNull TypeParameterDescriptor parameter,
|
||||
@NotNull TypeProjection projection,
|
||||
@NotNull TypeMappingMode mode
|
||||
) {
|
||||
Variance projectionKind = projection.getProjectionKind();
|
||||
private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
|
||||
// Return type must not contain wildcards
|
||||
if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
|
||||
|
||||
if (mode.getSkipDeclarationSiteWildcards() && projectionKind == Variance.INVARIANT) {
|
||||
return Variance.INVARIANT;
|
||||
}
|
||||
|
||||
Variance parameterVariance = parameter.getVariance();
|
||||
if (parameterVariance == Variance.INVARIANT) {
|
||||
return projectionKind;
|
||||
}
|
||||
|
||||
if (projectionKind == Variance.INVARIANT) {
|
||||
if (mode.getSkipDeclarationSiteWildcardsIfPossible() && !projection.isStarProjection()) {
|
||||
if (parameterVariance == Variance.OUT_VARIANCE && TypeMappingUtil.isMostPreciseCovariantArgument(projection.getType())){
|
||||
return Variance.INVARIANT;
|
||||
}
|
||||
|
||||
if (parameterVariance == Variance.IN_VARIANCE
|
||||
&& TypeMappingUtil.isMostPreciseContravariantArgument(projection.getType(), parameter)) {
|
||||
return Variance.INVARIANT;
|
||||
}
|
||||
}
|
||||
return parameterVariance;
|
||||
}
|
||||
if (parameterVariance == projectionKind) {
|
||||
@@ -724,6 +744,33 @@ public class JetTypeMapper {
|
||||
return Variance.OUT_VARIANCE;
|
||||
}
|
||||
|
||||
private Type mapKnownAsmType(
|
||||
KotlinType jetType,
|
||||
Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull Variance howThisTypeIsUsed
|
||||
) {
|
||||
return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, true);
|
||||
}
|
||||
|
||||
private Type mapKnownAsmType(
|
||||
KotlinType jetType,
|
||||
Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull Variance howThisTypeIsUsed,
|
||||
boolean allowProjections
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
if (jetType.getArguments().isEmpty()) {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
}
|
||||
else {
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
|
||||
}
|
||||
}
|
||||
return asmType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall) {
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
@@ -759,7 +806,7 @@ public class JetTypeMapper {
|
||||
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
|
||||
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
|
||||
|
||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
|
||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE)) {
|
||||
thisClass = mapClass(currentOwner);
|
||||
if (declarationOwner instanceof JavaClassDescriptor) {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
@@ -789,7 +836,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
FunctionDescriptor overriddenSpecialBuiltinFunction =
|
||||
SpecialBuiltinMembers.<FunctionDescriptor>getOverriddenBuiltinReflectingJvmDescriptor(functionDescriptor.getOriginal());
|
||||
SpecialBuiltinMembers.<FunctionDescriptor>getOverriddenBuiltinWithDifferentJvmDescriptor(functionDescriptor.getOriginal());
|
||||
FunctionDescriptor functionToCall = overriddenSpecialBuiltinFunction != null && !superCall
|
||||
? overriddenSpecialBuiltinFunction.getOriginal()
|
||||
: functionDescriptor.getOriginal();
|
||||
@@ -899,7 +946,7 @@ public class JetTypeMapper {
|
||||
PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
|
||||
if (element instanceof KtFunctionLiteral) {
|
||||
PsiElement expression = element.getParent();
|
||||
if (expression instanceof KtLambdaExpression) {
|
||||
if (expression instanceof KtFunctionLiteralExpression) {
|
||||
SamType samType = bindingContext.get(SAM_VALUE, (KtExpression) expression);
|
||||
if (samType != null) {
|
||||
return samType.getAbstractMethod().getName().asString();
|
||||
@@ -968,7 +1015,7 @@ public class JetTypeMapper {
|
||||
public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
|
||||
if (f.getInitialSignatureDescriptor() != null && f != f.getInitialSignatureDescriptor()) {
|
||||
// Overrides of special builtin in Kotlin classes always have special signature
|
||||
if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(f) == null ||
|
||||
if (SpecialBuiltinMembers.getOverriddenBuiltinWithDifferentJvmDescriptor(f) == null ||
|
||||
f.getContainingDeclaration().getOriginal() instanceof JavaClassDescriptor) {
|
||||
return mapSignature(f.getInitialSignatureDescriptor(), kind);
|
||||
}
|
||||
@@ -994,7 +1041,7 @@ public class JetTypeMapper {
|
||||
writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
writeParameter(sw, parameter.getType(), f);
|
||||
writeParameter(sw, parameter.getType());
|
||||
}
|
||||
|
||||
if (f instanceof AccessorForConstructorDescriptor) {
|
||||
@@ -1011,12 +1058,12 @@ public class JetTypeMapper {
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = f.getExtensionReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType(), f);
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : valueParameters) {
|
||||
if (writeCustomParameter(f, parameter, sw)) continue;
|
||||
writeParameter(sw, parameter.getType(), f);
|
||||
writeParameter(sw, parameter.getType());
|
||||
}
|
||||
|
||||
sw.writeReturnType();
|
||||
@@ -1030,9 +1077,8 @@ public class JetTypeMapper {
|
||||
SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
|
||||
|
||||
if (specialSignatureInfo != null) {
|
||||
String newGenericSignature = CodegenUtilKt.replaceValueParametersIn(
|
||||
specialSignatureInfo, signature.getGenericsSignature());
|
||||
return new JvmMethodSignature(signature.getAsmMethod(), newGenericSignature, signature.getValueParameters());
|
||||
return new JvmMethodSignature(
|
||||
signature.getAsmMethod(), specialSignatureInfo.getSignature(), signature.getValueParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1050,7 +1096,7 @@ public class JetTypeMapper {
|
||||
if (SpecialBuiltinMembers.isFromJavaOrBuiltins(f)) return false;
|
||||
|
||||
if (overridden.getName().asString().equals("remove") && mapType(parameter.getType()).getSort() == Type.INT) {
|
||||
writeParameter(sw, TypeUtils.makeNullable(parameter.getType()), f);
|
||||
writeParameter(sw, TypeUtils.makeNullable(parameter.getType()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1123,16 +1169,9 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String mapFieldSignature(@NotNull KotlinType backingFieldType, @NotNull PropertyDescriptor propertyDescriptor) {
|
||||
public String mapFieldSignature(@NotNull KotlinType backingFieldType) {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
|
||||
|
||||
if (!propertyDescriptor.isVar()) {
|
||||
mapReturnType(propertyDescriptor, sw, backingFieldType);
|
||||
}
|
||||
else {
|
||||
writeParameterType(sw, backingFieldType, propertyDescriptor);
|
||||
}
|
||||
|
||||
mapType(backingFieldType, sw, JetTypeMapperMode.VALUE);
|
||||
return sw.makeJavaGenericSignature();
|
||||
}
|
||||
|
||||
@@ -1150,7 +1189,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
else return;
|
||||
|
||||
writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType(), descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1184,7 +1223,7 @@ public class JetTypeMapper {
|
||||
for (KotlinType jetType : typeParameterDescriptor.getUpperBounds()) {
|
||||
if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||
if (!isJvmInterface(jetType)) {
|
||||
mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
break classBound;
|
||||
}
|
||||
}
|
||||
@@ -1202,13 +1241,13 @@ public class JetTypeMapper {
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
if (isJvmInterface(jetType)) {
|
||||
sw.writeInterfaceBound();
|
||||
mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
sw.writeInterfaceBoundEnd();
|
||||
}
|
||||
}
|
||||
else if (classifier instanceof TypeParameterDescriptor) {
|
||||
sw.writeInterfaceBound();
|
||||
mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
|
||||
mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
sw.writeInterfaceBoundEnd();
|
||||
}
|
||||
else {
|
||||
@@ -1217,50 +1256,16 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeParameter(
|
||||
@NotNull BothSignatureWriter sw,
|
||||
@NotNull KotlinType type,
|
||||
@Nullable CallableDescriptor callableDescriptor
|
||||
) {
|
||||
writeParameter(sw, JvmMethodParameterKind.VALUE, type, callableDescriptor);
|
||||
private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull KotlinType type) {
|
||||
writeParameter(sw, JvmMethodParameterKind.VALUE, type);
|
||||
}
|
||||
|
||||
private void writeParameter(
|
||||
@NotNull BothSignatureWriter sw,
|
||||
@NotNull JvmMethodParameterKind kind,
|
||||
@NotNull KotlinType type,
|
||||
@Nullable CallableDescriptor callableDescriptor
|
||||
) {
|
||||
private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull KotlinType type) {
|
||||
sw.writeParameterType(kind);
|
||||
|
||||
writeParameterType(sw, type, callableDescriptor);
|
||||
|
||||
mapType(type, sw, JetTypeMapperMode.VALUE);
|
||||
sw.writeParameterTypeEnd();
|
||||
}
|
||||
|
||||
private void writeParameterType(
|
||||
@NotNull BothSignatureWriter sw,
|
||||
@NotNull KotlinType type,
|
||||
@Nullable CallableDescriptor callableDescriptor
|
||||
) {
|
||||
TypeMappingMode typeMappingMode;
|
||||
|
||||
TypeMappingMode typeMappingModeFromAnnotation =
|
||||
TypeMappingUtil.extractTypeMappingModeFromAnnotation(callableDescriptor, type, /* isForAnnotationParameter = */ false);
|
||||
|
||||
if (typeMappingModeFromAnnotation != null) {
|
||||
typeMappingMode = typeMappingModeFromAnnotation;
|
||||
}
|
||||
else if (TypeMappingUtil.isMethodWithDeclarationSiteWildcards(callableDescriptor) && !type.getArguments().isEmpty()) {
|
||||
typeMappingMode = TypeMappingMode.GENERIC_ARGUMENT; // Render all wildcards
|
||||
}
|
||||
else {
|
||||
typeMappingMode = TypeMappingMode.getOptimalModeForValueParameter(type);
|
||||
}
|
||||
|
||||
mapType(type, sw, typeMappingMode);
|
||||
}
|
||||
|
||||
private static void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull Type type) {
|
||||
sw.writeParameterType(kind);
|
||||
sw.writeAsmType(type);
|
||||
@@ -1272,20 +1277,18 @@ public class JetTypeMapper {
|
||||
|
||||
ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
|
||||
if (captureThis != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType());
|
||||
}
|
||||
|
||||
KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
|
||||
if (captureReceiverType != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType, descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType);
|
||||
}
|
||||
|
||||
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
|
||||
writeParameter(
|
||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
|
||||
writeParameter(
|
||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(), descriptor);
|
||||
writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType());
|
||||
writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType());
|
||||
}
|
||||
|
||||
if (closure == null) return;
|
||||
@@ -1381,11 +1384,11 @@ public class JetTypeMapper {
|
||||
sw.writeParametersStart();
|
||||
|
||||
for (ScriptDescriptor importedScript : importedScripts) {
|
||||
writeParameter(sw, importedScript.getDefaultType(), /* callableDescriptor = */ null);
|
||||
writeParameter(sw, importedScript.getDefaultType());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
|
||||
writeParameter(sw, valueParameter.getType(), /* callableDescriptor = */ null);
|
||||
writeParameter(sw, valueParameter.getType());
|
||||
}
|
||||
|
||||
writeVoidReturn(sw);
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
internal class TypeMappingMode private constructor(
|
||||
val needPrimitiveBoxing: Boolean = true,
|
||||
val isForAnnotationParameter: Boolean = false,
|
||||
// Here DeclarationSiteWildcards means wildcard generated because of declaration-site variance
|
||||
val skipDeclarationSiteWildcards: Boolean = false,
|
||||
val skipDeclarationSiteWildcardsIfPossible: Boolean = false,
|
||||
private val genericArgumentMode: TypeMappingMode? = null,
|
||||
private val genericContravariantArgumentMode: TypeMappingMode? = genericArgumentMode,
|
||||
private val genericInvariantArgumentMode: TypeMappingMode? = genericArgumentMode
|
||||
) {
|
||||
companion object {
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
*/
|
||||
@JvmField
|
||||
val GENERIC_ARGUMENT = TypeMappingMode()
|
||||
|
||||
/**
|
||||
* kotlin.Int is mapped to I
|
||||
*/
|
||||
@JvmField
|
||||
val DEFAULT = TypeMappingMode(genericArgumentMode = GENERIC_ARGUMENT, needPrimitiveBoxing = false)
|
||||
|
||||
/**
|
||||
* kotlin.Int is mapped to Ljava/lang/Integer;
|
||||
* No projections allowed in immediate arguments
|
||||
*/
|
||||
@JvmField
|
||||
val SUPER_TYPE = TypeMappingMode(skipDeclarationSiteWildcards = true, genericArgumentMode = GENERIC_ARGUMENT)
|
||||
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as DEFAULT
|
||||
*/
|
||||
@JvmField
|
||||
val VALUE_FOR_ANNOTATION = TypeMappingMode(
|
||||
isForAnnotationParameter = true,
|
||||
needPrimitiveBoxing = false,
|
||||
genericArgumentMode = TypeMappingMode(isForAnnotationParameter = true, genericArgumentMode = GENERIC_ARGUMENT))
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun getOptimalModeForValueParameter(
|
||||
type: KotlinType
|
||||
) = getOptimalModeForSignaturePart(type, isForAnnotationParameter = false, canBeUsedInSupertypePosition = true)
|
||||
|
||||
@JvmStatic
|
||||
fun getOptimalModeForReturnType(
|
||||
type: KotlinType,
|
||||
isAnnotationMethod: Boolean
|
||||
) = getOptimalModeForSignaturePart(type, isForAnnotationParameter = isAnnotationMethod, canBeUsedInSupertypePosition = false)
|
||||
|
||||
private fun getOptimalModeForSignaturePart(
|
||||
type: KotlinType,
|
||||
isForAnnotationParameter: Boolean,
|
||||
canBeUsedInSupertypePosition: Boolean
|
||||
): TypeMappingMode {
|
||||
if (type.arguments.isEmpty()) return DEFAULT
|
||||
|
||||
val contravariantArgumentMode =
|
||||
if (!canBeUsedInSupertypePosition)
|
||||
TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = false,
|
||||
skipDeclarationSiteWildcardsIfPossible = true)
|
||||
else
|
||||
null
|
||||
|
||||
val invariantArgumentMode =
|
||||
if (canBeUsedInSupertypePosition)
|
||||
getOptimalModeForSignaturePart(type, isForAnnotationParameter, canBeUsedInSupertypePosition = false)
|
||||
else
|
||||
null
|
||||
|
||||
return TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = !canBeUsedInSupertypePosition,
|
||||
skipDeclarationSiteWildcardsIfPossible = true,
|
||||
genericContravariantArgumentMode = contravariantArgumentMode,
|
||||
genericInvariantArgumentMode = invariantArgumentMode)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards: Boolean,
|
||||
isForAnnotationParameter: Boolean,
|
||||
fallbackMode: TypeMappingMode? = null
|
||||
) = TypeMappingMode(
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
skipDeclarationSiteWildcards = skipDeclarationSiteWildcards,
|
||||
genericArgumentMode = fallbackMode)
|
||||
}
|
||||
|
||||
fun toGenericArgumentMode(effectiveVariance: Variance): TypeMappingMode =
|
||||
when (effectiveVariance) {
|
||||
Variance.IN_VARIANCE -> genericContravariantArgumentMode ?: this
|
||||
Variance.INVARIANT -> genericInvariantArgumentMode ?: this
|
||||
else -> genericArgumentMode ?: this
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user