Compare commits

..

29 Commits
beta4 ... beta2

Author SHA1 Message Date
Dmitry Jemerov
3674663d30 use Kotlin call hierarchy provider only for Kotlin elements, to ensure that it does not interfere with standard Java features of IntelliJ IDEA
(cherry picked from commit 7004917)
2015-11-26 11:34:34 +01:00
Natalia Ukhorskaya
e74282753a Fix compatibility with AS 2.0
#KT-10153 Fixed
2015-11-24 19:06:47 +03:00
Dmitry Jemerov
bbb92ead5b ensure that the short name of the Kotlin unused import inspection does not clash with Java (KT-10046)
(cherry picked from commit 30084df)
2015-11-20 14:07:12 +01:00
Michael Nedzelsky
08e9ff602f fix KT-10068 JsLibraryStdDetectionUtil does not use caching through JarUserDataManager
#KT-10068 Fixed
(cherry picked from commit ea4470a)
2015-11-19 18:54:44 +01:00
Nikolay Krasko
73596f7464 Enable bootstrapping for the branch 2015-11-19 16:14:54 +03:00
Alexander Udalov
0dcf34bb55 Fix deadlock on static initializers of KProperty implementations
#KT-10041 Fixed
2015-11-19 02:58:00 +03:00
Mikhail Glukhikh
0bcdfce84b Diagnostics corrected for smart cast impossible (cherry picked from commit 03287d5) 2015-11-18 20:13:28 +03:00
Yan Zhulanow
e8be0962c2 Android extensions: get descriptors using reflection (temporary change)
(cherry picked from commit f228c04)
2015-11-17 20:29:53 +03:00
Yan Zhulanow
8afd6421bb Revert "do not package kotlin-runtime and kotlin-reflect into Kotlin Android extensions zip"
This reverts commit 83bf5daf7f.
(cherry picked from commit a1dcede)
2015-11-17 20:29:45 +03:00
Dmitry Jemerov
a946126dca do not package kotlin-runtime and kotlin-reflect into Kotlin Android extensions zip
(cherry picked from commit 83bf5da)
2015-11-17 13:15:24 +01:00
Ilya Gorbunov
47895c0cc2 Correct deprecation replacement for Progression constructors.
Update testdata for LoadBuiltinsTest
2015-11-13 21:57:27 +03:00
Ilya Chernikov
bb6677620a Additional fix to the previous one: Disabling parallel builds without daemon again and undoing apprpriate fix to broken tests problem, since it effectively cancelled fix for parallel building itself and was causing exceptions on heavy builds 2015-11-12 19:14:00 +01:00
Ilya Chernikov
06104521f2 Disabling parallel builds without daemon again and undoing apprpriate fix to broken tests problem, since it effectively cancelled fix for parallel building itself and was causing exceptions on heavy builds 2015-11-12 17:13:26 +01:00
Valentin Kipyatkov
63fc7110a7 KT-9981 Code cleanup replace usages of !in incorrectly
#KT-9981 Fixed
2015-11-12 15:11:07 +03:00
Michael Bogdanov
f5bab93fd1 Additional diagnostic for KT-9980: KotlinFrontEndException: Exception while analyzing expression 2015-11-12 15:11:29 +03:00
Ilya Gorbunov
8f2c05668e Make MutableMap.set return Unit
#KT-7853 Fixed
2015-11-11 19:15:52 +03:00
Ilya Gorbunov
737763cc67 Restore correct sorting order (after cleanup in 17fc1d95) 2015-11-11 19:15:51 +03:00
Ilya Gorbunov
2bd44799f8 Simplify message expression from lambda argument when converting assert to if. 2015-11-11 19:15:50 +03:00
Ilya Gorbunov
e13fb0e7bc Deprecated with ERROR preconditions with eager message. 2015-11-11 19:15:49 +03:00
Ilya Gorbunov
16df7a9d92 Replace getStackTrace usages in j2k and testData. 2015-11-11 19:15:48 +03:00
Ilya Gorbunov
d5d803963f Replace Regex.match and matchAll usages 2015-11-11 19:15:47 +03:00
Ilya Gorbunov
20a15dc175 Refactor intention test files enumerating, do not use deprecated filter method, which would get another behavior after dropping deprecated one. 2015-11-11 19:15:46 +03:00
Ilya Gorbunov
26bd8600cf Drop deprecations and tighten up left ones. 2015-11-11 19:15:45 +03:00
Nikolay Krasko
abb116ef9a Fix locator syntax 2015-11-11 19:06:57 +03:00
Ilya Gorbunov
a336888858 Make emptyMap upperbound to be Any? rather than Any.
#KT-9963
2015-11-11 17:17:42 +03:00
Ilya Gorbunov
19501aac59 Do not override default AbstractList iterator() implementation for primitiveArray.asList wrappers.
#KT-9927 Fixed
2015-11-11 17:17:41 +03:00
Nikolay Krasko
f9ac5ae737 Enable auto-increment in beta2 branch 2015-11-11 17:13:27 +03:00
Dmitry Jemerov
9cb5defc43 don't analyze class repeatedly if we already found an annotated member there
#KT-8557 Fixed
(cherry picked from commit 6f2fb3f)
2015-11-11 15:10:12 +01:00
Valentin Kipyatkov
4782077357 KT-9928 Replacement not offered for a usage of symbol deprecated with DeprecationLevel.ERROR
#KT-9928 Fixed
(cherry picked from commit de11d57)
2015-11-11 17:08:58 +03:00
7205 changed files with 52990 additions and 95979 deletions

4
.idea/ant.xml generated
View File

@@ -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" />
@@ -11,12 +11,12 @@
<maximumHeapSize value="512" />
</buildFile>
<buildFile url="file://$PROJECT_DIR$/idea-runner/runner.xml" />
<buildFile url="file://$PROJECT_DIR$/replicate_versions.xml" />
<buildFile url="file://$PROJECT_DIR$/libraries/build-docs.xml">
<maximumHeapSize value="1024" />
<properties>
<property name="dokka.path" value="../../dokka" />
</properties>
</buildFile>
<buildFile url="file://$PROJECT_DIR$/TeamCityRelay.xml" />
</component>
</project>

View File

@@ -0,0 +1,26 @@
<component name="ArtifactManager">
<artifact name="KotlinAndroidExtensions">
<output-path>$PROJECT_DIR$/out/artifacts/KotlinAndroidExtensions</output-path>
<properties id="ant-postprocessing">
<options enabled="true">
<file>file://$PROJECT_DIR$/idea-runner/runner.xml</file>
<target>copy-runtime-for-idea-plugin</target>
</options>
</properties>
<root id="root">
<element id="directory" name="lib">
<element id="archive" name="kotlin-android-extensions.jar">
<element id="module-output" name="android-idea-plugin" />
</element>
<element id="directory" name="jps">
<element id="archive" name="kotlin-android-extensions-jps.jar">
<element id="module-output" name="android-jps-plugin" />
</element>
</element>
<element id="archive" name="android-compiler-plugin.jar">
<element id="module-output" name="android-compiler-plugin" />
</element>
</element>
</root>
</artifact>
</component>

View File

@@ -19,11 +19,10 @@
<element id="module-output" name="util" />
<element id="module-output" name="util.runtime" />
<element id="file-copy" path="$PROJECT_DIR$/resources/kotlinManifest.properties" />
<element id="module-output" name="daemon-client" />
<element id="module-output" name="daemon-common" />
<element id="module-output" name="kotlinr" />
<element id="module-output" name="rmi-interface" />
<element id="module-output" name="deserialization" />
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/native-platform-uberjar.jar" path-in-jar="/" />
<element id="module-output" name="android-jps-plugin" />
</root>
</artifact>
</component>

View File

@@ -42,22 +42,16 @@
<element id="module-output" name="serialization" />
<element id="module-output" name="idea-completion" />
<element id="module-output" name="idea-core" />
<element id="module-output" name="idea-js" />
<element id="module-output" name="container" />
<element id="module-output" name="daemon-common" />
<element id="module-output" name="rmi-interface" />
<element id="module-output" name="idea-repl" />
<element id="module-output" name="idea-live-templates" />
</element>
<element id="library" level="project" name="javax.inject" />
<element id="directory" name="jps">
<element id="artifact" artifact-name="KotlinJpsPlugin" />
</element>
<element id="library" level="project" name="markdown" />
<element id="archive" name="kotlin-android-extensions-plugin.jar">
<element id="module-output" name="android-idea-plugin" />
</element>
<element id="archive" name="kotlin-android-extensions-compiler-plugin.jar">
<element id="module-output" name="android-compiler-plugin" />
</element>
</element>
<element id="directory" name="kotlinc">
<element id="dir-copy" path="$PROJECT_DIR$/dist/kotlinc" />

View File

@@ -2,7 +2,6 @@
<dictionary name="Nikolay.Krasko">
<words>
<w>accessors</w>
<w>fqname</w>
<w>goto</w>
<w>gradle</w>
<w>intrinsics</w>

BIN
.idea/icon.png generated

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -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>

11
.idea/modules.xml generated
View File

@@ -21,9 +21,6 @@
<module fileurl="file://$PROJECT_DIR$/compiler/tests/compiler-tests.iml" filepath="$PROJECT_DIR$/compiler/tests/compiler-tests.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" filepath="$PROJECT_DIR$/compiler/conditional-preprocessor/conditional-preprocessor.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/container/container.iml" filepath="$PROJECT_DIR$/compiler/container/container.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/daemon/daemon.iml" filepath="$PROJECT_DIR$/compiler/daemon/daemon.iml" group="compiler/daemon" />
<module fileurl="file://$PROJECT_DIR$/compiler/daemon/daemon-client/daemon-client.iml" filepath="$PROJECT_DIR$/compiler/daemon/daemon-client/daemon-client.iml" group="compiler/daemon" />
<module fileurl="file://$PROJECT_DIR$/compiler/daemon/daemon-common/daemon-common.iml" filepath="$PROJECT_DIR$/compiler/daemon/daemon-common/daemon-common.iml" group="compiler/daemon" />
<module fileurl="file://$PROJECT_DIR$/core/descriptor.loader.java/descriptor.loader.java.iml" filepath="$PROJECT_DIR$/core/descriptor.loader.java/descriptor.loader.java.iml" group="core" />
<module fileurl="file://$PROJECT_DIR$/core/descriptors/descriptors.iml" filepath="$PROJECT_DIR$/core/descriptors/descriptors.iml" group="core" />
<module fileurl="file://$PROJECT_DIR$/core/descriptors.runtime/descriptors.runtime.iml" filepath="$PROJECT_DIR$/core/descriptors.runtime/descriptors.runtime.iml" group="core" />
@@ -39,8 +36,8 @@
<module fileurl="file://$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" filepath="$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" group="ide" />
<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-js/idea-js.iml" filepath="$PROJECT_DIR$/idea/idea-js/idea-js.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" />
@@ -56,13 +53,15 @@
<module fileurl="file://$PROJECT_DIR$/js/js.translator/js.translator.iml" filepath="$PROJECT_DIR$/js/js.translator/js.translator.iml" group="compiler/js" />
<module fileurl="file://$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" filepath="$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" group="ide/jps" />
<module fileurl="file://$PROJECT_DIR$/idea/kotlin-android-plugin/kotlin-android-plugin.iml" filepath="$PROJECT_DIR$/idea/kotlin-android-plugin/kotlin-android-plugin.iml" group="ide" />
<module fileurl="file://$PROJECT_DIR$/compiler/rmi/kotlinr/kotlinr.iml" filepath="$PROJECT_DIR$/compiler/rmi/kotlinr/kotlinr.iml" group="rmi" />
<module fileurl="file://$PROJECT_DIR$/compiler/light-classes/light-classes.iml" filepath="$PROJECT_DIR$/compiler/light-classes/light-classes.iml" group="compiler/java" />
<module fileurl="file://$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" filepath="$PROJECT_DIR$/compiler/plugin-api/plugin-api.iml" group="compiler" />
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/preloader.iml" filepath="$PROJECT_DIR$/compiler/preloader/preloader.iml" group="compiler/cli" />
<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$/compiler/rmi/rmi-interface/rmi-interface.iml" filepath="$PROJECT_DIR$/compiler/rmi/rmi-interface/rmi-interface.iml" group="rmi" />
<module fileurl="file://$PROJECT_DIR$/compiler/rmi/rmi-server/rmi-server.iml" filepath="$PROJECT_DIR$/compiler/rmi/rmi-server/rmi-server.iml" group="rmi" />
<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>

View File

@@ -24,7 +24,9 @@
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinPlugin" />
</option>
<option name="BuildArtifacts" enabled="true" />
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinAndroidExtensions" />
</option>
</method>
</configuration>
</component>

View File

@@ -43,7 +43,9 @@
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinPlugin" />
</option>
<option name="BuildArtifacts" enabled="true" />
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinAndroidExtensions" />
</option>
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea-runner/runner.xml" target="force-enable-kotlin-plugin" />
</method>
</configuration>

View File

@@ -24,7 +24,9 @@
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinPlugin" />
</option>
<option name="BuildArtifacts" enabled="true" />
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinAndroidExtensions" />
</option>
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea-runner/runner.xml" target="force-enable-kotlin-plugin" />
</method>
</configuration>

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA (win)" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
@@ -5,7 +6,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" />
@@ -16,7 +17,9 @@
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinPlugin" />
</option>
<option name="BuildArtifacts" enabled="true" />
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinAndroidExtensions" />
</option>
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea-runner/runner.xml" target="force-enable-kotlin-plugin" />
</method>
</configuration>

View File

@@ -22,7 +22,9 @@
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinPlugin" />
</option>
<option name="BuildArtifacts" enabled="true" />
<option name="BuildArtifacts" enabled="true">
<artifact name="KotlinAndroidExtensions" />
</option>
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/idea_runner/runner.xml" target="force_enable_kotlin_plugin" />
</method>
</configuration>

View File

@@ -1,4 +1,3 @@
<a href="http://kotlinslackin.herokuapp.com"><img src="https://kotlinslackin.herokuapp.com/badge.svg" height="20"></a>
[![TeamCity (simple build status)](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/bt345.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=bt345&branch_Kotlin=%3Cdefault%3E&tab=buildTypeStatusDiv)
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.kotlin/kotlin-maven-plugin.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)

View File

@@ -1,5 +1,6 @@
<project name="Kotlin CI Steps" default="none">
<import file="build.xml" optional="false"/>
<import file="replicate_versions.xml" optional="false"/>
<property name="build.number" value="snapshot"/>
<property name="jdk16.home" value="${java.home}"/>
@@ -12,6 +13,10 @@
<property name="plugin.xml.bk" value="${version_substitute_dir}/plugin.xml.bk"/>
<property name="plugin.xml.versioned" value="${plugin.xml}.versioned"/>
<property name="android-extensions.plugin.xml" value="plugins/android-idea-plugin/src/META-INF/plugin.xml"/>
<property name="android-extensions.plugin.xml.bk" value="${version_substitute_dir}/kotlin-android-extensions.plugin.xml.bk"/>
<property name="android-extensions.plugin.xml.versioned" value="${android-extensions.plugin.xml}.versioned"/>
<property name="compiler.version.java" value="compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/KotlinVersion.java"/>
<property name="compiler.version.java.bk" value="${version_substitute_dir}/KotlinVersion.java.bk"/>
<property name="compiler.version.java.versioned" value="${compiler.version.java}.versioned"/>
@@ -20,9 +25,6 @@
<property name="bare.plugin.zip" value="${artifact.output.path}/kotlin-bare-plugin-${build.number}.zip"/>
<property name="android-extensions.zip" value="${artifact.output.path}/kotlin-android-extensions-plugin-${build.number}.zip"/>
<property name="kotlin.bare.plugin.xml" value="jps-plugin/bare-plugin/src/META-INF/plugin.xml"/>
<property name="kotlin.bare.plugin.xml.bk" value="${version_substitute_dir}/kotlin.bare.plugin.xml.bk"/>
<macrodef name="echoprop">
<attribute name="prop"/>
<sequential>
@@ -85,23 +87,25 @@
target.file.versioned="${plugin.xml.versioned}"
test.string="&lt;version&gt;@snapshot@&lt;/version&gt;"/>
<substituteVersionInFile
target.file="${android-extensions.plugin.xml}"
target.file.bk="${android-extensions.plugin.xml.bk}"
target.file.versioned="${android-extensions.plugin.xml.versioned}"
test.string="&lt;version&gt;@snapshot@&lt;/version&gt;"/>
<substituteVersionInFile
target.file="${compiler.version.java}"
target.file.bk="${compiler.version.java.bk}"
target.file.versioned="${compiler.version.java.versioned}"
test.string="public static final String VERSION = &quot;@snapshot@&quot;;"/>
<substituteVersionInFile
target.file="${kotlin.bare.plugin.xml}"
target.file.bk="${kotlin.bare.plugin.xml.bk}"
test.string="&lt;version&gt;@snapshot@&lt;/version&gt;"/>
</target>
<replicateIdeaVersion target.file="${android-extensions.plugin.xml}"/>
</target>
<target name="revertTemplateFiles">
<copy file="${plugin.xml.bk}" tofile="${plugin.xml}" overwrite="true"/>
<copy file="${android-extensions.plugin.xml.bk}" tofile="${android-extensions.plugin.xml}" overwrite="true"/>
<copy file="${compiler.version.java.bk}" tofile="${compiler.version.java}" overwrite="true"/>
<copy file="${kotlin.bare.plugin.xml.bk}" tofile="${kotlin.bare.plugin.xml}" overwrite="true"/>
<delete dir="${version_substitute_dir}" quiet="true"/>
</target>
@@ -129,8 +133,9 @@
<zipPlugin filename="${bare.plugin.zip}" dir="BareKotlin"/>
<zip destfile="${android-extensions.zip}">
<zipfileset prefix="META-INF" dir="${basedir}/plugins/android-idea-plugin/old_plugin" includes="plugin.xml" />
<zipfileset prefix="KotlinAndroidExtensions" dir="${artifact.output.path}/KotlinAndroidExtensions"/>
</zip>
<delete dir="${artifact.output.path}/KotlinAndroidExtensions" quiet="true"/>
</target>
<macrodef name="print-statistic">
@@ -158,11 +163,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"/>

View File

@@ -1,99 +0,0 @@
<project name="Change plugins version" default="change-version">
<property name="relay.origin.version" value="1.0.0-beta-2423"/>
<property name="relay.substitute.version" value="1.0.0-beta-2423-IJ-141-3"/>
<property name="relay.plugins.dir" value="artifacts"/>
<property name="relay.unpack.directory" value="relay-dir"/>
<macrodef name="substituteRegexpInFile">
<attribute name="src.file"/>
<attribute name="output.dir"/>
<attribute name="origin.version"/>
<attribute name="substituted.version"/>
<sequential>
<copy todir="@{output.dir}">
<fileset file="@{src.file}"/>
<filterchain>
<replaceregex pattern="@{origin.version}" replace="@{substituted.version}" />
</filterchain>
</copy>
</sequential>
</macrodef>
<macrodef name="substitudeVersionInPlugin">
<attribute name="plugin.path"/>
<attribute name="plugin.jar.name"/>
<attribute name="origin.version"/>
<attribute name="substituted.version"/>
<attribute name="plugin.subdir"/>
<attribute name="output-dir" default="@{substituted.version}"/>
<attribute name="output.plugin.file.name" default="@{plugin.jar.name}-@{substituted.version}.zip"/>
<attribute name="temp.origin.dir" default="${relay.unpack.directory}/@{plugin.jar.name}/plugin-origin"/>
<attribute name="temp.substitute.dir" default="${relay.unpack.directory}/@{plugin.jar.name}/substitute"/>
<sequential>
<delete dir="${relay.unpack.directory}/@{plugin.jar.name}"/>
<mkdir dir="${relay.unpack.directory}/@{plugin.jar.name}"/>
<unzip src="@{plugin.path}" dest="@{temp.origin.dir}">
<patternset>
<include name="**/lib/@{plugin.jar.name}.jar" />
</patternset>
<flattenmapper/>
</unzip>
<unzip src="@{temp.origin.dir}/@{plugin.jar.name}.jar" dest="@{temp.origin.dir}">
<patternset>
<include name="**/META-INF/plugin.xml" />
</patternset>
<flattenmapper/>
</unzip>
<substituteRegexpInFile
src.file="@{temp.origin.dir}/plugin.xml" output.dir="@{temp.substitute.dir}"
origin.version="@{origin.version}" substituted.version="@{substituted.version}"/>
<!-- Copy updated file back into jar -->
<copy file="@{temp.origin.dir}/@{plugin.jar.name}.jar" todir="@{temp.substitute.dir}"/>
<jar destfile="@{temp.substitute.dir}/@{plugin.jar.name}.jar" update="true">
<zipfileset file="@{temp.substitute.dir}/plugin.xml" prefix="META-INF"/>
</jar>
<!-- Pack updated plugin.jar back to zip file -->
<copy file="@{plugin.path}" tofile="@{substituted.version}/@{output.plugin.file.name}"/>
<zip destfile="@{substituted.version}/@{output.plugin.file.name}" update="true">
<zipfileset file="@{temp.substitute.dir}/@{plugin.jar.name}.jar" prefix="@{plugin.subdir}/lib"/>
</zip>
</sequential>
</macrodef>
<target name="change-version" description="Repack plugin with other version">
<delete dir="${relay.unpack.directory}"/>
<delete dir="${relay.substitute.version}"/>
<mkdir dir="${relay.unpack.directory}"/>
<mkdir dir="${relay.substitute.version}"/>
<substitudeVersionInPlugin
plugin.jar.name="kotlin-plugin"
plugin.path="${relay.plugins.dir}/kotlin-plugin-${relay.origin.version}.zip"
origin.version="${relay.origin.version}"
plugin.subdir="Kotlin"
substituted.version="${relay.substitute.version}"/>
<substitudeVersionInPlugin
plugin.jar.name="kotlin-bare-plugin"
plugin.path="${relay.plugins.dir}/kotlin-bare-plugin-${relay.origin.version}.zip"
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>

View File

@@ -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}"/>
@@ -94,8 +91,8 @@
<include name="compiler/frontend.java/src"/>
<include name="compiler/light-classes/src"/>
<include name="compiler/plugin-api/src"/>
<include name="compiler/daemon/src"/>
<include name="compiler/daemon/daemon-common/src"/>
<include name="compiler/rmi/rmi-server/src"/>
<include name="compiler/rmi/rmi-interface/src"/>
<include name="compiler/serialization/src"/>
<include name="compiler/util/src"/>
<include name="js/js.dart-ast/src"/>
@@ -121,7 +118,8 @@
<include name="cli/**"/>
<include name="cli-common/**"/>
<include name="conditional-preprocessor/**"/>
<include name="daemon/**"/>
<include name="rmi-server/**"/>
<include name="rmi-interface/**"/>
<include name="util/**"/>
<include name="util.runtime/**"/>
<include name="light-classes/**"/>
@@ -180,33 +178,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 ? -->
@@ -220,8 +204,8 @@
<fileset dir="compiler/cli/src"/>
<fileset dir="compiler/cli/cli-common/src"/>
<fileset dir="compiler/conditional-preprocessor/src"/>
<fileset dir="compiler/daemon/src"/>
<fileset dir="compiler/daemon/daemon-common/src"/>
<fileset dir="compiler/rmi/rmi-server/src"/>
<fileset dir="compiler/rmi/rmi-interface/src"/>
<fileset dir="compiler/container/src"/>
<fileset dir="compiler/frontend/src"/>
<fileset dir="compiler/frontend.java/src"/>
@@ -310,7 +294,6 @@
<arg value="@{output}"/>
<arg value="-no-stdlib"/>
<arg value="-meta-info"/>
<arg value="-kjsm"/>
<arg line="-main noCall"/>
</java>
</sequential>
@@ -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}/${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}/${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}/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}">
<file name="${compiled.builtins.js}"/>
</sources>
<sources dir="${js.stdlib.output.dir}">
<sources dir="${output}">
<file name="${compiled.stdlib.js}"/>
</sources>
@@ -379,11 +362,8 @@
<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="">
<include name="kotlin.js"/>
<include name="${compiled.stdlib.meta.js}"/>
<include name="stdlib/**"/>
</zipfileset>
<zipfileset file="${output}/kotlin.js" prefix=""/>
<zipfileset file="${output}/${compiled.stdlib.meta.js}" prefix=""/>
<manifest>
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
@@ -600,12 +580,12 @@
</jar>
</target>
<target name="daemon-client">
<cleandir dir="${output}/classes/daemon-client"/>
<target name="kotlinr">
<cleandir dir="${output}/classes/kotlinr"/>
<kotlinc output="${output}/classes/daemon-client" modulename="client">
<kotlinc output="${output}/classes/kotlinr" modulename="kotlin-rmi">
<src>
<pathelement path="compiler/daemon/daemon-client/src"/>
<pathelement path="compiler/rmi/kotlinr/src"/>
</src>
<classpath>
<pathelement path="${bootstrap.runtime}"/>
@@ -615,8 +595,8 @@
</classpath>
</kotlinc>
<jar destfile="${kotlin-home}/lib/kotlin-daemon-client.jar">
<fileset dir="${output}/classes/daemon-client"/>
<jar destfile="${kotlin-home}/lib/kotlinr.jar">
<fileset dir="${output}/classes/kotlinr"/>
<zipfileset src="${dependencies.dir}/native-platform-uberjar.jar" includes="**" />
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
</jar>
@@ -798,7 +778,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 +788,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 +932,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,kotlinr"
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"
@@ -1077,5 +1035,4 @@
<target name="build-bootstrap-artifacts" depends="dist,zip-compiler"/>
<target name="build-artifacts" depends="dist,zip-compiler,kotlin-for-upsource,zip-test-data"/>
<!-- Dummy change to see build in TeamCity dependencies -->
</project>

View File

@@ -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();
@@ -188,12 +188,6 @@ public class CodegenUtil {
return null;
}
}
if (statement instanceof KtConstructorDelegationReferenceExpression && statement.getTextLength() == 0) {
// PsiElement for constructor delegation reference is always generated, so we shouldn't mark it's line number if it's empty
return null;
}
Document document = file.getViewProvider().getDocument();
return document != null ? document.getLineNumber(markEndOffset ? statement.getTextRange().getEndOffset() : statement.getTextOffset()) + 1 : null;
}

View File

@@ -31,41 +31,37 @@ 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" }

View File

@@ -43,16 +43,5 @@ public class SimpleOutputFile(
override fun asByteArray(): ByteArray = content.toByteArray()
override fun asText(): String = content
override fun toString() = "$relativePath (compiled from $sourceFiles)"
}
public class SimpleOutputBinaryFile(
override val sourceFiles: List<File>,
override val relativePath: String,
private val content: ByteArray
) : OutputFile {
override fun asByteArray(): ByteArray = content
override fun asText(): String = String(content)
override fun toString() = "$relativePath (compiled from $sourceFiles)"
}

View File

@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
public class AccessorForConstructorDescriptor(
private val calleeDescriptor: ConstructorDescriptor,
@@ -39,16 +38,6 @@ public class AccessorForConstructorDescriptor(
override fun getSuperCallTarget(): ClassDescriptor? = superCallTarget
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),

View File

@@ -426,7 +426,7 @@ public abstract class AnnotationCodegen {
for (ConstantValue<?> value : values) {
if (value instanceof EnumValue) {
ClassDescriptor enumEntry = ((EnumValue) value).getValue();
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
KotlinType classObjectType = DescriptorUtilsKt.getClassObjectType(enumEntry);
if (classObjectType != null) {
if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) {
result.add(ElementType.valueOf(enumEntry.getName().asString()));
@@ -454,7 +454,7 @@ public abstract class AnnotationCodegen {
ConstantValue<?> compileTimeConstant = valueArguments.iterator().next();
if (compileTimeConstant instanceof EnumValue) {
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
KotlinType classObjectType = DescriptorUtilsKt.getClassObjectType(enumEntry);
if (classObjectType != null) {
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
return RetentionPolicy.valueOf(enumEntry.getName().asString());

View File

@@ -38,17 +38,20 @@ import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.load.java.JavaVisibilities;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.resolve.DeprecationUtilKt;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt;
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
@@ -226,9 +229,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;
@@ -325,6 +328,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;
@@ -376,6 +382,11 @@ public class AsmUtil {
}
}
if (memberDescriptor instanceof PropertyDescriptor &&
((PropertyDescriptor) memberDescriptor).isConst() || hasJvmFieldAnnotation(memberDescriptor)) {
return null;
}
return null;
}
@@ -438,6 +449,14 @@ public class AsmUtil {
}
}
public static List<FieldInfo> transformCapturedParams(List<Pair<String, Type>> allFields, Type owner) {
List<FieldInfo> result = new ArrayList<FieldInfo>();
for (Pair<String, Type> field : allFields) {
result.add(FieldInfo.createForHiddenField(owner, field.second, field.first));
}
return result;
}
public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) {
assert !info.isStatic();
Type fieldType = info.getFieldType();
@@ -632,6 +651,43 @@ public class AsmUtil {
}
}
public static boolean genNotNullAssertionForField(
@NotNull InstructionAdapter v,
@NotNull GenerationState state,
@NotNull PropertyDescriptor descriptor
) {
return genNotNullAssertion(v, state, descriptor, "checkFieldIsNotNull");
}
private static boolean genNotNullAssertion(
@NotNull InstructionAdapter v,
@NotNull GenerationState state,
@NotNull CallableDescriptor descriptor,
@NotNull String assertMethodToCall
) {
// Assertions are generated elsewhere for platform types
if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return false;
if (!state.isCallAssertionsEnabled()) return false;
if (!isDeclaredInJava(descriptor)) return false;
KotlinType type = descriptor.getReturnType();
if (type == null || isNullableType(FlexibleTypesKt.lowerIfFlexible(type))) return false;
Type asmType = state.getTypeMapper().mapReturnType(descriptor);
if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) {
v.dup();
v.visitLdcInsn(descriptor.getContainingDeclaration().getName().asString());
v.visitLdcInsn(descriptor.getName().asString());
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, assertMethodToCall,
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", false);
return true;
}
return false;
}
@NotNull
public static StackValue genNotNullAssertions(
@NotNull GenerationState state,
@@ -656,6 +712,19 @@ public class AsmUtil {
};
}
private static boolean isDeclaredInJava(@NotNull CallableDescriptor callableDescriptor) {
CallableDescriptor descriptor = callableDescriptor;
while (true) {
if (descriptor instanceof JavaCallableMemberDescriptor) {
return true;
}
CallableDescriptor original = descriptor.getOriginal();
if (descriptor == original) break;
descriptor = original;
}
return false;
}
public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
v.aconst(null);

View File

@@ -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);
}
}

View File

@@ -45,7 +45,8 @@ public interface Callable {
}
}
public fun afterReceiverGeneration(v: InstructionAdapter) {
public fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
}
}

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
@@ -30,7 +31,7 @@ import org.jetbrains.org.objectweb.asm.util.Printer
public class CallableMethod(
override val owner: Type,
private val defaultImplOwner: Type?,
private val defaultMethodDesc: String,
private val defaultImplParam: Type?,
private val signature: JvmMethodSignature,
private val invokeOpcode: Int,
override val dispatchReceiverType: Type?,
@@ -55,21 +56,24 @@ public class CallableMethod(
}
public fun genInvokeDefaultInstruction(v: InstructionAdapter) {
if (defaultImplOwner == null) {
if (defaultImplOwner == null || defaultImplParam == null) {
throw IllegalStateException()
}
val method = getAsmMethod()
val desc = JetTypeMapper.getDefaultDescriptor(
method,
if (invokeOpcode == INVOKESTATIC) null else defaultImplParam.getDescriptor(),
extensionReceiverType != null
)
if ("<init>".equals(method.getName())) {
v.aconst(null)
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", defaultMethodDesc, false)
v.visitMethodInsn(INVOKESPECIAL, defaultImplOwner.getInternalName(), "<init>", desc, false)
}
else {
v.visitMethodInsn(INVOKESTATIC, defaultImplOwner.getInternalName(),
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, false)
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
method.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, desc, false)
}
}

View File

@@ -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) {

View File

@@ -275,7 +275,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
if (bridge.equals(delegate)) return;
MethodVisitor mv =
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC,
v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE,
bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
@@ -283,7 +283,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
MemberCodegen.markLineNumberForDescriptor(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
MemberCodegen.markLineNumberForSyntheticFunction(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
iv.load(0, asmType);
@@ -368,6 +368,13 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
}
else if (container instanceof ScriptDescriptor) {
// TODO: correct container for scripts (KScript?)
StackValue value = generateClassLiteralReference(
state.getTypeMapper(), ((ScriptDescriptor) container).getClassDescriptor().getDefaultType()
);
value.put(K_CLASS_TYPE, iv);
}
else {
iv.aconst(null);
}

View File

@@ -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)

View File

@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.ScriptCodeDescriptor;
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.diagnostics.Errors;
@@ -57,6 +58,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
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;
@@ -308,29 +310,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public void gen(KtElement expr, Type type) {
StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr);
// for repl store the result of the last line into special field
if (value.type != Type.VOID_TYPE && state.getReplSpecific().getShouldGenerateScriptResultValue()) {
ScriptContext context = getScriptContext();
if (expr == context.getLastStatement()) {
StackValue.Field resultValue = StackValue.field(context.getResultFieldInfo(), StackValue.LOCAL_0);
resultValue.store(value, v);
state.getReplSpecific().setHasResult(true);
return;
}
}
value.put(type, v);
}
@NotNull
private ScriptContext getScriptContext() {
CodegenContext context = getContext();
while (!(context instanceof ScriptContext)) {
context = context.getParentContext();
}
return (ScriptContext) context;
}
public StackValue genLazy(KtElement expr, Type type) {
StackValue value = gen(expr);
return StackValue.coercion(value, type);
@@ -668,7 +650,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()
@@ -686,15 +668,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());
@@ -761,7 +743,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// This method consumes range/progression from stack
// The result is stored to local variable
protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + elementType.getDescriptor(), false);
Type boxedType = boxType(elementType);
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor(), false);
StackValue.coerce(boxedType, elementType, v);
v.store(varToStore, elementType);
}
}
@@ -917,6 +901,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
protected int endVar;
// For integer progressions instead of comparing loopParameterVar with endVar at the beginning of an iteration we check whether
// loopParameterVar == finalVar at the end of the iteration (and also if there should be any iterations at all, before the loop)
protected final boolean isIntegerProgression;
private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) {
super(forExpression);
@@ -926,6 +914,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
case Type.SHORT:
case Type.CHAR:
case Type.LONG:
isIntegerProgression = true;
break;
case Type.DOUBLE:
case Type.FLOAT:
isIntegerProgression = false;
break;
default:
@@ -940,12 +934,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
endVar = createLoopTempVariable(asmElementType);
}
// Index of the local variable holding the actual last value of the loop parameter.
// For ranges it equals end, for progressions it's a function of start, end and increment
protected abstract int getFinalVar();
protected void checkPostCondition(@NotNull Label loopExit) {
assert endVar != -1 :
"endVar must be allocated, endVar = " + endVar;
int finalVar = getFinalVar();
assert isIntegerProgression && finalVar != -1 :
"Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.load(finalVar, asmElementType);
if (asmElementType.getSort() == Type.LONG) {
v.lcmp();
v.ifeq(loopExit);
@@ -954,10 +953,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.ificmpeq(loopExit);
}
}
@Override
public void checkPreCondition(@NotNull Label loopExit) {
}
}
private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
@@ -974,8 +969,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected abstract void storeRangeStartAndEnd();
@Override
protected int getFinalVar() {
return endVar;
}
@Override
public void checkPreCondition(@NotNull Label loopExit) {
if (isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.cmpg(asmElementType);
v.ifgt(loopExit);
}
@Override
public void checkEmptyLoop(@NotNull Label loopExit) {
if (!isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
@@ -994,7 +1006,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
protected void increment(@NotNull Label loopExit) {
checkPostCondition(loopExit);
if (isIntegerProgression) {
checkPostCondition(loopExit);
}
if (asmElementType == Type.INT_TYPE) {
v.iinc(loopParameterVar, 1);
@@ -1041,9 +1055,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
gen(forExpression.getLoopRange(), asmLoopRangeType);
v.dup();
// ranges inherit first and last from corresponding progressions
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
}
}
@@ -1051,10 +1064,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private int incrementVar;
private Type incrementType;
private int finalVar;
private ForInProgressionExpressionLoopGenerator(@NotNull KtForExpression forExpression) {
super(forExpression);
}
@Override
protected int getFinalVar() {
return finalVar;
}
@Override
public void beforeLoop() {
super.beforeLoop();
@@ -1074,13 +1094,66 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.dup();
v.dup();
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar);
storeFinalVar();
}
private void storeFinalVar() {
if (!isIntegerProgression) {
finalVar = -1;
return;
}
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.load(incrementVar, incrementType);
Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE;
v.invokestatic("kotlin/internal/ProgressionUtilKt", "getProgressionFinalElement",
Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType), false);
finalVar = createLoopTempVariable(asmElementType);
v.store(finalVar, asmElementType);
}
@Override
public void checkPreCondition(@NotNull Label loopExit) {
if (isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.load(incrementVar, incrementType);
Label negativeIncrement = new Label();
Label afterIf = new Label();
if (incrementType.getSort() == Type.DOUBLE) {
v.dconst(0.0);
}
else {
v.fconst(0.0f);
}
v.cmpl(incrementType);
v.ifle(negativeIncrement); // if increment < 0, jump
// increment > 0
v.cmpg(asmElementType); // if loop parameter is NaN, exit from loop, as well
v.ifgt(loopExit);
v.goTo(afterIf);
// increment < 0
v.mark(negativeIncrement);
v.cmpl(asmElementType); // if loop parameter is NaN, exit from loop, as well
v.iflt(loopExit);
v.mark(afterIf);
}
@Override
public void checkEmptyLoop(@NotNull Label loopExit) {
if (!isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
@@ -1125,7 +1198,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
protected void increment(@NotNull Label loopExit) {
checkPostCondition(loopExit);
if (isIntegerProgression) {
checkPostCondition(loopExit);
}
v.load(loopParameterVar, asmElementType);
v.load(incrementVar, asmElementType);
@@ -1154,7 +1229,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private StackValue generateBreakOrContinueExpression(
@NotNull KtExpressionWithLabel expression,
boolean isBreak,
final @NotNull Label afterBreakContinueLabel
@NotNull Label afterBreakContinueLabel
) {
assert expression instanceof KtContinueExpression || expression instanceof KtBreakExpression;
@@ -1173,16 +1248,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (labelElement == null ||
loopBlockStackElement.targetLabel != null &&
labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) {
final Label label = isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel;
return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter adapter) {
PseudoInsnsKt.fixStackAndJump(v, label);
v.mark(afterBreakContinueLabel);
return Unit.INSTANCE;
}
}
);
Label label = isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel;
PseudoInsnsKt.fixStackAndJump(v, label);
v.mark(afterBreakContinueLabel);
return StackValue.none();
}
}
else {
@@ -1331,7 +1400,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());
}
@@ -1568,9 +1637,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);
}
}
@@ -1608,9 +1677,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);
}
}
@@ -1790,37 +1859,33 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@Override
public StackValue visitReturnExpression(@NotNull final KtReturnExpression expression, StackValue receiver) {
return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter adapter) {
KtExpression returnedExpression = expression.getReturnedExpression();
CallableMemberDescriptor descriptor = getContext().getContextDescriptor();
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
boolean isNonLocalReturn = nonLocalReturn != null;
if (isNonLocalReturn && !state.isInlineEnabled()) {
state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression));
genThrow(v, "java/lang/UnsupportedOperationException",
"Non-local returns are not allowed with inlining disabled");
return Unit.INSTANCE;
}
public StackValue visitReturnExpression(@NotNull KtReturnExpression expression, StackValue receiver) {
KtExpression returnedExpression = expression.getReturnedExpression();
CallableMemberDescriptor descriptor = getContext().getContextDescriptor();
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
boolean isNonLocalReturn = nonLocalReturn != null;
if (isNonLocalReturn && !state.isInlineEnabled()) {
state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression));
genThrow(v, "java/lang/UnsupportedOperationException",
"Non-local returns are not allowed with inlining disabled");
return StackValue.none();
}
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType;
if (returnedExpression != null) {
gen(returnedExpression, returnType);
}
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType;
if (returnedExpression != null) {
gen(returnedExpression, returnType);
}
Label afterReturnLabel = new Label();
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
Label afterReturnLabel = new Label();
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel);
if (isNonLocalReturn) {
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
}
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
v.mark(afterReturnLabel);
return Unit.INSTANCE;
}
});
if (isNonLocalReturn) {
InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName);
}
v.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
v.mark(afterReturnLabel);
return StackValue.none();
}
public void generateFinallyBlocksIfNeeded(Type returnType, @NotNull Label afterReturnLabel) {
@@ -1878,10 +1943,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (!endsWithReturn(expr)) {
markLineNumber(expr, true);
if (isLambdaVoidBody(expr, returnType)) {
markLineNumber((KtFunctionLiteral) expr.getParent(), true);
}
if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) {
StackValue.none().put(returnType, v);
}
@@ -1899,17 +1960,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return bodyExpression instanceof KtReturnExpression;
}
private static boolean isLambdaVoidBody(KtElement bodyExpression, Type returnType) {
if (bodyExpression instanceof KtBlockExpression) {
PsiElement parent = bodyExpression.getParent();
if (parent instanceof KtFunctionLiteral) {
return Type.VOID_TYPE.equals(returnType);
}
}
return false;
}
@Override
public StackValue visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, @NotNull StackValue receiver) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
@@ -1993,6 +2043,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (localOrCaptured != null) {
return localOrCaptured;
}
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (descriptor instanceof ValueParameterDescriptor && container instanceof ScriptCodeDescriptor) {
ScriptCodeDescriptor scriptCodeDescriptor = (ScriptCodeDescriptor) container;
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) scriptCodeDescriptor.getContainingDeclaration();
Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
//noinspection ConstantConditions
StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false);
Type fieldType = typeMapper.mapType(valueParameterDescriptor);
return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false, script,
valueParameterDescriptor);
}
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
}
@@ -2071,10 +2136,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 ? call.getExplicitReceiver().getType() : null;
}
return null;
}
@@ -2122,7 +2184,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
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) ||
@@ -2163,7 +2225,13 @@ 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);
@@ -2247,8 +2315,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) {
@@ -2321,19 +2389,17 @@ 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);
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
if (!codegenExtensions.isEmpty()) {
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
for (ExpressionCodegenExtension extension : codegenExtensions) {
StackValue stackValue = extension.applyFunction(receiver, resolvedCall, context);
if (stackValue != null) return stackValue;
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);
}
}
Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall);
Callable callable = resolveToCallable(fd, superCall, resolvedCall);
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
}
@@ -2390,10 +2456,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull CallGenerator callGenerator,
@NotNull ArgumentGenerator argumentGenerator
) {
callableMethod.beforeParameterGeneration(v, null);
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
if (!codegenExtensions.isEmpty()) {
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
for (ExpressionCodegenExtension extension : codegenExtensions) {
if (extension.applyFunction(receiver, resolvedCall, context)) return;
}
}
receiver.put(receiver.type, v);
callableMethod.afterReceiverGeneration(v);
}
callGenerator.putHiddenParams();
@@ -2472,8 +2548,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(
@@ -2482,9 +2559,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@NotNull
public StackValue generateReceiverValue(@Nullable ReceiverValue receiverValue, boolean isSuper) {
if (receiverValue instanceof ImplicitClassReceiver) {
ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor();
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue, boolean isSuper) {
if (receiverValue instanceof ClassReceiver) {
ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor();
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
CallableMemberDescriptor contextDescriptor = context.getContextDescriptor();
if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) {
@@ -2494,15 +2571,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.singleton(receiverDescriptor, typeMapper);
}
}
else if (receiverDescriptor instanceof ScriptDescriptor) {
return generateScriptReceiver
((ScriptDescriptor) receiverDescriptor);
}
else {
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper,
receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor));
receiverValue instanceof CastClassReceiver || isEnumEntry(receiverDescriptor));
}
}
else if (receiverValue instanceof ScriptReceiver) {
return generateScript((ScriptReceiver) receiverValue);
}
else if (receiverValue instanceof ExtensionReceiver) {
return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor());
}
@@ -2519,8 +2595,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return context.generateReceiver(descriptor, state, false);
}
@NotNull
private StackValue generateScriptReceiver(@NotNull ScriptDescriptor receiver) {
private StackValue generateScript(@NotNull ScriptReceiver receiver) {
CodegenContext cur = context;
StackValue result = StackValue.LOCAL_0;
boolean inStartConstructorContext = cur instanceof ConstructorContext;
@@ -2532,14 +2607,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (cur instanceof ScriptContext) {
ScriptContext scriptContext = (ScriptContext) cur;
if (scriptContext.getScriptDescriptor() == receiver) {
ScriptDescriptor receiverDeclarationDescriptor = receiver.getDeclarationDescriptor();
if (scriptContext.getScriptDescriptor() == receiverDeclarationDescriptor) {
//TODO lazy
return result;
}
Type currentScriptType = typeMapper.mapType(scriptContext.getScriptDescriptor());
Type classType = typeMapper.mapType(receiver);
String fieldName = scriptContext.getScriptFieldName(receiver);
return StackValue.field(classType, currentScriptType, fieldName, false, result, receiver);
else {
Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor());
Type classType = asmTypeForScriptDescriptor(bindingContext, receiverDeclarationDescriptor);
String fieldName = scriptContext.getScriptFieldName(receiverDeclarationDescriptor);
return StackValue.field(classType, currentScriptType, fieldName, false, result, receiverDeclarationDescriptor);
}
}
result = cur.getOuterExpression(result, false);
@@ -2555,6 +2633,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
throw new UnsupportedOperationException();
}
@NotNull
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) {
return generateThisOrOuter(calleeContainingClass, isSuper, false);
@@ -2746,7 +2825,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull KtElement element,
@NotNull VariableDescriptor variableDescriptor,
@NotNull VariableDescriptor target,
@Nullable ReceiverValue dispatchReceiver
@NotNull ReceiverValue dispatchReceiver
) {
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
@@ -3264,7 +3343,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();
@@ -3281,7 +3360,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);
@@ -3317,14 +3396,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type varType = asmType(variableDescriptor.getType());
StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType);
StackValue storeTo;
if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) {
KtScript scriptPsi = KtPsiUtil.getScript(variableDeclaration);
assert scriptPsi != null;
Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi);
storeTo = StackValue.field(varType, scriptClassType, variableDeclaration.getName(), false, StackValue.LOCAL_0, variableDescriptor);
}
else if (sharedVarType == null) {
storeTo = StackValue.local(index, varType);
}
else {
storeTo = StackValue.shared(index, varType);
}
storeTo.putReceiver(v, false);
initializer.put(initializer.type, v);
markLineNumber(variableDeclaration, false);
storeTo.storeSelector(initializer.type, v);
storeTo.store(initializer, v);
}
@NotNull
@@ -3361,7 +3447,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (dispatchReceiver != null) {
Type receiverType = typeMapper.mapType(dispatchReceiver.getType());
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
boolean callSuper = containingDeclaration.isInner() && receiver instanceof ImplicitClassReceiver;
boolean callSuper = containingDeclaration.isInner() && receiver instanceof ClassReceiver;
generateReceiverValue(receiver, callSuper).put(receiverType, v);
}
@@ -3485,15 +3571,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@Override
public StackValue visitThrowExpression(@NotNull final KtThrowExpression expression, StackValue receiver) {
return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter adapter) {
gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE);
v.athrow();
return Unit.INSTANCE;
}
});
public StackValue visitThrowExpression(@NotNull KtThrowExpression expression, StackValue receiver) {
gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE);
v.athrow();
return StackValue.none();
}
@Override
@@ -3677,8 +3758,13 @@ The "returned" value of try expression with no finally is either the last expres
}
if (opToken != KtTokens.AS_SAFE) {
if (!TypeUtils.isNullableType(rightType) && !TypeUtils.isReifiedTypeParameter(rightType)) {
CodegenUtilKt.generateNullCheckForNonSafeAs(v, rightType);
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 {
@@ -3734,7 +3820,7 @@ The "returned" value of try expression with no finally is either the last expres
return negated ? StackValue.not(value) : value;
}
private StackValue generateInstanceOf(final StackValue expressionToGen, final KotlinType kotlinType, final boolean leaveExpressionOnStack) {
private StackValue generateInstanceOf(final StackValue expressionToGen, final KotlinType jetType, final boolean leaveExpressionOnStack) {
return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
@@ -3742,13 +3828,22 @@ The "returned" value of try expression with no finally is either the last expres
if (leaveExpressionOnStack) {
v.dup();
}
CodegenUtilKt.generateIsCheck(v, kotlinType.isMarkedNullable() && !TypeUtils.isReifiedTypeParameter(kotlinType), new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter adapter) {
generateInstanceOfInstruction(kotlinType);
return Unit.INSTANCE;
}
});
if (jetType.isMarkedNullable()) {
Label nope = new Label();
Label end = new Label();
v.dup();
v.ifnull(nope);
generateInstanceOfInstruction(jetType);
v.goTo(end);
v.mark(nope);
v.pop();
v.iconst(1);
v.mark(end);
}
else {
generateInstanceOfInstruction(jetType);
}
return null;
}
});
@@ -3777,8 +3872,8 @@ The "returned" value of try expression with no finally is either the last expres
parentCodegen.getReifiedTypeParametersUsages().
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
}
boolean putNullableFlag = ReifiedTypeInliner.isNullableMarkerInstruction(markerMethodName) && type.isMarkedNullable();
v.visitLdcInsn(typeParameterDescriptor.getName().asString() + (putNullableFlag ? "?" : ""));
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
v.invokestatic(
IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName,
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false

View File

@@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,7 +58,6 @@ 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.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -221,6 +219,8 @@ public class FunctionCodegen {
}
endVisit(mv, null, origin.getElement());
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
}
private void generateMethodAnnotations(
@@ -354,10 +354,6 @@ public class FunctionCodegen {
mv.visitLabel(methodBegin);
JetTypeMapper typeMapper = parentCodegen.typeMapper;
if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, getSignatureMapper(typeMapper))) {
generateTypeCheckBarrierIfNeeded(
new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterType = */null);
}
Label methodEnd;
@@ -371,11 +367,11 @@ public class FunctionCodegen {
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);
}
@@ -396,7 +392,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,
@@ -404,7 +400,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) {
@@ -553,13 +549,18 @@ 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) {
bridgesToGenerate = ImplKt.generateBridgesForFunctionDescriptor(
descriptor,
getSignatureMapper(typeMapper)
new Function1<FunctionDescriptor, Method>() {
@Override
public Method invoke(FunctionDescriptor descriptor) {
return typeMapper.mapSignature(descriptor).getAsmMethod();
}
}
);
if (!bridgesToGenerate.isEmpty()) {
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
@@ -574,7 +575,12 @@ public class FunctionCodegen {
else {
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
descriptor,
getSignatureMapper(typeMapper)
new Function1<FunctionDescriptor, Method>() {
@Override
public Method invoke(FunctionDescriptor descriptor) {
return typeMapper.mapSignature(descriptor).getAsmMethod();
}
}
);
if (!specials.isEmpty()) {
@@ -587,7 +593,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();
@@ -597,16 +603,6 @@ public class FunctionCodegen {
}
}
@NotNull
private static Function1<FunctionDescriptor, Method> getSignatureMapper(final @NotNull JetTypeMapper typeMapper) {
return new Function1<FunctionDescriptor, Method>() {
@Override
public Method invoke(FunctionDescriptor descriptor) {
return typeMapper.mapSignature(descriptor).getAsmMethod();
}
};
}
private static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
String name = descriptor.getName().asString();
List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
@@ -853,11 +849,9 @@ public class FunctionCodegen {
Type[] originalArgTypes = delegateTo.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv);
MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
MemberCodegen.markLineNumberForSyntheticFunction(owner.getThisDescriptor(), iv);
if (delegateTo.getArgumentTypes().length == 1 && isSpecialBridge) {
generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes()[0]);
}
generateInstanceOfBarrierIfNeeded(iv, descriptor, bridge, delegateTo);
iv.load(0, OBJECT_TYPE);
for (int i = 0, reg = 1; i < argTypes.length; i++) {
@@ -882,45 +876,58 @@ public class FunctionCodegen {
endVisit(mv, "bridge method", origin);
}
private static void generateTypeCheckBarrierIfNeeded(
private static void generateInstanceOfBarrierIfNeeded(
@NotNull InstructionAdapter iv,
@NotNull FunctionDescriptor descriptor,
@NotNull Type returnType,
@Nullable final Type delegateParameterType
@NotNull Method bridge,
@NotNull Method delegateTo
) {
BuiltinMethodsWithSpecialGenericSignature.DefaultValue defaultValue =
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
if (defaultValue == null) return;
if (BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) == null) return;
assert descriptor.getValueParameters().size() == 1 : "Should be descriptor with one value parameter, but found: " + descriptor;
boolean isCheckForAny = delegateParameterType == null || OBJECT_TYPE.equals(delegateParameterType);
final KotlinType kotlinType = descriptor.getValueParameters().get(0).getType();
if (isCheckForAny && TypeUtils.isNullableType(kotlinType)) return;
if (bridge.getArgumentTypes()[0].getSort() != Type.OBJECT) return;
iv.load(1, OBJECT_TYPE);
Label afterBarrier = new Label();
KotlinType jetType = descriptor.getValueParameters().get(0).getType();
if (isCheckForAny) {
assert !TypeUtils.isNullableType(kotlinType) : "Only bridges for not-nullable types are necessary";
iv.ifnonnull(afterBarrier);
// TODO: reuse logic from ExpressionCodegen
if (jetType.isMarkedNullable()) {
Label nope = new Label();
Label end = new Label();
iv.dup();
iv.ifnull(nope);
TypeIntrinsics.instanceOf(
iv,
jetType,
boxType(delegateTo.getArgumentTypes()[0])
);
iv.goTo(end);
iv.mark(nope);
iv.pop();
iv.iconst(1);
iv.mark(end);
}
else {
CodegenUtilKt.generateIsCheck(iv, kotlinType.isMarkedNullable(), new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter adapter) {
TypeIntrinsics.instanceOf(adapter, kotlinType, boxType(delegateParameterType));
return Unit.INSTANCE;
}
});
iv.ifne(afterBarrier);
TypeIntrinsics.instanceOf(
iv,
jetType,
boxType(delegateTo.getArgumentTypes()[0])
);
}
StackValue.constant(defaultValue.getValue(), returnType).put(returnType, iv);
iv.areturn(returnType);
Label afterBarrier = new Label();
iv.ifne(afterBarrier);
String shortName = getFqName(descriptor).shortName().asString();
StackValue returnValue =
("indexOf".equals(shortName) || "lastIndexOf".equals(shortName)) ? StackValue.constant(-1, Type.INT_TYPE) : StackValue.none();
returnValue.put(bridge.getReturnType(), iv);
iv.areturn(bridge.getReturnType());
iv.visitLabel(afterBarrier);
}

View File

@@ -22,7 +22,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.calls.model.DelegatingResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
@@ -36,6 +35,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 +81,13 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
}
}
@Nullable
@NotNull
@Override
public ReceiverValue getExtensionReceiver() {
return extensionReceiver;
}
@Nullable
@NotNull
@Override
public ReceiverValue getDispatchReceiver() {
return dispatchReceiver;
@@ -117,7 +118,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,18 +156,18 @@ 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");
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature));
return ExpressionReceiver.Companion.create(receiverExpression, receiver.getType(), BindingContext.EMPTY);
return new ExpressionReceiver(receiverExpression, receiver.getType());
}
@NotNull

View File

@@ -63,7 +63,7 @@ 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.ReceiverValue;
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
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();
}
}
@@ -304,7 +302,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JvmClassSignature signature() {
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
typeMapper.writeFormalTypeParameters(descriptor.getDeclaredTypeParameters(), sw);
typeMapper.writeFormalTypeParameters(descriptor.getTypeConstructor().getParameters(), sw);
sw.writeSuperclass();
if (superClassType == null) {
@@ -373,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);
@@ -414,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() {
@@ -857,7 +851,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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>
InstructionAdapter v = createOrGetClInitCodegen().v;
markLineNumberForElement(element, v);
markLineNumberForSyntheticFunction(element, v);
v.anew(classAsmType);
v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
@@ -892,7 +886,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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);
@@ -948,14 +942,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
final KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
JvmDeclarationOrigin origin = JvmDeclarationOriginKt
.OtherOrigin(primaryConstructor != null ? primaryConstructor : myClass, constructorDescriptor);
functionCodegen.generateMethod(origin, constructorDescriptor, constructorContext,
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo, primaryConstructor);
generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo);
}
}
);
@@ -964,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) {
@@ -995,13 +993,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generatePrimaryConstructorImpl(
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull ExpressionCodegen codegen,
@NotNull DelegationFieldsInfo fieldsInfo,
@Nullable KtPrimaryConstructor primaryConstructor
@NotNull DelegationFieldsInfo fieldsInfo
) {
InstructionAdapter iv = codegen.v;
markLineNumberForConstructor(constructorDescriptor, primaryConstructor, codegen);
generateClosureInitialization(iv);
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
@@ -1014,9 +1009,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
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);
}
}
@@ -1058,11 +1053,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
) {
InstructionAdapter iv = codegen.v;
KtSecondaryConstructor constructor =
(KtSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
markLineNumberForConstructor(constructorDescriptor, constructor, codegen);
ResolvedCall<ConstructorDescriptor> constructorDelegationCall =
getDelegationConstructorCall(bindingContext, constructorDescriptor);
ConstructorDescriptor delegateConstructor = constructorDelegationCall == null ? null :
@@ -1075,6 +1065,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateInitializers(codegen);
}
KtSecondaryConstructor constructor =
(KtSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
assert constructor != null;
if (constructor.hasBody()) {
codegen.gen(constructor.getBodyExpression(), Type.VOID_TYPE);
@@ -1083,29 +1075,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.visitInsn(RETURN);
}
private static void markLineNumberForConstructor(
@NotNull ConstructorDescriptor descriptor,
@Nullable KtConstructor constructor,
@NotNull ExpressionCodegen codegen
) {
if (constructor == null) {
markLineNumberForDescriptor(descriptor.getContainingDeclaration(), codegen.v);
}
else if (constructor.hasBody() && !(constructor instanceof KtSecondaryConstructor && !((KtSecondaryConstructor) constructor).hasImplicitDelegationCall())) {
KtBlockExpression bodyExpression = constructor.getBodyExpression();
List<KtExpression> statements = bodyExpression != null ? bodyExpression.getStatements() : Collections.<KtExpression>emptyList();
if (!statements.isEmpty()) {
codegen.markStartLineNumber(statements.iterator().next());
}
else {
codegen.markStartLineNumber(bodyExpression != null ? bodyExpression : constructor);
}
}
else {
codegen.markStartLineNumber(constructor);
}
}
private void generateInitializers(@NotNull final ExpressionCodegen codegen) {
generateInitializers(new Function0<ExpressionCodegen>() {
@Override
@@ -1155,41 +1124,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++;
}
@@ -1198,14 +1167,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();
@@ -1237,7 +1206,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ResolvedCall<? extends CallableDescriptor> call = CallUtilKt.getResolvedCall(expr, bindingContext);
if (call != null) {
lookupReceiver(call.getDispatchReceiver());
lookupReceiver((ReceiverValue) call.getExtensionReceiver());
lookupReceiver(call.getExtensionReceiver());
}
}
else if (descriptor instanceof VariableDescriptor) {
@@ -1250,8 +1219,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
private void lookupReceiver(@Nullable ReceiverValue value) {
if (value instanceof ImplicitReceiver) {
private void lookupReceiver(@NotNull ReceiverValue value) {
if (value instanceof ThisReceiver) {
if (value instanceof ExtensionReceiver) {
ReceiverParameterDescriptor parameter =
((ExtensionReceiver) value).getDeclarationDescriptor().getExtensionReceiverParameter();
@@ -1259,7 +1228,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
lookupInContext(parameter);
}
else {
lookupInContext(((ImplicitReceiver) value).getDeclarationDescriptor());
lookupInContext(((ThisReceiver) value).getDeclarationDescriptor());
}
}
}
@@ -1295,8 +1264,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
initializer.accept(visitor);
}
}
else if (declaration instanceof KtAnonymousInitializer) {
KtAnonymousInitializer initializer = (KtAnonymousInitializer) declaration;
else if (declaration instanceof KtClassInitializer) {
KtClassInitializer initializer = (KtClassInitializer) declaration;
initializer.accept(visitor);
}
else if (declaration instanceof KtSecondaryConstructor) {
@@ -1305,9 +1274,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);
}
@@ -1333,7 +1302,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)) {
@@ -1561,7 +1530,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> args) {
protected void reorderArgumentsIfNeeded(@NotNull List<? extends ArgumentAndDeclIndex> args) {
}
}
@@ -1573,8 +1542,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);
}
@@ -1622,7 +1590,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);
@@ -1640,11 +1608,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);
}

View File

@@ -51,7 +51,7 @@ public class InterfaceImplBodyCodegen(
override fun generateDeclaration() {
v.defineClass(
myClass, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
myClass, V1_6, ACC_PUBLIC or ACC_FINAL,
typeMapper.mapDefaultImpls(descriptor).internalName,
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
)
@@ -63,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
@@ -103,8 +103,6 @@ public class InterfaceImplBodyCodegen(
}
}
}
generateSyntheticAccessors()
}
private fun generateDelegationToSuperTraitImpl(descriptor: FunctionDescriptor, implementation: FunctionDescriptor) {

View File

@@ -134,13 +134,12 @@ public class JvmCodegenUtil {
@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;
}
@@ -165,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);
}

View File

@@ -24,20 +24,40 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.psi.KtScript;
import org.jetbrains.kotlin.resolve.ScriptNameUtil;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript;
public class KotlinCodegenFacade {
public static void prepareForCompilation(@NotNull GenerationState state) {
for (KtFile file : state.getFiles()) {
if (file.isScript()) {
KtScript script = file.getScript();
assert script != null;
FqName name = ScriptNameUtil.classNameForScript(script);
Type type = AsmUtil.asmTypeByFqNameWithoutInnerClasses(name);
registerClassNameForScript(state.getBindingTrace(), script, type, state.getFileClassesProvider());
}
}
state.beforeCompile();
}
public static void compileCorrectFiles(
@NotNull GenerationState state,
@NotNull CompilationErrorHandler errorHandler
) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
state.beforeCompile();
prepareForCompilation(state);
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();

View File

@@ -46,6 +46,7 @@ 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;
@@ -64,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;
@@ -142,18 +144,18 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
return null;
}
public static void markLineNumberForDescriptor(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
public static void markLineNumberForSyntheticFunction(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
if (declarationDescriptor == null) {
return;
}
PsiElement classElement = DescriptorToSourceUtils.getSourceFromDescriptor(declarationDescriptor);
if (classElement != null) {
markLineNumberForElement(classElement, v);
markLineNumberForSyntheticFunction(classElement, v);
}
}
public static void markLineNumberForElement(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
public static void markLineNumberForSyntheticFunction(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
Integer lineNumber = CodegenUtil.getLineNumberForElement(element, false);
if (lineNumber != null) {
Label label = new Label();
@@ -271,16 +273,20 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
String outerClassInternalName = null;
if (containing instanceof ClassDescriptor) {
outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
}
} /* disabled cause of KT-7775
else if (containing instanceof ScriptDescriptor) {
outerClassInternalName = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containing).getInternalName();
}*/
String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
}
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();
@@ -314,7 +320,10 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile());
}
}
/*disabled cause of KT-7775
else if (outermost instanceof ScriptContext) {
return asmTypeForScriptDescriptor(bindingContext, ((ScriptContext) outermost).getScriptDescriptor());
}*/
return null;
}
@@ -364,8 +373,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
initializeProperty(codegen.invoke(), (KtProperty) declaration);
}
}
else if (declaration instanceof KtAnonymousInitializer) {
KtExpression body = ((KtAnonymousInitializer) declaration).getBody();
else if (declaration instanceof KtClassInitializer) {
KtExpression body = ((KtClassInitializer) declaration).getBody();
if (body != null) {
codegen.invoke().gen(body, Type.VOID_TYPE);
}
@@ -483,13 +492,13 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
if (delegatedProperties.isEmpty()) return;
v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
"[" + K_PROPERTY_TYPE, null, null);
"[" + PROPERTY_METADATA_TYPE, null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
InstructionAdapter iv = createOrGetClInitCodegen().v;
iv.iconst(delegatedProperties.size());
iv.newarray(K_PROPERTY_TYPE);
iv.newarray(PROPERTY_METADATA_TYPE);
for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
PropertyDescriptor property =
@@ -524,16 +533,16 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
//noinspection ConstantConditions
value = createOrGetClInitCodegen().generatePropertyReference(
delegatedProperties.get(i).getDelegate(), property, property,
dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : null
dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER
);
}
value.put(K_PROPERTY_TYPE, iv);
value.put(PROPERTY_METADATA_TYPE, iv);
iv.astore(K_PROPERTY_TYPE);
iv.astore(PROPERTY_METADATA_TYPE);
}
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE);
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
}
public String getClassName() {
@@ -600,10 +609,9 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) {
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
markLineNumberForElement(element, codegen.v);
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), codegen.v);
markLineNumberForSyntheticFunction(element, codegen.v);
generateMethodCallTo(original, accessor, codegen.v);
codegen.v.areturn(signature.getReturnType());
}
}
@@ -631,7 +639,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
InstructionAdapter iv = codegen.v;
markLineNumberForElement(element, iv);
markLineNumberForSyntheticFunction(element, iv);
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
for (int i = 0, reg = 0; i < argTypes.length; i++) {
@@ -642,7 +650,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
}
if (callableDescriptor instanceof PropertyGetterDescriptor) {
property.put(signature.getReturnType(), iv);
property.put(property.type, iv);
}
else {
property.store(StackValue.onStack(property.type), iv, true);
@@ -672,7 +680,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
}
}
private StackValue generateMethodCallTo(
private void generateMethodCallTo(
@NotNull FunctionDescriptor functionDescriptor,
@Nullable FunctionDescriptor accessorDescriptor,
@NotNull InstructionAdapter iv
@@ -683,7 +691,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) {
@@ -708,7 +716,5 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
}
callableMethod.genInvokeInstruction(iv);
return StackValue.onStack(callableMethod.getReturnType());
}
}

View File

@@ -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>,
@@ -297,8 +279,7 @@ public class MultifileClassCodegen(
}
companion object {
private val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER
private val OPEN_FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_SUPER
private val FACADE_CLASS_ATTRIBUTES = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL
private fun getOnlyPackageFragment(packageFqName: FqName, files: Collection<KtFile>, bindingContext: BindingContext): PackageFragmentDescriptor? {
val fragments = SmartList<PackageFragmentDescriptor>()

View File

@@ -46,7 +46,7 @@ public class MultifileClassPartCodegen(
override fun generateDeclaration() {
v.defineClass(element, Opcodes.V1_6,
Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC or Opcodes.ACC_SUPER,
Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC,
filePartType.internalName,
null,
"java/lang/Object",

View File

@@ -143,18 +143,12 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
this.typeParameters = new ArrayList<TypeParameterDescriptor>(typeParameters);
}
@NotNull
@Override
public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
return typeParameters;
}
public void createTypeConstructor() {
assert typeConstructor == null : typeConstructor;
this.typeConstructor = TypeConstructorImpl.createForClass(
this,
Annotations.Companion.getEMPTY(),
ModalityKt.isFinalClass(this),
!getModality().isOverridable(),
getName().asString(),
typeParameters,
supertypes

View File

@@ -63,7 +63,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
@Override
protected void generateDeclaration() {
v.defineClass(element, V1_6,
ACC_PUBLIC | ACC_FINAL | ACC_SUPER,
ACC_PUBLIC | ACC_FINAL,
packagePartType.getInternalName(),
null,
"java/lang/Object",

View File

@@ -58,7 +58,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
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.AsmTypes.PROPERTY_METADATA_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -118,7 +118,16 @@ public class PropertyCodegen {
if (CodegenContextUtil.isImplClassOwner(context)) {
assert declaration != null : "Declaration is null for different context: " + context;
genBackingFieldAndAnnotations(declaration, descriptor, false);
boolean hasBackingField = hasBackingField(declaration, descriptor);
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
descriptor.getAnnotations(), AnnotationSplitter.getTargetSet(false, descriptor.isVar(), hasBackingField));
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
generateBackingField(declaration, descriptor, fieldAnnotations);
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
}
if (isAccessorNeeded(declaration, descriptor, getter)) {
@@ -127,21 +136,8 @@ public class PropertyCodegen {
if (isAccessorNeeded(declaration, descriptor, setter)) {
generateSetter(declaration, descriptor, setter);
}
}
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
boolean hasBackingField = hasBackingField(declaration, descriptor);
AnnotationSplitter annotationSplitter =
AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
descriptor.getAnnotations(),
AnnotationSplitter.getTargetSet(isParameter, descriptor.isVar(), hasBackingField));
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
generateBackingField(declaration, descriptor, fieldAnnotations);
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
context.recordSyntheticAccessorIfNeeded(descriptor, bindingContext);
}
/**
@@ -178,20 +174,21 @@ public class PropertyCodegen {
return true;
}
private static boolean areAccessorsNeededForPrimaryConstructorProperty(
@NotNull PropertyDescriptor descriptor
) {
if (hasJvmFieldAnnotation(descriptor)) return false;
public void generatePrimaryConstructorProperty(KtParameter p, PropertyDescriptor descriptor) {
AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
descriptor.getAnnotations(), AnnotationSplitter.getTargetSet(true, descriptor.isVar(), hasBackingField(p, descriptor)));
return !Visibilities.isPrivate(descriptor.getVisibility());
}
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
public void generatePrimaryConstructorProperty(@NotNull KtParameter p, @NotNull PropertyDescriptor descriptor) {
genBackingFieldAndAnnotations(p, descriptor, true);
generateBackingField(p, descriptor, fieldAnnotations);
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
if (areAccessorsNeededForPrimaryConstructorProperty(descriptor)) {
if (!Visibilities.isPrivate(descriptor.getVisibility())) {
generateGetter(p, descriptor, null);
generateSetter(p, descriptor, null);
if (descriptor.isVar()) {
generateSetter(p, descriptor, null);
}
}
}
@@ -358,7 +355,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);
@@ -524,15 +521,13 @@ public class PropertyCodegen {
codegen.tempVariables.put(
resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(),
new StackValue(K_PROPERTY_TYPE) {
new StackValue(PROPERTY_METADATA_TYPE) {
@Override
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
Field array = StackValue.field(
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
);
StackValue.arrayElement(
K_PROPERTY_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)
).put(type, v);
Field array = StackValue
.field(Type.getType("[" + PROPERTY_METADATA_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true,
StackValue.none());
StackValue.arrayElement(PROPERTY_METADATA_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)).put(type, v);
}
}
);

View File

@@ -33,6 +33,7 @@ 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.resolve.scopes.receivers.ScriptReceiver
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
@@ -47,11 +48,19 @@ public class PropertyReferenceCodegen(
classBuilder: ClassBuilder,
private val classDescriptor: ClassDescriptor,
private val target: VariableDescriptor,
dispatchReceiver: ReceiverValue?
dispatchReceiver: ReceiverValue
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
private val asmType = typeMapper.mapClass(classDescriptor)
private val dispatchReceiverType = dispatchReceiver?.type
private val dispatchReceiverType =
when {
dispatchReceiver is ScriptReceiver -> {
// TODO: fix receiver for scripts, see ScriptReceiver#getType
dispatchReceiver.declarationDescriptor.classDescriptor.defaultType
}
dispatchReceiver.exists() -> dispatchReceiver.type
else -> null
}
private val extensionReceiverType = target.extensionReceiverParameter?.type
@@ -127,7 +136,7 @@ public class PropertyReferenceCodegen(
StackValue.singleton(containingObject, typeMapper).put(typeMapper.mapClass(containingObject), this)
}
for ((index, type) in listOfNotNull(dispatchReceiverType, extensionReceiverType).withIndex()) {
for ((index, type) in listOf(dispatchReceiverType, extensionReceiverType).filterNotNull().withIndex()) {
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
}

View File

@@ -38,21 +38,10 @@ public class RangeCodegenUtil {
private static final ImmutableMap<FqName, PrimitiveType> RANGE_TO_ELEMENT_TYPE;
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_TO_ELEMENT_TYPE;
private static PrimitiveType[] supportedRangeTypes() {
return new PrimitiveType[] {
PrimitiveType.CHAR,
PrimitiveType.INT,
PrimitiveType.LONG,
// deprecated:
PrimitiveType.BYTE,
PrimitiveType.SHORT,
};
}
static {
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = ImmutableMap.builder();
for (PrimitiveType primitiveType : supportedRangeTypes()) {
for (PrimitiveType primitiveType : PrimitiveType.values()) {
FqName rangeClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Range"));
FqName progressionClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
rangeBuilder.put(rangeClassFqName, primitiveType);

View File

@@ -70,7 +70,6 @@ public class SamWrapperCodegen {
samType.getJavaClassDescriptor().getContainingDeclaration(),
fqName.shortName(),
Modality.FINAL,
ClassKind.CLASS,
Collections.singleton(samType.getType()),
SourceElement.NO_SOURCE
);
@@ -86,7 +85,7 @@ public class SamWrapperCodegen {
ClassBuilder cv = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(erasedInterfaceFunction), asmType, file);
cv.defineClass(file,
V1_6,
ACC_FINAL | ACC_SUPER,
ACC_FINAL,
asmType.getInternalName(),
null,
OBJECT_TYPE.getInternalName(),

View File

@@ -23,11 +23,12 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.ScriptContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -37,6 +38,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForScriptDescriptor;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -52,16 +55,18 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration);
assert scriptDescriptor != null;
Type classType = state.getTypeMapper().mapType(scriptDescriptor);
ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
assert classDescriptorForScript != null;
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, scriptDescriptor),
Type classType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, classDescriptorForScript),
classType, declaration.getContainingFile());
List<ScriptDescriptor> earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter();
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
ScriptContext scriptContext = parentContext.intoScript(
scriptDescriptor,
earlierScripts == null ? Collections.<ScriptDescriptor>emptyList() : earlierScripts,
scriptDescriptor,
state.getTypeMapper()
classDescriptorForScript
);
return new ScriptCodegen(declaration, state, scriptContext, builder);
}
@@ -88,7 +93,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
v.defineClass(scriptDeclaration,
V1_6,
ACC_PUBLIC | ACC_SUPER,
ACC_PUBLIC,
classType.getInternalName(),
null,
"java/lang/Object",
@@ -99,8 +104,8 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
protected void generateBody() {
genMembers();
genFieldsForParameters(scriptDescriptor, v);
genConstructor(scriptDescriptor, v,
context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
genConstructor(scriptDescriptor, context.getContextDescriptor(), v,
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()));
}
@Override
@@ -110,25 +115,22 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
private void genConstructor(
@NotNull ScriptDescriptor scriptDescriptor,
@NotNull ClassDescriptor classDescriptorForScript,
@NotNull ClassBuilder classBuilder,
@NotNull MethodContext methodContext
) {
//noinspection ConstantConditions
Type blockType = typeMapper.mapType(scriptDescriptor.getScriptCodeDescriptor().getReturnType());
PropertyDescriptor scriptResultProperty = scriptDescriptor.getScriptResultProperty();
classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(scriptResultProperty),
ACC_PUBLIC | ACC_FINAL, scriptResultProperty.getName().asString(),
blockType.getDescriptor(), null, null);
JvmMethodSignature jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, context.getEarlierScripts());
if (state.getReplSpecific().getShouldGenerateScriptResultValue()) {
FieldInfo resultFieldInfo = context.getResultFieldInfo();
classBuilder.newField(
JvmDeclarationOrigin.NO_ORIGIN,
ACC_PUBLIC | ACC_FINAL,
resultFieldInfo.getFieldName(),
resultFieldInfo.getFieldType().getDescriptor(),
null,
null
);
}
MethodVisitor mv = classBuilder.newMethod(
JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getUnsubstitutedPrimaryConstructor()),
JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getClassDescriptor().getUnsubstitutedPrimaryConstructor()),
ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
null, null);
@@ -137,7 +139,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
InstructionAdapter iv = new InstructionAdapter(mv);
Type classType = typeMapper.mapType(scriptDescriptor);
Type classType = typeMapper.mapType(classDescriptorForScript);
iv.load(0, classType);
iv.invokespecial("java/lang/Object", "<init>", "()V", false);
@@ -154,23 +156,22 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
int add = 0;
List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
for (int i = 0; i < valueParameters.size(); i++) {
ValueParameterDescriptor parameter = valueParameters.get(i);
for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) {
ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i);
frameMap.enter(parameter, argTypes[i + add]);
}
int offset = 1;
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
Type earlierClassType = typeMapper.mapClass(earlierScript);
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
iv.load(0, classType);
iv.load(offset, earlierClassType);
offset += earlierClassType.getSize();
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
}
for (ValueParameterDescriptor parameter : valueParameters) {
for (ValueParameterDescriptor parameter : scriptDescriptor.getScriptCodeDescriptor().getValueParameters()) {
Type parameterType = typeMapper.mapType(parameter.getType());
iv.load(0, classType);
iv.load(offset, parameterType);
@@ -187,6 +188,16 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
}
});
StackValue stackValue = codegen.gen(scriptDeclaration.getBlockExpression());
if (stackValue.type != Type.VOID_TYPE) {
StackValue.Field resultValue = StackValue
.field(blockType, classType, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, false, StackValue.LOCAL_0);
resultValue.store(stackValue, iv);
}
else {
stackValue.put(blockType, iv);
}
iv.areturn(Type.VOID_TYPE);
}
@@ -196,12 +207,12 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) {
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
Type earlierClassName = typeMapper.mapType(earlierScript);
int access = ACC_PUBLIC | ACC_FINAL;
Type earlierClassName = asmTypeForScriptDescriptor(bindingContext, earlierScript);
int access = ACC_PRIVATE | ACC_FINAL;
classBuilder.newField(NO_ORIGIN, access, context.getScriptFieldName(earlierScript), earlierClassName.getDescriptor(), null, null);
}
for (ValueParameterDescriptor parameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
for (ValueParameterDescriptor parameter : script.getScriptCodeDescriptor().getValueParameters()) {
Type parameterType = typeMapper.mapType(parameter);
int access = ACC_PUBLIC | ACC_FINAL;
classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(parameter), access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null);

View File

@@ -235,8 +235,8 @@ public abstract class StackValue {
}
@NotNull
public static Field field(@NotNull FieldInfo info, @NotNull StackValue receiver) {
return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), info.isStatic(), receiver);
private static Field field(@NotNull FieldInfo info) {
return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true, none());
}
@NotNull
@@ -501,20 +501,20 @@ public abstract class StackValue {
callDispatchReceiver = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverForBackend();
}
ReceiverValue callExtensionReceiver = (ReceiverValue) resolvedCall.getExtensionReceiver();
if (callDispatchReceiver != null || callExtensionReceiver != null
ReceiverValue callExtensionReceiver = resolvedCall.getExtensionReceiver();
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
@@ -532,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) {
@@ -548,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();
@@ -593,15 +593,15 @@ public abstract class StackValue {
@NotNull
public static Field singleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) {
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none());
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper));
}
public static Field singletonViaInstance(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false), none());
return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false));
}
public static Field oldSingleton(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) {
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true), none());
return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true));
}
public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) {
@@ -832,9 +832,9 @@ public abstract class StackValue {
v.store(firstParamIndex, type);
}
ReceiverValue receiverParameter = (ReceiverValue) resolvedGetCall.getExtensionReceiver();
ReceiverValue receiverParameter = 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);
@@ -842,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);
}
@@ -863,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 {
@@ -970,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;
}
}
@@ -1084,7 +1084,9 @@ public abstract class StackValue {
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD,
backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
genNotNullAssertionForLateInitIfNeeded(v);
if (!genNotNullAssertionForField(v, state, descriptor)) {
genNotNullAssertionForLateInitIfNeeded(v);
}
coerceTo(type, v);
}
else {

View File

@@ -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
@@ -159,26 +158,30 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
element.acceptChildren(this);
}
@Override
public void visitScript(@NotNull KtScript script) {
classStack.push(bindingContext.get(SCRIPT, script));
nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(script.getFqName()));
script.acceptChildren(this);
nameStack.pop();
classStack.pop();
}
@Override
public void visitKtFile(@NotNull KtFile file) {
nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName()));
if (file.isScript()) {
// TODO: replace with visitScript override
//noinspection ConstantConditions
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, bindingContext.get(SCRIPT, file.getScript()));
classStack.push(classDescriptor);
//noinspection ConstantConditions
nameStack.push(asmTypeForScriptPsi(bindingContext, file.getScript()).getInternalName());
}
else {
nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName()));
}
file.acceptChildren(this);
nameStack.pop();
if (file.isScript()) {
classStack.pop();
}
}
@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 +251,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 +267,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 +281,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
classStack.push(classDescriptor);
nameStack.push(name);
super.visitLambdaExpression(lambdaExpression);
super.visitFunctionLiteralExpression(expression);
nameStack.pop();
classStack.pop();
}
@@ -383,7 +386,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
String peek = peekFromStack(nameStack);
String name = safeIdentifier(descriptor.getName()).asString();
if (containingDeclaration instanceof ClassDescriptor) {
if (containingDeclaration instanceof ClassDescriptor || containingDeclaration instanceof ScriptDescriptor) {
return peek + '$' + name;
}
else if (containingDeclaration instanceof PackageFragmentDescriptor) {
@@ -432,8 +435,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);
}

View File

@@ -24,13 +24,17 @@ import org.jetbrains.kotlin.codegen.SamType;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice;
import org.jetbrains.kotlin.util.slicedMap.Slices;
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
@@ -39,12 +43,15 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.util.*;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
public class CodegenBinding {
public static final WritableSlice<ClassDescriptor, MutableClosure> CLOSURE = Slices.createSimpleSlice();
public static final WritableSlice<CallableDescriptor, ClassDescriptor> CLASS_FOR_CALLABLE = Slices.createSimpleSlice();
public static final WritableSlice<ScriptDescriptor, ClassDescriptor> CLASS_FOR_SCRIPT = Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Type> ASM_TYPE = Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Boolean> ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice();
@@ -82,6 +89,22 @@ public class CodegenBinding {
return Boolean.TRUE.equals(bindingContext.get(ENUM_ENTRY_CLASS_NEED_SUBCLASS, classDescriptor));
}
@NotNull
public static Type asmTypeForScriptDescriptor(BindingContext bindingContext, @NotNull ScriptDescriptor scriptDescriptor) {
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
//noinspection ConstantConditions
return getAsmType(bindingContext, classDescriptor);
}
@NotNull
public static Type asmTypeForScriptPsi(BindingContext bindingContext, @NotNull KtScript script) {
ScriptDescriptor scriptDescriptor = bindingContext.get(SCRIPT, script);
if (scriptDescriptor == null) {
throw new IllegalStateException("Script descriptor not found by PSI " + script);
}
return asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
}
@NotNull
public static ClassDescriptor anonymousClassForCallable(
@NotNull BindingContext bindingContext,
@@ -140,7 +163,7 @@ public class CodegenBinding {
@NotNull Type asmType,
@NotNull JvmFileClassesProvider fileClassesManager
) {
KtElement element = (KtElement) DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor);
KtElement element = (KtElement) descriptorToDeclaration(classDescriptor);
assert element != null : "No source element for " + classDescriptor;
MutableClosure closure = new MutableClosure(classDescriptor, enclosing);
@@ -173,6 +196,29 @@ public class CodegenBinding {
innerClasses.add(inner);
}
public static void registerClassNameForScript(
@NotNull BindingTrace trace,
@NotNull KtScript script,
@NotNull Type asmType,
@NotNull JvmFileClassesProvider fileClassesManager
) {
ScriptDescriptor descriptor = trace.getBindingContext().get(SCRIPT, script);
if (descriptor == null) {
throw new IllegalStateException("Script descriptor is not found for PSI: " + PsiUtilsKt.getElementTextWithContext(script));
}
String simpleName = asmType.getInternalName().substring(asmType.getInternalName().lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor =
new ClassDescriptorImpl(descriptor, Name.special("<script-" + simpleName + ">"), Modality.FINAL,
Collections.singleton(DescriptorUtilsKt.getBuiltIns(descriptor).getAnyType()),
KotlinSourceElementKt.toSourceElement(script));
classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.<ConstructorDescriptor>emptySet(), null);
recordClosure(trace, classDescriptor, null, asmType, fileClassesManager);
trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor);
}
@NotNull
private static Collection<KtFile> allFilesInPackages(BindingContext bindingContext, Collection<KtFile> files) {
// todo: we use Set and add given files but ignoring other scripts because something non-clear kept in binding

View File

@@ -20,19 +20,20 @@ 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.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
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.load.java.getOverriddenBuiltinWithDifferentJvmDescriptor
import org.jetbrains.kotlin.load.java.hasRealKotlinSuperClassWithOverrideOf
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 +52,7 @@ object BuiltinSpecialBridgesUtil {
val functionHandle = DescriptorBasedFunctionHandle(function)
val fake = !functionHandle.isDeclaration
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
val overriddenBuiltin = function.getOverriddenBuiltinWithDifferentJvmDescriptor()!!
val reachableDeclarations = findAllReachableDeclarations(function)
@@ -62,6 +63,7 @@ object BuiltinSpecialBridgesUtil {
val needGenerateSpecialBridge = needGenerateSpecialBridge(
function, reachableDeclarations, overriddenBuiltin, signatureByDescriptor, overriddenBuiltinSignature)
&& methodItself != overriddenBuiltinSignature
val specialBridge = if (needGenerateSpecialBridge)
BridgeForBuiltinSpecial(overriddenBuiltinSignature, methodItself, isSpecial = true)
@@ -92,16 +94,6 @@ object BuiltinSpecialBridgesUtil {
return bridges
}
@JvmStatic
public fun <Signature> FunctionDescriptor.shouldHaveTypeSafeBarrier(
signatureByDescriptor: (FunctionDescriptor) -> Signature
): Boolean {
if (BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(this) == null) return false
val builtin = getOverriddenBuiltinReflectingJvmDescriptor()!!
return signatureByDescriptor(this) == signatureByDescriptor(builtin)
}
}
@@ -123,24 +115,13 @@ private fun <Signature> needGenerateSpecialBridge(
signatureByDescriptor: (FunctionDescriptor) -> Signature,
overriddenBuiltinSignature: Signature
): Boolean {
if (signatureByDescriptor(functionDescriptor) == overriddenBuiltinSignature) return false
if (specialCallableDescriptor.modality == Modality.FINAL) return false
// Is there Kotlin superclass that already has generated special bridge
if (functionDescriptor.firstOverridden { overridden ->
val originalOverridden = overridden.original
if (overridden === functionDescriptor
|| originalOverridden !is FunctionDescriptor
|| originalOverridden.containingDeclaration is JavaClassDescriptor
|| DescriptorUtils.isInterface(originalOverridden.containingDeclaration)) return@firstOverridden false
val overriddenSpecial = originalOverridden.getOverriddenBuiltinReflectingJvmDescriptor()?.original ?: return@firstOverridden false
signatureByDescriptor(originalOverridden) != signatureByDescriptor(overriddenSpecial)
} != null) return false
return reachableDeclarations.none { it.modality == Modality.FINAL
&& signatureByDescriptor(it) == overriddenBuiltinSignature }
val classDescriptor = functionDescriptor.containingDeclaration as ClassDescriptor
return !classDescriptor.hasRealKotlinSuperClassWithOverrideOf(specialCallableDescriptor)
&& specialCallableDescriptor.modality != Modality.FINAL
&& reachableDeclarations.none {
it.modality == Modality.FINAL
&& signatureByDescriptor(it) == overriddenBuiltinSignature
}
}
public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
@@ -153,7 +134,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
}

View File

@@ -1,97 +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
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
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.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.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
fun generateIsCheck(
v: InstructionAdapter,
isNullable: Boolean,
generateInstanceOfInstruction: (InstructionAdapter) -> Unit
) {
if (isNullable) {
val nope = Label()
val end = Label()
with(v) {
dup()
ifnull(nope)
generateInstanceOfInstruction(this)
goTo(end)
mark(nope)
pop()
iconst(1)
mark(end)
}
}
else {
generateInstanceOfInstruction(v)
}
}
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 (!AsmUtil.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())
}
}
}

View File

@@ -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
@@ -315,10 +315,9 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
public ScriptContext intoScript(
@NotNull ScriptDescriptor script,
@NotNull List<ScriptDescriptor> earlierScripts,
@NotNull ClassDescriptor classDescriptor,
@NotNull JetTypeMapper typeMapper
@NotNull ClassDescriptor classDescriptor
) {
return new ScriptContext(typeMapper, script, earlierScripts, classDescriptor, this);
return new ScriptContext(script, earlierScripts, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
}
@NotNull
@@ -365,24 +364,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,35 +501,38 @@ 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();
if (!isInliningContext && (
!properContext.hasThisDescriptor() ||
enclosing == properContext.getThisDescriptor() ||
enclosing == properContext.getClassOrPackageParentContext().getContextDescriptor())) {
if (!isInlineMethodContext() && (
!hasThisDescriptor() ||
enclosing == getThisDescriptor() ||
enclosing == getClassOrPackageParentContext().getContextDescriptor())) {
return descriptor;
}
return (D) properContext.accessibleDescriptorIfNeeded(descriptor, superCallTarget, isInliningContext);
return accessibleDescriptorIfNeeded(descriptor, superCallTarget);
}
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);
}
}
@SuppressWarnings("unchecked")
@NotNull
private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded(
@NotNull D descriptor,
@Nullable ClassDescriptor superCallTarget,
boolean withinInliningContext
@Nullable ClassDescriptor superCallTarget
) {
CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor);
@@ -564,14 +553,10 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
superCallTarget = (ClassDescriptor) enclosed;
}
if (descriptorContext == null && withinInliningContext && superCallTarget != null) {
//generate super calls within inline function through synthetic accessors
descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this);
}
if (descriptorContext == null) {
return descriptor;
}
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
int propertyAccessFlag = getVisibilityAccessFlag(descriptor);
@@ -579,14 +564,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
int getterAccessFlag = getter == null ? propertyAccessFlag
: propertyAccessFlag | getVisibilityAccessFlag(getter);
boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext,
withinInliningContext, superCallTarget != null);
boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext);
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
int setterAccessFlag = setter == null ? propertyAccessFlag
: propertyAccessFlag | getVisibilityAccessFlag(setter);
boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext,
withinInliningContext, superCallTarget != null);
boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext);
if (!getterAccessorRequired && !setterAccessorRequired) {
return descriptor;
@@ -595,7 +578,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
else {
int flag = getVisibilityAccessFlag(unwrappedDescriptor);
if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext, withinInliningContext, superCallTarget != null)) {
if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext)) {
return descriptor;
}
return (D) descriptorContext.getAccessor(descriptor, superCallTarget);
@@ -605,14 +588,10 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
private static boolean isAccessorRequired(
int accessFlag,
@NotNull CallableMemberDescriptor unwrappedDescriptor,
@NotNull CodegenContext descriptorContext,
boolean withinInline,
boolean isSuperCall
@NotNull CodegenContext descriptorContext
) {
return isSuperCall && withinInline ||
(accessFlag & ACC_PRIVATE) != 0 ||
((accessFlag & ACC_PROTECTED) != 0 &&
(withinInline || !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor())));
return (accessFlag & ACC_PRIVATE) != 0 ||
((accessFlag & ACC_PROTECTED) != 0 && !isInSamePackage(unwrappedDescriptor, descriptorContext.getContextDescriptor()));
}
private static boolean isInSamePackage(DeclarationDescriptor descriptor1, DeclarationDescriptor descriptor2) {
@@ -640,7 +619,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 +627,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();
}
}

View File

@@ -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

View File

@@ -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.toMap ({ Pair(it.calleeDescriptor, it.superCallTarget) }, {it}) - alreadyExistKeys
return accessors + filtered.values
}
}

View File

@@ -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
}
}

View File

@@ -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;

View File

@@ -16,48 +16,30 @@
package org.jetbrains.kotlin.codegen.context;
import kotlin.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.FieldInfo;
import org.jetbrains.kotlin.codegen.OwnerKind;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
import org.jetbrains.kotlin.psi.KtAnonymousInitializer;
import org.jetbrains.kotlin.psi.KtDeclaration;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtScript;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import java.util.List;
public class ScriptContext extends ClassContext {
public class ScriptContext extends FieldOwnerContext<ClassDescriptor> {
private final ScriptDescriptor scriptDescriptor;
private final List<ScriptDescriptor> earlierScripts;
private final KtExpression lastStatement;
public ScriptContext(
@NotNull JetTypeMapper typeMapper,
@NotNull ScriptDescriptor scriptDescriptor,
@NotNull List<ScriptDescriptor> earlierScripts,
@NotNull ClassDescriptor contextDescriptor,
@Nullable CodegenContext parentContext
@NotNull OwnerKind contextKind,
@Nullable CodegenContext parentContext,
@Nullable MutableClosure closure
) {
super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null);
super(contextDescriptor, contextKind, parentContext, closure, contextDescriptor, null);
this.scriptDescriptor = scriptDescriptor;
this.earlierScripts = earlierScripts;
KtScript script = (KtScript) DescriptorToSourceUtils.getSourceFromDescriptor(scriptDescriptor);
assert script != null : "Declaration should be present for script: " + scriptDescriptor;
KtDeclaration lastDeclaration = CollectionsKt.lastOrNull(script.getDeclarations());
if (lastDeclaration instanceof KtAnonymousInitializer) {
this.lastStatement = ((KtAnonymousInitializer) lastDeclaration).getBody();
}
else {
this.lastStatement = null;
}
}
@NotNull
@@ -65,15 +47,6 @@ public class ScriptContext extends ClassContext {
return scriptDescriptor;
}
@NotNull
public FieldInfo getResultFieldInfo() {
assert getState().getReplSpecific().getShouldGenerateScriptResultValue() : "Should not be called unless 'scriptResultFieldName' is set";
GenerationState state = getState();
String scriptResultFieldName = state.getReplSpecific().getScriptResultFieldName();
assert scriptResultFieldName != null;
return FieldInfo.createForHiddenField(state.getTypeMapper().mapClass(scriptDescriptor), AsmTypes.OBJECT_TYPE, scriptResultFieldName);
}
@NotNull
public List<ScriptDescriptor> getEarlierScripts() {
return earlierScripts;
@@ -88,11 +61,6 @@ public class ScriptContext extends ClassContext {
return "script$" + (index + 1);
}
@Nullable
public KtExpression getLastStatement() {
return lastStatement;
}
@Override
public String toString() {
return "Script: " + getContextDescriptor().getName().asString();

View File

@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.*
public interface ExpressionCodegenExtension {
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
"org.jetbrains.kotlin.expressionCodegenExtension", ExpressionCodegenExtension::class.java)
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>("org.jetbrains.kotlin.expressionCodegenExtension", javaClass<ExpressionCodegenExtension>())
public class Context(
public val typeMapper: JetTypeMapper,
@@ -42,10 +42,10 @@ public interface ExpressionCodegenExtension {
public fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
/**
* Used for generating custom byte code for the function call. This function has lazy semantics.
* Returns new stack value.
* Used for generating custom byte code for the function call. This function has non-lazy semantics.
* Returns true if the stack was modified.
*/
public fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
public fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): Boolean = false
public fun generateClassSyntheticParts(
classBuilder: ClassBuilder,

View File

@@ -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,11 +28,13 @@ 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.*;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
public class AnonymousObjectTransformer {
@@ -62,6 +65,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,12 +81,12 @@ 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>();
@@ -96,11 +101,6 @@ public class AnonymousObjectTransformer {
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitInnerClass(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();
@@ -179,7 +179,7 @@ public class AnonymousObjectTransformer {
ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder();
List<CapturedParamInfo> additionalFakeParams =
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder,
anonymousObjectGen, parentRemapper);
anonymousObjectGen);
List<MethodVisitor> deferringMethods = new ArrayList();
for (MethodNode next : methodsToTransform) {
@@ -192,7 +192,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);
@@ -206,10 +206,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);
@@ -240,7 +236,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 =
@@ -288,23 +284,26 @@ public class AnonymousObjectTransformer {
}
}
List<Pair<String, Type>> capturedFieldsToGenerate = new ArrayList<Pair<String, Type>>();
for (CapturedParamInfo capturedParamInfo : allCapturedBuilder.listCaptured()) {
if (capturedParamInfo.getLambda() == null) { //not inlined
capturedFieldsToGenerate.add(new Pair<String, Type>(capturedParamInfo.getNewFieldName(), capturedParamInfo.getType()));
}
}
String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()]));
MethodVisitor constructorVisitor = classBuilder.newMethod(NO_ORIGIN,
AsmUtil.NO_FLAG_PACKAGE_PRIVATE,
"<init>", constructorDescriptor,
null, ArrayUtil.EMPTY_STRING_ARRAY);
//initialize captured fields
List<NewJavaField> newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured());
List<FieldInfo> fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo(newLambdaType, newFieldsWithSkipped);
List<FieldInfo> fields = AsmUtil.transformCapturedParams(capturedFieldsToGenerate, newLambdaType);
int paramIndex = 0;
InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor);
for (int i = 0; i < fieldInfoWithSkipped.size(); i++) {
FieldInfo fieldInfo = fieldInfoWithSkipped.get(i);
if (!newFieldsWithSkipped.get(i).getSkip()) {
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer);
}
for (FieldInfo fieldInfo : fields) {
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer);
paramIndex++;
}
@@ -328,7 +327,8 @@ public class AnonymousObjectTransformer {
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
constructorVisitor.visitEnd();
AsmUtil.genClosureFields(TransformationUtilsKt.toNameTypePair(TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder);
AsmUtil.genClosureFields(capturedFieldsToGenerate, classBuilder);
//TODO for inline method make public class
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
}
@@ -348,7 +348,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
@@ -378,8 +378,7 @@ public class AnonymousObjectTransformer {
@NotNull MethodNode constructor,
@NotNull ParametersBuilder capturedParamBuilder,
@NotNull ParametersBuilder constructorParamBuilder,
@NotNull final AnonymousObjectGeneration anonymousObjectGen,
@NotNull FieldRemapper parentFieldRemapper
@NotNull final AnonymousObjectGeneration anonymousObjectGen
) {
CapturedParamOwner owner = new CapturedParamOwner() {
@@ -389,7 +388,7 @@ public class AnonymousObjectTransformer {
}
};
Set<LambdaInfo> capturedLambdas = new LinkedHashSet<LambdaInfo>(); //captured var of inlined parameter
List<LambdaInfo> capturedLambdas = new ArrayList<LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>();
Map<Integer, LambdaInfo> indexToLambda = anonymousObjectGen.getLambdasToInline();
Set<Integer> capturedParams = new HashSet<Integer>();
@@ -399,8 +398,7 @@ public class AnonymousObjectTransformer {
while (cur != null) {
if (cur instanceof FieldInsnNode) {
FieldInsnNode fieldNode = (FieldInsnNode) cur;
String fieldName = fieldNode.name;
if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldName)) {
if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldNode.name)) {
boolean isPrevVarNode = fieldNode.getPrevious() instanceof VarInsnNode;
boolean isPrevPrevVarNode = isPrevVarNode && fieldNode.getPrevious().getPrevious() instanceof VarInsnNode;
@@ -411,8 +409,7 @@ public class AnonymousObjectTransformer {
VarInsnNode previous = (VarInsnNode) fieldNode.getPrevious();
int varIndex = previous.var;
LambdaInfo lambdaInfo = indexToLambda.get(varIndex);
String newFieldName = isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values()) ? getNewFieldName(fieldName, true) : fieldName;
CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldName, newFieldName, Type.getType(fieldNode.desc), lambdaInfo != null, null);
CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldNode.name, Type.getType(fieldNode.desc), lambdaInfo != null, null);
if (lambdaInfo != null) {
info.setLambda(lambdaInfo);
capturedLambdas.add(lambdaInfo);
@@ -457,57 +454,23 @@ public class AnonymousObjectTransformer {
//TODO: some of such parameters could be skipped - we should perform additional analysis
Map<String, LambdaInfo> capturedLambdasToInline = new HashMap<String, LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamDesc> allRecapturedParameters = new ArrayList<CapturedParamDesc>();
boolean addCapturedNotAddOuter = parentFieldRemapper.isRoot() || (parentFieldRemapper instanceof InlinedLambdaRemapper && parentFieldRemapper.getParent().isRoot());
Map<String, CapturedParamInfo> alreadyAdded = new HashMap<String, CapturedParamInfo>();
for (LambdaInfo info : capturedLambdas) {
if (addCapturedNotAddOuter) {
for (CapturedParamDesc desc : info.getCapturedVars()) {
String key = desc.getFieldName() + "$$$" + desc.getType().getClassName();
CapturedParamInfo alreadyAddedParam = alreadyAdded.get(key);
for (CapturedParamDesc desc : info.getCapturedVars()) {
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName()));
StackValue composed = StackValue.field(desc.getType(),
oldObjectType, /*TODO owner type*/
recapturedParamInfo.getNewFieldName(),
false,
StackValue.LOCAL_0);
recapturedParamInfo.setRemapValue(composed);
allRecapturedParameters.add(desc);
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(
desc,
alreadyAddedParam != null ? alreadyAddedParam.getNewFieldName() : getNewFieldName(desc.getFieldName(), false));
StackValue composed = StackValue.field(desc.getType(),
oldObjectType, /*TODO owner type*/
recapturedParamInfo.getNewFieldName(),
false,
StackValue.LOCAL_0);
recapturedParamInfo.setRemapValue(composed);
allRecapturedParameters.add(desc);
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
if (alreadyAddedParam != null) {
recapturedParamInfo.setSkipInConstructor(true);
}
if (isThis0(desc.getFieldName())) {
alreadyAdded.put(key, recapturedParamInfo);
}
}
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
}
capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info);
}
if (parentFieldRemapper instanceof InlinedLambdaRemapper && !capturedLambdas.isEmpty() && !addCapturedNotAddOuter) {
//lambda with non InlinedLambdaRemapper already have outer
FieldRemapper parent = parentFieldRemapper.getParent();
assert parent instanceof RegeneratedLambdaFieldRemapper;
final Type ownerType = Type.getObjectType(parent.getLambdaInternalName());
CapturedParamDesc desc = new CapturedParamDesc(new CapturedParamOwner() {
@Override
public Type getType() {
return ownerType;
}
}, InlineCodegenUtil.THIS, ownerType);
CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.THIS$0/*outer lambda/object*/);
StackValue composed = StackValue.LOCAL_0;
recapturedParamInfo.setRemapValue(composed);
allRecapturedParameters.add(desc);
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed);
}
anonymousObjectGen.setAllRecapturedParameters(allRecapturedParameters);
anonymousObjectGen.setCapturedLambdasToInline(capturedLambdasToInline);
@@ -515,30 +478,13 @@ public class AnonymousObjectTransformer {
return constructorAdditionalFakeParams;
}
private static boolean shouldRenameThis0(@NotNull FieldRemapper parentFieldRemapper, Collection<LambdaInfo> values) {
if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
for (LambdaInfo value : values) {
for (CapturedParamDesc desc : value.getCapturedVars()) {
if (isThis0(desc.getFieldName())) {
return true;
}
}
}
}
return false;
}
@NotNull
public String getNewFieldName(@NotNull String oldName, boolean originalField) {
public String getNewFieldName(@NotNull String oldName) {
if (InlineCodegenUtil.THIS$0.equals(oldName)) {
if (!originalField) {
return oldName;
} else {
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
return addUniqueField(oldName + InlineCodegenUtil.INLINE_FUN_THIS_0_SUFFIX);
}
//"this$0" couldn't clash and we should keep this name invariant for further transformations
return oldName;
}
return addUniqueField(oldName + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX);
return addUniqueField(oldName + "$inlined");
}
@NotNull
@@ -553,8 +499,4 @@ public class AnonymousObjectTransformer {
existNames.add(newName);
return newName;
}
private static boolean isFirstDeclSiteLambdaFieldRemapper(FieldRemapper parentRemapper) {
return !(parentRemapper instanceof RegeneratedLambdaFieldRemapper) && !(parentRemapper instanceof InlinedLambdaRemapper);
}
}

View File

@@ -33,8 +33,6 @@ public class CapturedParamInfo extends ParameterInfo {
private final String newFieldName;
private boolean skipInConstructor;
public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, int remapIndex) {
this(desc, desc.getFieldName(), skipped, index, remapIndex);
}
@@ -70,7 +68,6 @@ public class CapturedParamInfo extends ParameterInfo {
public CapturedParamInfo clone(int newIndex, StackValue newRamapIndex) {
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(desc, newFieldName, isSkipped, newIndex, newRamapIndex);
capturedParamInfo.setLambda(lambda);
capturedParamInfo.setSkipInConstructor(skipInConstructor);
return capturedParamInfo;
}
@@ -78,12 +75,4 @@ public class CapturedParamInfo extends ParameterInfo {
public String getContainingLambdaName() {
return desc.getContainingLambdaName();
}
public boolean isSkipInConstructor() {
return skipInConstructor;
}
public void setSkipInConstructor(boolean skipInConstructor) {
this.skipInConstructor = skipInConstructor;
}
}

View File

@@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
import org.jetbrains.org.objectweb.asm.tree.MethodNode;
@@ -121,10 +120,6 @@ public class FieldRemapper {
return lambdaInternalName;
}
public String getNewLambdaInternalName() {
return lambdaInternalName;
}
public boolean isRoot() {
return parent == null;
}

View File

@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.modules.TargetId;
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;
@@ -63,6 +62,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
@@ -246,7 +246,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
@@ -310,7 +310,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();
@@ -539,34 +539,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);
}
@@ -606,16 +598,18 @@ public class InlineCodegen extends CallGenerator {
CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state, sourceFile);
if (descriptor instanceof ScriptDescriptor) {
List<ScriptDescriptor> earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter();
return parent.intoScript((ScriptDescriptor) descriptor,
earlierScripts == null ? Collections.emptyList() : earlierScripts,
(ClassDescriptor) descriptor, state.getTypeMapper());
}
else if (descriptor instanceof ClassDescriptor) {
if (descriptor instanceof ClassDescriptor) {
OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION;
return parent.intoClass((ClassDescriptor) descriptor, kind, state);
}
else if (descriptor instanceof ScriptDescriptor) {
ClassDescriptor classDescriptorForScript = state.getBindingContext().get(CLASS_FOR_SCRIPT, (ScriptDescriptor) descriptor);
assert classDescriptorForScript != null : "Can't find class for script: " + descriptor;
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
return parent.intoScript((ScriptDescriptor) descriptor,
earlierScripts == null ? Collections.emptyList() : earlierScripts,
classDescriptorForScript);
}
else if (descriptor instanceof FunctionDescriptor) {
return parent.intoFunction((FunctionDescriptor) descriptor);
}
@@ -639,7 +633,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);
@@ -787,7 +781,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
) {
}

View File

@@ -29,9 +29,7 @@ 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;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
@@ -64,7 +62,6 @@ public class InlineCodegenUtil {
public static final String CAPTURED_FIELD_PREFIX = "$";
public static final String THIS$0 = "this$0";
public static final String THIS = "this";
public static final String RECEIVER$0 = "receiver$0";
public static final String NON_LOCAL_RETURN = "$$$$$NON_LOCAL_RETURN$$$$$";
public static final String FIRST_FUN_LABEL = "$$$$$ROOT$$$$$";
@@ -74,9 +71,6 @@ public class InlineCodegenUtil {
public static final String INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall";
public static final String INLINE_MARKER_FINALLY_START = "finallyStart";
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(
@@ -123,7 +117,7 @@ public class InlineCodegenUtil {
}
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.toString(), lines[0], lines[1]);
return new SMAPAndMethodNode(node[0], smap);
}
@@ -132,7 +126,7 @@ public class InlineCodegenUtil {
CodegenContext<?> parentContext = context.getParentContext();
while (parentContext != null) {
if (parentContext instanceof MethodContext) {
if (((MethodContext) parentContext).isInlineMethodContext()) {
if (((MethodContext) parentContext).isInlineFunction()) {
//just init default one to one mapping
codegen.getOrCreateSourceMapper();
break;
@@ -312,7 +306,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();
@@ -320,10 +315,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);
@@ -399,7 +390,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) {
@@ -494,26 +485,4 @@ public class InlineCodegenUtil {
public static boolean isFakeLocalVariableForInline(@NotNull String name) {
return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT);
}
public static boolean isThis0(String name) {
return THIS$0.equals(name);
}
@Nullable
public static AbstractInsnNode getPrevMeaningful(@NotNull AbstractInsnNode node) {
AbstractInsnNode result = node.getPrevious();
while (result != null && !UtilKt.isMeaningful(result)) {
result = result.getPrevious();
}
return result;
}
public static void removeInterval(@NotNull MethodNode node, @NotNull AbstractInsnNode startInc, @NotNull AbstractInsnNode endInc) {
while (startInc != endInc) {
AbstractInsnNode next = startInc.getNext();
node.instructions.remove(startInc);
startInc = next;
}
node.instructions.remove(startInc);
}
}

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.inline;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode;
import java.util.Collection;
@@ -51,15 +50,4 @@ public class InlinedLambdaRemapper extends FieldRemapper {
public boolean isInsideInliningLambda() {
return true;
}
@Nullable
@Override
public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) {
if (parent.isRoot()) {
return super.getFieldForInline(node, prefix);
} else {
return parent.getFieldForInline(node, prefix);
}
}
}

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen.inline;
import com.google.common.collect.Lists;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.ClosureCodegen;
import org.jetbrains.kotlin.codegen.StackValue;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
@@ -78,7 +77,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 +85,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 +152,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 +166,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 +260,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 +352,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));
}
}
};
@@ -451,16 +440,11 @@ public class MethodInliner {
if (sourceValue.insns.size() == 1) {
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
AbstractInsnNode processingInstruction = insnNode;
if (insnNode.getOpcode() == Opcodes.SWAP) {
processingInstruction = InlineCodegenUtil.getPrevMeaningful(insnNode);
}
lambdaInfo = getLambdaIfExists(processingInstruction);
lambdaInfo = getLambdaIfExists(insnNode);
if (lambdaInfo != null) {
//remove inlinable access
assert processingInstruction != null;
InlineCodegenUtil.removeInterval(node, processingInstruction, insnNode);
node.instructions.remove(insnNode);
}
}
@@ -559,15 +543,10 @@ public class MethodInliner {
}
private boolean isAlreadyRegenerated(@NotNull String owner) {
return inliningContext.typeRemapper.hasNoAdditionalMapping(owner);
return inliningContext.typeMapping.containsKey(owner);
}
@Nullable
public LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
if (insnNode == null) {
return null;
}
public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) {
if (insnNode.getOpcode() == Opcodes.ALOAD) {
int varIndex = ((VarInsnNode) insnNode).var;
return getLambdaIfExists(varIndex);

View File

@@ -77,11 +77,10 @@ internal class ParametersBuilder private constructor(){
fun addCapturedParam(
containingLambda: CapturedParamOwner,
fieldName: String,
newFieldName: String,
type: Type,
skipped: Boolean,
original: ParameterInfo?): CapturedParamInfo {
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), newFieldName, skipped, nextCapturedIndex(),
val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCapturedIndex(),
if (original != null) original.getIndex() else -1)
if (original != null) {
info.setLambda(original.getLambda())

View File

@@ -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;
}

View File

@@ -51,11 +51,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
@Override
public boolean canProcess(@NotNull String fieldOwner, String fieldName, boolean isFolding) {
return super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner, isFolding);
return super.canProcess(fieldOwner, fieldName, isFolding) || isRecapturedLambdaType(fieldOwner);
}
private boolean isRecapturedLambdaType(String owner, boolean isFolding) {
return recapturedLambdas.containsKey(owner) && (isFolding || false == parent instanceof InlinedLambdaRemapper);
private boolean isRecapturedLambdaType(String owner) {
return recapturedLambdas.containsKey(owner);
}
@Nullable
@@ -79,20 +79,10 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
return super.findField(fieldInsnNode, parameters.getCaptured());
}
@Override
public String getNewLambdaInternalName() {
return newOwnerType;
}
@Nullable
@Override
public StackValue getFieldForInline(@NotNull FieldInsnNode node, @Nullable StackValue prefix) {
assert node.name.startsWith("$$$") : "Captured field template should start with $$$ prefix";
if (node.name.equals("$$$" + InlineCodegenUtil.THIS)) {
assert oldOwnerType.equals(node.owner) : "Can't unfold '$$$THIS' parameter";
return StackValue.LOCAL_0;
}
FieldInsnNode fin = new FieldInsnNode(node.getOpcode(), node.owner, node.name.substring(3), node.desc);
CapturedParamInfo field = findFieldInMyCaptured(fin);
@@ -105,9 +95,8 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
}
}
StackValue result = StackValue.field(field.isSkipped ?
Type.getObjectType(parent.parent.getNewLambdaInternalName()) : field.getType(),
Type.getObjectType(getNewLambdaInternalName()), /*TODO owner type*/
StackValue result = StackValue.field(field.getType(),
Type.getObjectType(newOwnerType), /*TODO owner type*/
field.getNewFieldName(), false,
prefix == null ? StackValue.LOCAL_0 : prefix);

View File

@@ -18,22 +18,16 @@ package org.jetbrains.kotlin.codegen.inline
import com.google.common.collect.ImmutableSet
import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.generateIsCheck
import org.jetbrains.kotlin.codegen.generateNullCheckForNonSafeAs
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
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?) {
companion object {
@@ -70,23 +64,15 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
Type.getMethodDescriptor(Type.VOID_TYPE), false
);
}
@JvmStatic
public fun isNullableMarkerInstruction(marker: String) = INSTANCEOF_MARKER_METHOD_NAME == marker ||
CHECKCAST_MARKER_METHOD_NAME == marker
}
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 (isParametrisedReifiedMarker(insn)) {
@@ -97,7 +83,6 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
}
}
node.maxStack = node.maxStack + maxStackSize
return result
}
@@ -142,25 +127,20 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
* or null if it shouldn't
*/
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? {
val parameter = getParameter(insn) ?: return null
val mapping = parametersMapping?.get(parameter.name) ?: return null
val kotlinType =
if (isNullableMarkerInstruction(insn.name) && 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 (insn.name) {
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType)
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, kotlinType, asmType, safe = false)
SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, kotlinType, asmType, safe = true)
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, kotlinType, 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
}) {
@@ -170,8 +150,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
return null
} else {
val nullableSuffix = if (isNullableMarkerInstruction(insn.name) && kotlinType.isMarkedNullable) "?" else ""
instructions.set(insn.previous!!, LdcInsnNode(mapping.newName + nullableSuffix))
instructions.set(insn.getPrevious()!!, LdcInsnNode(mapping.newName))
return mapping.newName
}
}
@@ -179,66 +158,20 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
private fun processNewArray(insn: MethodInsnNode, parameter: Type) =
processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY)
private fun processCheckcast(insn: MethodInsnNode,
instructions: InsnList,
jetType: KotlinType,
asmType: Type,
safe: Boolean) =
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
addNullCheckForAsIfNeeded(insn.previous!!, instructions, jetType, safe)
TypeIntrinsics.checkcast(instanceofInsn, instructions, jetType, asmType, safe)
return true
}
private fun addNullCheckForAsIfNeeded(insn: AbstractInsnNode, instructions: InsnList, jetType: KotlinType, safe: Boolean) {
if (!safe && !TypeUtils.isNullableType(jetType)) {
val methodNode = MethodNode(InlineCodegenUtil.API)
generateNullCheckForNonSafeAs(InstructionAdapter(methodNode), jetType)
InlineCodegenUtil.insertNodeBefore(methodNode, instructions, insn)
maxStackSize = Math.max(maxStackSize, 4)
}
}
private fun processInstanceof(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type) =
rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { instanceofInsn: AbstractInsnNode ->
if (instanceofInsn !is TypeInsnNode) return false
addNullCheckForIsIfNeeded(insn, instructions, jetType)
TypeIntrinsics.instanceOf(instanceofInsn, instructions, jetType, asmType)
return true
}
private fun addNullCheckForIsIfNeeded(insn: AbstractInsnNode, instructions: InsnList, type: KotlinType) {
if (TypeUtils.isNullableType(type)) {
val instanceOf = insn.next
insertNullCheckAround(instructions, insn.previous!!, instanceOf)
maxStackSize = Math.max(maxStackSize, 2)
}
}
private fun insertNullCheckAround(instructions: InsnList, start: AbstractInsnNode, end: AbstractInsnNode) {
val methodNode = MethodNode(InlineCodegenUtil.API)
var splitIndex: Int = -1
generateIsCheck(InstructionAdapter(methodNode), true) {
splitIndex = methodNode.instructions.size()
}
assert(splitIndex >= 0) {
"Split index should be non-negative, but $splitIndex"
}
val nullCheckInsns = methodNode.instructions.toArray()
nullCheckInsns.take(splitIndex).forEach {
instructions.insertBefore(start, it)
}
nullCheckInsns.drop(splitIndex).reversed().forEach {
instructions.insert(end, it)
}
}
inline private fun rewriteNextTypeInsn(
marker: MethodInsnNode,
expectedNextOpcode: Int,
@@ -262,16 +195,17 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
return true
}
private fun getParameter(insn: MethodInsnNode): ParameterNameAndNullability? {
private fun getParameterName(insn: MethodInsnNode): String? {
val prev = insn.getPrevious()!!
val parameterNameWithFlag = when (prev.getOpcode()) {
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 fun getTypeParameterMapping(insn: MethodInsnNode): ReifiedTypeParameterMapping? {
return parametersMapping?.get(getParameterName(insn) ?: return null)
}
}
@@ -282,17 +216,17 @@ 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? {
fun get(name: String): ReifiedTypeParameterMapping? {
return mappingsByName[name]
}
}
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 {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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.inline
import com.intellij.openapi.util.Pair
import org.jetbrains.kotlin.codegen.FieldInfo
import org.jetbrains.org.objectweb.asm.Type
class NewJavaField(val name: String, val type: Type, val skip: Boolean)
fun getNewFieldsToGenerate(params: List<CapturedParamInfo>): List<NewJavaField> {
return params.filter {
//not inlined
it.lambda == null
}.map {
NewJavaField(it.newFieldName, it.type, it.isSkipInConstructor)
}
}
fun transformToFieldInfo(lambdaType: Type, newFields: List<NewJavaField>): List<FieldInfo> {
return newFields.map { field ->
FieldInfo.createForHiddenField(lambdaType, field.type, field.name)
}
}
fun filterSkipped(fields: List<NewJavaField>): List<NewJavaField> {
return fields.filter { !it.skip }
}
fun toNameTypePair(fields: List<NewJavaField>): List<Pair<String, Type>> = fields.map { Pair(it.name, it.type) }

View File

@@ -17,17 +17,18 @@
package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.genInvokeAppendMethod
import org.jetbrains.kotlin.codegen.AsmUtil.genStringBuilderConstructor
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -40,11 +41,11 @@ public class Concat : IntrinsicMethod() {
arguments: List<KtExpression>,
receiver: StackValue
): Type {
if (element is KtBinaryExpression && element.operationReference.getReferencedNameElementType() == KtTokens.PLUS) {
if (element is KtBinaryExpression && element.getOperationReference().getReferencedNameElementType() == KtTokens.PLUS) {
// LHS + RHS
genStringBuilderConstructor(v)
codegen.invokeAppend(element.left)
codegen.invokeAppend(element.right)
codegen.invokeAppend(element.getLeft())
codegen.invokeAppend(element.getRight())
}
else {
// LHS?.plus(RHS)
@@ -59,6 +60,7 @@ public class Concat : IntrinsicMethod() {
return JAVA_STRING_TYPE
}
override fun toCallable(method: CallableMethod): Callable =
object : IntrinsicCallable(method) {
override fun invokeMethodWithArguments(
@@ -66,37 +68,16 @@ public class Concat : IntrinsicMethod() {
receiver: StackValue,
codegen: ExpressionCodegen
): StackValue {
if (resolvedCall.call.callElement.parent is KtCallableReferenceExpression) {
// NB we come here only in case of inlined callable reference to String::plus.
// This will map arguments properly, invoking callbacks defined in Callable.
return super.invokeMethodWithArguments(resolvedCall, receiver, codegen)
}
return StackValue.operation(returnType) {
val arguments = resolvedCall.call.valueArguments.map { it.getArgumentExpression()!! }
val arguments = resolvedCall.getCall().getValueArguments().map { it.getArgumentExpression()!! }
val actualType = generateImpl(
codegen, it, returnType,
resolvedCall.call.callElement,
resolvedCall.getCall().getCallElement(),
arguments,
StackValue.receiver(resolvedCall, receiver, codegen, this)
)
StackValue.coerce(actualType, returnType, it)
}
}
override fun afterReceiverGeneration(v: InstructionAdapter) {
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
v.dupX1()
v.swap()
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
}
override fun invokeIntrinsic(v: InstructionAdapter) {
// String::plus has type String.(Any?) -> String, thus we have no argument type information
// in case of callable reference passed to a generic function, e.g.:
// charArrayOf('O', 'K').fold("", String::plus)
// TODO Make String::plus generic, and invoke proper StringBuilder#append.
AsmUtil.genInvokeAppendMethod(v, AsmTypes.OBJECT_TYPE)
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)
}
}
}
}

View File

@@ -37,17 +37,17 @@ public abstract class IntrinsicMethod {
}
@NotNull
protected Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) {
public Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) {
return toCallable(method, isSuper);
}
@NotNull
protected Callable toCallable(@NotNull CallableMethod method, boolean isSuperCall) {
public Callable toCallable(@NotNull CallableMethod method, boolean isSuperCall) {
return toCallable(method);
}
@NotNull
protected Callable toCallable(@NotNull CallableMethod method) {
public Callable toCallable(@NotNull CallableMethod method) {
throw new UnsupportedOperationException("Not implemented");
}

View File

@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen.intrinsics;
import com.google.common.collect.ImmutableList;
import kotlin.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
@@ -27,7 +26,6 @@ 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 org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt;
import java.util.HashMap;
import java.util.Map;
@@ -65,12 +63,11 @@ public class IntrinsicMethods {
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());
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOf", 1, new JavaClassArray());
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
for (Name method : primitiveCastMethods) {
String methodName = method.asString();
@@ -97,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);

View File

@@ -58,7 +58,7 @@ public class JavaClassProperty : IntrinsicPropertyGetter() {
}
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver()!!.getType())
val classType = codegen.getState().typeMapper.mapType(resolvedCall.getCall().getDispatchReceiver().getType())
return object : IntrinsicCallable(getType(javaClass<Class<Any>>()), listOf(), classType, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
if (isPrimitive(classType)) {

View File

@@ -25,15 +25,13 @@ import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
public class KClassJavaProperty : IntrinsicPropertyGetter() {
override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
val extensionReceiver = resolvedCall!!.extensionReceiver as ReceiverValue
val type = extensionReceiver.type.arguments.single().type
val type = resolvedCall!!.extensionReceiver.type.arguments.single().type
val asmType = codegen.state.typeMapper.mapType(type)
return when {

View File

@@ -44,19 +44,10 @@ public class RangeTo : IntrinsicMethod() {
nullOr(method.dispatchReceiverType, argType),
nullOr(method.extensionReceiverType, argType)
) {
override fun afterReceiverGeneration(v: InstructionAdapter) {
override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
v.anew(returnType)
when (argType.size) {
1 -> {
v.dupX1()
v.swap()
}
2 -> {
v.dup()
v.dup2X2()
v.pop2()
}
}
v.dup()
value?.moveToTopOfStack(value.type, v, 2)
}
override fun invokeIntrinsic(v: InstructionAdapter) {

View File

@@ -29,11 +29,11 @@ public class RedundantGotoMethodTransformer : MethodTransformer() {
* Removes redundant GOTO's, i.e. to subsequent labels
*/
override fun transform(internalClassName: String, methodNode: MethodNode) {
val insns = methodNode.instructions.toArray().apply { reverse() }
val insns = methodNode.instructions.toArray()
val insnsToRemove = arrayListOf<AbstractInsnNode>()
val currentLabels = hashSetOf<LabelNode>()
for (insn in insns) {
for (insn in insns.reversed()) {
if (insn.isMeaningful) {
if (insn.getOpcode() == Opcodes.GOTO && (insn as JumpInsnNode).label in currentLabels) {
insnsToRemove.add(insn)

View File

@@ -125,7 +125,7 @@ public open class MethodAnalyzer<V : Value>(
frames[instructions.indexOf(insn)]
private fun checkAssertions() {
if (instructions.toArray().any { it.getOpcode() == Opcodes.JSR || it.getOpcode() == Opcodes.RET })
if (instructions.toArray() any { it.getOpcode() == Opcodes.JSR || it.getOpcode() == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6")
}

View File

@@ -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;
}
}

View File

@@ -17,19 +17,19 @@
package org.jetbrains.kotlin.codegen.serialization;
import com.intellij.openapi.util.Pair;
import kotlin.jvm.functions.Function3;
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;
import org.jetbrains.kotlin.util.slicedMap.Slices;
import org.jetbrains.kotlin.util.slicedMap.*;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.Collection;
public final class JvmSerializationBindings {
public static final SerializationMappingSlice<FunctionDescriptor, Method> METHOD_FOR_FUNCTION =
SerializationMappingSlice.create();
@@ -70,7 +70,32 @@ public final class JvmSerializationBindings {
BasicWritableSlice.initSliceDebugNames(JvmSerializationBindings.class);
}
private final MutableSlicedMap map = SlicedMapImpl.create();
private final MutableSlicedMap map;
private JvmSerializationBindings(@NotNull MutableSlicedMap map) {
this.map = map;
}
public JvmSerializationBindings() {
this(SlicedMapImpl.create());
}
@NotNull
public static JvmSerializationBindings union(@NotNull Collection<JvmSerializationBindings> bindings) {
final MutableSlicedMap result = SlicedMapImpl.create();
for (JvmSerializationBindings binding : bindings) {
binding.map.forEach(new Function3<WritableSlice, Object, Object, Void>() {
@Override
public Void invoke(WritableSlice slice, Object key, Object value) {
result.put(slice, key, value);
return null;
}
});
}
return new JvmSerializationBindings(result);
}
public <K, V> void put(@NotNull SerializationMappingSlice<K, V> slice, @NotNull K key, @NotNull V value) {
map.put(slice, key, value);

View File

@@ -118,15 +118,6 @@ public class BothSignatureWriter {
writeAsmType0(asmType);
}
public void writeOuterClassBegin(Type resultingAsmType, String outerInternalName) {
signatureVisitor().visitClassType(outerInternalName);
writeAsmType0(resultingAsmType);
}
public void writeInnerClass(String name) {
signatureVisitor().visitInnerClassType(name);
}
public void writeClassEnd() {
signatureVisitor().visitEnd();
}
@@ -263,13 +254,13 @@ public class BothSignatureWriter {
}
@NotNull
public JvmMethodSignature makeJvmMethodSignature(@NotNull String name, boolean skipGenericSignature) {
public JvmMethodSignature makeJvmMethodSignature(@NotNull String name) {
List<Type> types = new ArrayList<Type>(kotlinParameterTypes.size());
for (JvmMethodParameterSignature parameter : kotlinParameterTypes) {
types.add(parameter.getAsmType());
}
Method asmMethod = new Method(name, jvmReturnType, types.toArray(new Type[types.size()]));
return new JvmMethodSignature(asmMethod, !skipGenericSignature ? makeJavaGenericSignature() : null, kotlinParameterTypes);
return new JvmMethodSignature(asmMethod, makeJavaGenericSignature(), kotlinParameterTypes);
}
public int getCurrentSignatureSize() {

View File

@@ -40,10 +40,10 @@ class BuilderFactoryForDuplicateClassNameDiagnostics(
}
private fun reportError(internalName: String, vararg another: JvmDeclarationOrigin) {
val fromString = another.mapNotNull { it.descriptor }.
val fromString = another.map { it.descriptor }.filterNotNull().
joinToString { DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(it) }
another.mapNotNull { it.element }.forEach {
another.map { it.element }.filterNotNull().forEach {
diagnostics.report(ErrorsJvm.DUPLICATE_CLASS_NAMES.on(it, internalName, fromString))
}
}

View File

@@ -26,13 +26,17 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor
import org.jetbrains.kotlin.load.java.descriptors.getParentJavaStaticClassScope
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.psi.KtNamedFunction
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 +56,10 @@ 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()
}
private val mainFunctionDetector = MainFunctionDetector(bindingContext)
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 +87,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
@@ -114,7 +102,7 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
signatures@
for ((rawSignature, origins) in groupedBySignature.entrySet()) {
if (origins.size <= 1) continue
if (origins.size() <= 1) continue
var memberElement: PsiElement? = null
var ownNonFakeCount = 0
@@ -174,7 +162,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 +170,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

View File

@@ -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
@@ -41,7 +38,6 @@ import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import java.io.File
public class GenerationState @JvmOverloads constructor(
@@ -56,6 +52,7 @@ public class GenerationState @JvmOverloads constructor(
disableInline: Boolean = false,
disableOptimization: Boolean = false,
public val useTypeTableInSerializer: Boolean = false,
public val diagnostics: DiagnosticSink = DiagnosticSink.DO_NOTHING,
public val packagesWithObsoleteParts: Collection<FqName> = emptySet(),
public val obsoleteMultifileClasses: Collection<FqName> = emptySet(),
// for PackageCodegen in incremental compilation mode
@@ -66,20 +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 {
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
@@ -95,16 +91,6 @@ public class GenerationState @JvmOverloads constructor(
incrementalCompilationComponents.getIncrementalCache(targetId)
else null
private val extraJvmDiagnosticsTrace: BindingTrace = DelegatingBindingTrace(bindingContext, false, "For extra diagnostics in ${this.javaClass}")
private val interceptedBuilderFactory: ClassBuilderFactory
private var used = false
public val diagnostics: DiagnosticSink get() = extraJvmDiagnosticsTrace
public val collectedExtraJvmDiagnostics: Diagnostics = LazyJvmDiagnostics {
duplicateSignatureFactory.reportDiagnostics()
extraJvmDiagnosticsTrace.bindingContext.diagnostics
}
public val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
public val classBuilderMode: ClassBuilderMode = builderFactory.getClassBuilderMode()
public val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState")
@@ -114,20 +100,12 @@ public class GenerationState @JvmOverloads constructor(
public val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
public val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
public val reflectionTypes: ReflectionTypes = ReflectionTypes(module)
public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes()
public val factory: ClassFileFactory
private val duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics
public val replSpecific = ForRepl()
//TODO: should be refactored out
public class ForRepl {
public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
public var scriptResultFieldName: String? = null
public val shouldGenerateScriptResultValue: Boolean get() = scriptResultFieldName != null
public var hasResult: Boolean = false
}
private val interceptedBuilderFactory: ClassBuilderFactory
private var used = false
public val isCallAssertionsEnabled: Boolean = !disableCallAssertions
@JvmName("isCallAssertionsEnabled") get
@@ -143,13 +121,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)
@@ -177,20 +154,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()
}

View File

@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen.state;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
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 +49,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 +111,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);
@@ -134,6 +168,9 @@ public class JetTypeMapper {
else if (container instanceof ClassDescriptor) {
return mapClass((ClassDescriptor) container);
}
else if (container instanceof ScriptDescriptor) {
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
}
else {
throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
}
@@ -320,53 +357,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,9 +405,9 @@ 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);
return sw.makeJvmMethodSignature(descriptor.getName().asString());
}
@NotNull
@@ -389,18 +415,37 @@ 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();
@@ -441,10 +486,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();
}
}
@@ -453,15 +501,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);
}
@@ -531,6 +579,10 @@ public class JetTypeMapper {
return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name;
}
if (container instanceof ScriptDescriptor) {
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name;
}
assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
@@ -574,144 +626,71 @@ public class JetTypeMapper {
}
private void writeGenericType(
@NotNull KotlinType type,
@NotNull Type asmType,
@Nullable BothSignatureWriter signatureVisitor,
@NotNull TypeMappingMode mode
BothSignatureWriter signatureVisitor,
Type asmType,
KotlinType jetType,
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(jetType)) {
signatureVisitor.writeAsmType(asmType);
return;
}
PossiblyInnerType possiblyInnerType = TypeParameterUtilsKt.buildPossiblyInnerType(type);
assert possiblyInnerType != null : "possiblyInnerType with arguments should not be null";
signatureVisitor.writeClassBegin(asmType);
List<PossiblyInnerType> innerTypesAsList = possiblyInnerType.segments();
PossiblyInnerType outermostInnerType = innerTypesAsList.get(0);
ClassDescriptor outermostClass = outermostInnerType.getClassDescriptor();
List<TypeProjection> arguments = jetType.getArguments();
for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
TypeProjection argument = arguments.get(parameter.getIndex());
if (innerTypesAsList.size() == 1) {
signatureVisitor.writeClassBegin(asmType);
if (projectionsAllowed && argument.isStarProjection()) {
signatureVisitor.writeUnboundedWildcard();
}
else {
Variance projectionKind = projectionsAllowed
? getEffectiveVariance(
parameter.getVariance(),
argument.getProjectionKind(),
howThisTypeIsUsed
)
: Variance.INVARIANT;
signatureVisitor.writeTypeArgument(projectionKind);
mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
signatureVisitor.writeTypeArgumentEnd();
}
}
else {
signatureVisitor.writeOuterClassBegin(
asmType,
mapType(outermostClass.getDefaultType()).getInternalName());
}
writeGenericArguments(
signatureVisitor,
outermostInnerType.getArguments(), outermostClass.getDeclaredTypeParameters(), mode);
for (PossiblyInnerType innerPart : innerTypesAsList.subList(1, innerTypesAsList.size())) {
ClassDescriptor classDescriptor = innerPart.getClassDescriptor();
signatureVisitor.writeInnerClass(getJvmShortName(classDescriptor));
writeGenericArguments(
signatureVisitor, innerPart.getArguments(),
classDescriptor.getDeclaredTypeParameters(), mode);
}
signatureVisitor.writeClassEnd();
}
}
@Nullable
private static String getJvmShortName(@NotNull ClassDescriptor klass) {
ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(klass));
if (classId != null) {
return classId.getShortClassName().asString();
}
return SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
}
private void writeGenericArguments(
@NotNull BothSignatureWriter signatureVisitor,
@NotNull List<? extends TypeProjection> arguments,
@NotNull List<? extends TypeParameterDescriptor> parameters,
@NotNull TypeMappingMode mode
) {
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
) {
signatureVisitor.writeUnboundedWildcard();
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());
}
else {
TypeMappingMode argumentMode = TypeMappingUtil.updateArgumentModeFromAnnotations(mode, argument.getType());
Variance projectionKind = getVarianceForWildcard(parameter, argument, argumentMode);
});
signatureVisitor.writeTypeArgument(projectionKind);
if (hasNothingInArguments) return true;
mapType(argument.getType(), signatureVisitor,
argumentMode.toGenericArgumentMode(
TypeMappingUtil.getEffectiveVariance(parameter.getVariance(), argument.getProjectionKind())));
signatureVisitor.writeTypeArgumentEnd();
return CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
@Override
public Boolean invoke(TypeProjection projection) {
return !projection.isStarProjection() && hasNothingInArguments(projection.getType());
}
}
});
}
private static boolean hasNothingInNonContravariantPosition(KotlinType kotlinType) {
List<TypeParameterDescriptor> parameters = kotlinType.getConstructor().getParameters();
List<TypeProjection> arguments = kotlinType.getArguments();
private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
// Return type must not contain wildcards
if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
for (int i = 0; i < arguments.size(); i++) {
TypeProjection projection = arguments.get(i);
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;
}
@NotNull
private static Variance getVarianceForWildcard(
@NotNull TypeParameterDescriptor parameter,
@NotNull TypeProjection projection,
@NotNull TypeMappingMode mode
) {
Variance projectionKind = projection.getProjectionKind();
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) {
@@ -723,13 +702,39 @@ 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) {
JvmMethodSignature method = mapSignature(descriptor);
Type owner = mapClass(((ConstructorDescriptor) descriptor).getContainingDeclaration());
String defaultImplDesc = mapDefaultMethod(descriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
return new CallableMethod(owner, owner, defaultImplDesc, method, INVOKESPECIAL, null, null, null);
return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
}
DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
@@ -739,7 +744,7 @@ public class JetTypeMapper {
JvmMethodSignature signature;
Type owner;
Type ownerForDefaultImpl;
FunctionDescriptor baseMethodDescriptor;
Type ownerForDefaultParam;
int invokeOpcode;
Type thisClass;
@@ -754,11 +759,11 @@ public class JetTypeMapper {
boolean isInterface = currentIsInterface && originalIsInterface;
baseMethodDescriptor = findBaseDeclaration(functionDescriptor).getOriginal();
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
ownerForDefaultParam = mapClass(ownerForDefault);
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : ownerForDefaultParam;
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;
@@ -788,7 +793,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();
@@ -805,8 +810,8 @@ public class JetTypeMapper {
else {
signature = mapSignature(functionDescriptor.getOriginal());
owner = mapOwner(functionDescriptor);
ownerForDefaultParam = owner;
ownerForDefaultImpl = owner;
baseMethodDescriptor = functionDescriptor;
if (functionParent instanceof PackageFragmentDescriptor) {
invokeOpcode = INVOKESTATIC;
thisClass = null;
@@ -831,11 +836,8 @@ public class JetTypeMapper {
else {
receiverParameterType = null;
}
String defaultImplDesc = mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).getDescriptor();
return new CallableMethod(
owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
thisClass, receiverParameterType, calleeType);
}
@@ -898,7 +900,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();
@@ -916,18 +918,6 @@ public class JetTypeMapper {
}
}
@NotNull
private static OwnerKind getKindForDefaultImplCall(@NotNull FunctionDescriptor baseMethodDescriptor) {
DeclarationDescriptor containingDeclaration = baseMethodDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof PackageFragmentDescriptor) {
return OwnerKind.PACKAGE;
}
else if (isInterface(containingDeclaration)) {
return OwnerKind.DEFAULT_IMPLS;
}
return OwnerKind.IMPLEMENTATION;
}
@NotNull
public static String mapDefaultFieldName(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegated) {
String name;
@@ -967,7 +957,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);
}
@@ -993,7 +983,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) {
@@ -1010,12 +1000,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();
@@ -1023,15 +1013,15 @@ public class JetTypeMapper {
sw.writeReturnTypeEnd();
}
JvmMethodSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f), f instanceof AccessorForCallableDescriptor);
JvmMethodSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f));
if (kind != OwnerKind.DEFAULT_IMPLS) {
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());
}
}
@@ -1049,7 +1039,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;
}
@@ -1057,7 +1047,7 @@ public class JetTypeMapper {
}
@NotNull
private static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
public static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
String descriptor = method.getDescriptor();
int argumentsCount = Type.getArgumentTypes(descriptor).length;
if (isExtension) {
@@ -1122,16 +1112,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();
}
@@ -1149,7 +1132,7 @@ public class JetTypeMapper {
}
else return;
writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType(), descriptor);
writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType());
}
@NotNull
@@ -1183,7 +1166,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;
}
}
@@ -1201,13 +1184,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 {
@@ -1216,50 +1199,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);
@@ -1271,20 +1220,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;
@@ -1380,16 +1327,18 @@ public class JetTypeMapper {
sw.writeParametersStart();
for (ScriptDescriptor importedScript : importedScripts) {
writeParameter(sw, importedScript.getDefaultType(), /* callableDescriptor = */ null);
ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
assert descriptor != null : "Script not found: " + importedScript;
writeParameter(sw, descriptor.getDefaultType());
}
for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
writeParameter(sw, valueParameter.getType(), /* callableDescriptor = */ null);
for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) {
writeParameter(sw, valueParameter.getType());
}
writeVoidReturn(sw);
return sw.makeJvmMethodSignature("<init>", false);
return sw.makeJvmMethodSignature("<init>");
}
public Type getSharedVarType(DeclarationDescriptor descriptor) {

View File

@@ -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
}
}

View File

@@ -1,129 +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.
*/
@file:JvmName("TypeMappingUtil")
package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
fun KotlinType.isMostPreciseContravariantArgument(parameter: TypeParameterDescriptor): Boolean =
// TODO: probably class upper bound should be used
KotlinBuiltIns.isAnyOrNullableAny(this)
fun KotlinType.isMostPreciseCovariantArgument(): Boolean = !canHaveSubtypesIgnoringNullability()
private fun KotlinType.canHaveSubtypesIgnoringNullability(): Boolean {
val constructor = constructor
val descriptor = constructor.declarationDescriptor
when (descriptor) {
is TypeParameterDescriptor -> return true
is ClassDescriptor -> if (!descriptor.isFinalClass) return true
}
for ((parameter, argument) in constructor.parameters.zip(arguments)) {
if (argument.isStarProjection) return true
val projectionKind = argument.projectionKind
val type = argument.type
val effectiveVariance = getEffectiveVariance(parameter.variance, projectionKind)
if (effectiveVariance == Variance.OUT_VARIANCE && !type.isMostPreciseCovariantArgument()) return true
if (effectiveVariance == Variance.IN_VARIANCE && !type.isMostPreciseContravariantArgument(parameter)) return true
}
return false
}
public fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Variance): Variance {
if (parameterVariance === Variance.INVARIANT) {
return projectionKind
}
if (projectionKind === Variance.INVARIANT) {
return parameterVariance
}
if (parameterVariance === projectionKind) {
return parameterVariance
}
// In<out X> = In<*>
// Out<in X> = Out<*>
return Variance.OUT_VARIANCE
}
val CallableDescriptor?.isMethodWithDeclarationSiteWildcards: Boolean
get() {
if (this !is CallableMemberDescriptor) return false
return firstOverridden {
METHODS_WITH_DECLARATION_SITE_WILDCARDS.containsRaw(it.propertyIfAccessor.fqNameOrNull())
} != null
}
private val METHODS_WITH_DECLARATION_SITE_WILDCARDS = setOf(
FqName("kotlin.MutableCollection.addAll"),
FqName("kotlin.MutableList.addAll"),
FqName("kotlin.MutableMap.putAll")
)
internal fun TypeMappingMode.updateArgumentModeFromAnnotations(type: KotlinType): TypeMappingMode {
type.suppressWildcardsMode()?.let {
return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter)
}
if (type.annotations.hasAnnotation(JVM_WILDCARD_ANNOTATION_FQ_NAME)) {
return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
skipDeclarationSiteWildcards = false, isForAnnotationParameter = isForAnnotationParameter, fallbackMode = this)
}
return this
}
internal fun extractTypeMappingModeFromAnnotation(
callableDescriptor: CallableDescriptor?,
outerType: KotlinType,
isForAnnotationParameter: Boolean
): TypeMappingMode? =
(outerType.suppressWildcardsMode() ?: callableDescriptor?.suppressWildcardsMode())?.let {
if (outerType.arguments.isNotEmpty())
TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter)
else
TypeMappingMode.DEFAULT
}
private fun DeclarationDescriptor.suppressWildcardsMode(): Boolean? =
parentsWithSelf.mapNotNull {
it.annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)
}.firstOrNull().suppressWildcardsMode()
private fun KotlinType.suppressWildcardsMode(): Boolean? =
annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME).suppressWildcardsMode()
private fun AnnotationDescriptor?.suppressWildcardsMode(): Boolean? {
return (this ?: return null).allValueArguments.values.firstOrNull()?.value as? Boolean ?: true
}
private val JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmSuppressWildcards")
private val JVM_WILDCARD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmWildcard")

View File

@@ -47,7 +47,7 @@ public class MappingClassesForWhenByEnumCodegen {
cb.defineClass(
srcFile,
V1_6,
ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_SYNTHETIC,
ACC_FINAL | ACC_SYNTHETIC | ACC_PUBLIC,
mappingsClass.getInternalName(),
null,
OBJECT_TYPE.getInternalName(),

View File

@@ -132,18 +132,24 @@ public class BuiltInsSerializer(private val dependOnOldBuiltIns: Boolean) {
val fragments = packageView.fragments
val packageProto = DescriptorSerializer.createTopLevel(extension).packageProto(fragments).build()
packageProto.writeTo(packageStream)
write(destDir, BuiltInsSerializedResourcePaths.getPackageFilePath(fqName), packageStream)
write(destDir, BuiltInsSerializedResourcePaths.getPackageFilePath(fqName), packageStream,
BuiltInsSerializedResourcePaths.fallbackPaths.getPackageFilePath(fqName))
val nameStream = ByteArrayOutputStream()
extension.stringTable.serializeTo(nameStream)
write(destDir, BuiltInsSerializedResourcePaths.getStringTableFilePath(fqName), nameStream)
write(destDir, BuiltInsSerializedResourcePaths.getStringTableFilePath(fqName), nameStream,
BuiltInsSerializedResourcePaths.fallbackPaths.getStringTableFilePath(fqName))
}
private fun write(destDir: File, fileName: String, stream: ByteArrayOutputStream) {
private fun write(destDir: File, fileName: String, stream: ByteArrayOutputStream, legacyFileName: String? = null) {
totalSize += stream.size()
totalFiles++
File(destDir, fileName).parentFile.mkdirs()
File(destDir, fileName).writeBytes(stream.toByteArray())
legacyFileName?.let { fileName ->
File(destDir, fileName).writeBytes(stream.toByteArray())
}
}
private fun serializeClass(

View File

@@ -16,20 +16,27 @@
package org.jetbrains.kotlin.serialization.builtins
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.*
import org.jetbrains.kotlin.types.KotlinType
public class BuiltInsSerializerExtension : SerializerExtension() {
private val stringTable = StringTableImpl()
private val annotationSerializer = AnnotationSerializer(stringTable)
override fun getStringTable(): StringTable = stringTable
public class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
override fun shouldUseTypeTable(): Boolean = true
override fun serializePackage(packageFragments: Collection<PackageFragmentDescriptor>, proto: ProtoBuf.Package.Builder) {
if (packageFragments.isEmpty()) return
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder) {
for (annotation in descriptor.annotations) {
proto.addExtension(BuiltInsProtoBuf.classAnnotation, annotationSerializer.serializeAnnotation(annotation))
}
}
override fun serializePackage(packageFragments: Collection<PackageFragmentDescriptor>, proto: ProtoBuf.Package.Builder) {
val classes = packageFragments.flatMap {
it.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS).filterIsInstance<ClassDescriptor>()
}
@@ -37,7 +44,40 @@ public class BuiltInsSerializerExtension : KotlinSerializerExtensionBase(BuiltIn
for (descriptor in DescriptorSerializer.sort(classes)) {
proto.addExtension(BuiltInsProtoBuf.className, stringTable.getSimpleNameIndex(descriptor.name))
}
}
proto.setExtension(BuiltInsProtoBuf.packageFqName, stringTable.getPackageFqNameIndex(packageFragments.first().fqName))
override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder) {
for (annotation in descriptor.annotations) {
proto.addExtension(BuiltInsProtoBuf.constructorAnnotation, annotationSerializer.serializeAnnotation(annotation))
}
}
override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) {
for (annotation in descriptor.annotations) {
proto.addExtension(BuiltInsProtoBuf.functionAnnotation, annotationSerializer.serializeAnnotation(annotation))
}
}
override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) {
for (annotation in descriptor.annotations) {
proto.addExtension(BuiltInsProtoBuf.propertyAnnotation, annotationSerializer.serializeAnnotation(annotation))
}
val compileTimeConstant = descriptor.compileTimeInitializer ?: return
if (compileTimeConstant !is NullValue) {
val valueProto = annotationSerializer.valueProto(compileTimeConstant)
proto.setExtension(BuiltInsProtoBuf.compileTimeValue, valueProto.build())
}
}
override fun serializeValueParameter(descriptor: ValueParameterDescriptor, proto: ProtoBuf.ValueParameter.Builder) {
for (annotation in descriptor.annotations) {
proto.addExtension(BuiltInsProtoBuf.parameterAnnotation, annotationSerializer.serializeAnnotation(annotation))
}
}
override fun serializeType(type: KotlinType, proto: ProtoBuf.Type.Builder) {
for (annotation in type.annotations) {
proto.addExtension(BuiltInsProtoBuf.typeAnnotation, annotationSerializer.serializeAnnotation(annotation))
}
}
}

View File

@@ -36,10 +36,10 @@ found top-level declarations to <destination dir> (files such as
val destDir = File(args[0])
val srcDirs = args.drop(1).map { File(it) }
val srcDirs = args drop(1) map { File(it) }
assert(srcDirs.isNotEmpty()) { "At least one source directory should be specified" }
val missing = srcDirs.filterNot { it.exists() }
val missing = srcDirs filterNot { it.exists() }
assert(missing.isEmpty()) { "These source directories are missing: $missing" }
BuiltInsSerializer(dependOnOldBuiltIns = false).serialize(destDir, srcDirs, listOf()) { totalSize, totalFiles ->

View File

@@ -17,11 +17,3 @@
package org.jetbrains.kotlin.cli.common
public val KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY = "kotlin.environment.keepalive"
fun String?.toBooleanLenient(): Boolean? = when (this?.toLowerCase()) {
null -> false
in listOf("", "yes", "true", "on", "y") -> true
in listOf("no", "false", "off", "n") -> false
else -> null
}

View File

@@ -41,9 +41,6 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
@Argument(value = "meta-info", description = "Generate metadata")
public boolean metaInfo;
@Argument(value = "kjsm", description = "Generate kjsm-files (for creating libraries)")
public boolean kjsm;
@Argument(value = "target", description = "Generate JS files for specific ECMA version (only ECMA 5 is supported)")
@ValueDescription("<version>")
public String target;

View File

@@ -64,9 +64,6 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
@Argument(value = "Xreport-perf", description = "Report detailed performance statistics")
public boolean reportPerf;
@Argument(value = "Xmultifile-facades-open", description = "Compile multifile facade classes as open")
public boolean multifileFacadesOpen;
// Paths to output directories for friend modules.
public String[] friendPaths;

View File

@@ -20,8 +20,6 @@ import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class GroupingMessageCollector implements MessageCollector {
private final MessageCollector delegate;
@@ -50,14 +48,13 @@ public class GroupingMessageCollector implements MessageCollector {
public void flush() {
boolean hasError = false;
Collection<String> keys = sortedKeys();
for (String path : keys) {
for (String path : groupedMessages.keySet()) {
for (Message message : groupedMessages.get(path)) {
hasError |= CompilerMessageSeverity.ERRORS.contains(message.severity);
}
}
for (String path : keys) {
for (String path : groupedMessages.keySet()) {
for (Message message : groupedMessages.get(path)) {
if (!hasError || CompilerMessageSeverity.ERRORS.contains(message.severity)) {
delegate.report(message.severity, message.message, message.location);
@@ -68,22 +65,6 @@ public class GroupingMessageCollector implements MessageCollector {
groupedMessages.clear();
}
@NotNull
private Collection<String> sortedKeys() {
List<String> sortedKeys = new ArrayList<String>(groupedMessages.keySet());
// ensure that messages with no location i.e. perf, incomplete hierarchy are always reported first
Collections.sort(sortedKeys, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (o1 == o2) return 0;
if (o1 == null) return -1;
if (o2 == null) return 1;
return o1.compareTo(o2);
}
});
return sortedKeys;
}
private static class Message {
private final CompilerMessageSeverity severity;
private final String message;

Some files were not shown because too many files have changed in this diff Show More