Compare commits

..

365 Commits

Author SHA1 Message Date
Pavel V. Talanov
a3f51fabce Comments for review 2017-07-24 18:00:02 +03:00
Kirill Rakhman
4c7ddbe397 "Use destructuring declaration" should not be available for top-level and class properties (#1205)
Fixes #KT-19167
2017-07-24 14:33:46 +02:00
Dmitry Petrov
f558b4238c Use counter loop in intrinsic array constructors
#KT-19149 Fixed Target versions 1.1.5
2017-07-24 10:17:30 +03:00
Dmitry Petrov
c9d9a8220d Minor: use IntrinsicMethods.INTRINSICS_CLASS_NAME where appropriate 2017-07-24 10:15:27 +03:00
Dmitry Petrov
fda89e9c72 Add test for KT-19128
It looks like the problem was caused by incorrect merging of
StrictBasicValues and was fixed by commit
904c7f9c64.

 #KT-19128 Fixed
2017-07-24 10:15:27 +03:00
Dmitry Petrov
d0c8af5621 Keep track of second receiver type in CallReceiver
#KT-17725 Fixed Target versions 1.1.5
2017-07-24 10:15:27 +03:00
Dmitry Petrov
3f34a97880 Minor: extract CallReceiver to a top-level class, move code around 2017-07-24 10:15:27 +03:00
Simon Ogorodnik
f079ed949c KT-19015: Enable multiarg completion for non-first argument
#KT-19015 fixed
2017-07-24 00:00:11 +03:00
Ilya Gorbunov
ec5c15f190 test-dagger-maven-example: kotlin version comes as a parameter 2017-07-21 20:15:34 +03:00
Ilya Gorbunov
d8ea3ddcc8 Cleanup poms of projects migrated to gradle 2017-07-21 20:15:34 +03:00
Alexander Udalov
f69e96b240 Fix IAE at protoDifferenceUtils.kt on new metadata field
The class_local_variable/package_local_variable JVM extensions were
added in 616d575fb6

 #KT-19155 Fixed
2017-07-21 20:11:43 +03:00
Nikolay Krasko
b6bd3e15c5 Fix outdated highlighting for Kotlin injected fragments (KT-18842)
Do not use cached value for injection in non-dispatch threads and throw
PCE if value isn't ready. Otherwise outdated value may be stored in
highlighting.

 #KT-18842 Fixed
2017-07-21 19:57:21 +03:00
Alexander Udalov
7f8e7c66f5 Suppress FNFE in .kotlin_metadata index
Similarly to VirtualFileKotlinClass.create.

This could happen for example when some files are removed from
kotlin-stdlib-common
2017-07-21 19:03:15 +03:00
Alexander Udalov
ebdf5aa223 Discriminate header classes in favor of non-header type aliases
In the test case, the problem was that Foo.a's type was resolved to the
_class A_, which was written to metadata on JVM instead of the class
AImpl with typealias A as an abbreviation. This metadata was incorrect
because there's no class A from the JVM compiler's point of view; that's
why the error "cannot access class A" was reported

 #KT-19151 Fixed
2017-07-21 19:03:15 +03:00
Mikhail Glukhikh
6ee94dae6f Code cleanup: KotlinSafeDeleteProcessor 2017-07-21 18:59:13 +03:00
Mikhail Glukhikh
d05a525d8d Search for KtTypeAlias in safe delete processor
Related to KT-16046
2017-07-21 18:59:07 +03:00
Mikhail Glukhikh
dd0cf8219e Add type aliases into UnusedSymbolInspection / safe delete
So #KT-16046 Fixed
2017-07-21 18:59:01 +03:00
Mikhail Glukhikh
951e8cd91a Code cleanup: unnecessary local variable applied 2017-07-21 18:58:48 +03:00
Mikhail Glukhikh
202fb19cf6 If-then to safe access: more correct receiver calculation
So #KT-18928 Fixed
2017-07-21 18:58:33 +03:00
Mikhail Glukhikh
31bb1cc0f9 Invoke back setting "show inline dialog for local variables"
So #KT-19130 Fixed
2017-07-21 18:58:27 +03:00
Kirill Rakhman
a7084ceb9b Fix some type hints related issues (#1204)
* Type hints shouldn't appear for negative literals
Fixes #KT-18974

* Make type hints work for destructuring declarations
Fixes #KT-18444

* Hide type hints for generic constructor calls if type arguments are explicitly specified
Fixes #KT-19167
2017-07-21 16:31:46 +02:00
Nikolay Krasko
f4038f7109 Fix slow typing because of counting injected fragments (KT-18842)
- cache result of kotlin injection on modification tracker
- never count injection in dispatch thread, use cached result instead
- compute injection with write action priority, reuse cache if unfinished

 #KT-18842 Fixed
2017-07-21 15:41:06 +03:00
Nikolay Krasko
436b637282 Refactoring: show using ProcessCancelException in method name 2017-07-21 15:41:06 +03:00
Nikolay Krasko
fbe16f7b91 Refactoring: delete unused CachedValueProperty class 2017-07-21 15:41:06 +03:00
Mikhail Glukhikh
1cb6128f2f Minor: J2K test fix 2017-07-21 12:21:04 +03:00
Dmitry Petrov
bf3e896464 Update 'this' extension receiver when there's a smart cast
If 'this' (implicit or explicit) was used as an extension receiver,
and the corresponding call required a smart-cast,
this information was effectively lost in "old" resolution & inference,
but is required by "old" JVM BE to generate proper CHECKCASTs.
2017-07-21 08:58:52 +03:00
Dmitry Petrov
c9d54d7110 Generate proper error candidates for type aliases
#KT-17745 Fixed Target versions 1.1.5
2017-07-21 08:58:12 +03:00
Dmitry Petrov
b4d8337ca5 Ignore test for 'primitive Char == object' in JS (KT-19081) 2017-07-21 08:52:29 +03:00
Dmitry Petrov
709a7e201f Simplify code for specialized BranchedValues 2017-07-21 08:52:29 +03:00
Dmitry Petrov
e1a55e8dec Prefer compact bytecode for primitive/object comparisons with Boolean
'java.lang.Boolean#valueOf' doesn't allocate new objects
(it uses pre-allocated singletons for 'true' and 'false').
2017-07-21 08:52:29 +03:00
Dmitry Petrov
8e9c0294fe Do not box primitives for 'primitive == object'
NB user-defined 'equals' can violate contract for 'Object#equals', e.g.,
it can be asymmetric.
Thus we can't avoid boxing for 'object == primitive'.
2017-07-21 08:52:29 +03:00
Dmitry Petrov
fa42f202fa Avoid boxing on 'primitive == boxed' when possible
Similar to 'boxed == primitive' case, different bytecode due to
evaluation order.
2017-07-21 08:52:29 +03:00
Dmitry Petrov
e440de3494 Minor: GeneratePrimitiveVsObjectEqualityTestData 2017-07-21 08:52:29 +03:00
Dmitry Petrov
98ee83f4a3 Minor: move condition for boxed==primitive to corresponding isApplicable 2017-07-21 08:52:29 +03:00
Dmitry Petrov
4cba600268 Minor: some more evaluation order tests for 'boxed == primitive' 2017-07-21 08:52:29 +03:00
Dmitry Petrov
81609e4c6f Generate complex equality comparison only when RHS can have side effects
In "short" version, LHS is always evaluated before RHS,
and RHS may be not evaluated if LHS is null.
So, it makes sense to use "short" version in cases when RHS can't have
side effects (because of more compact bytecode and more opportunities
for code elimination).
2017-07-21 08:52:29 +03:00
Dmitry Petrov
8aacddb9f0 Avoid primitive boxing for 'boxed == primitive' if possible
This makes sense for non-floating-point primitive type
(boolean, char, byte, short, int, long):
floating-point types use specialized versions of 'areEqual'.
2017-07-21 08:52:29 +03:00
Dmitry Petrov
275c758da1 Cleanup and move code around in BranchedValue
- Cleanup inspections
- Move optimized boxed-vs-primitive comparisons to a separate file
2017-07-21 08:52:29 +03:00
Dmitry Petrov
051ac44759 Verify bytecode after mandatory transformations and after optimizations 2017-07-21 08:52:29 +03:00
Simon Ogorodnik
7ed1669050 KT-19011: Fix import optimizing when extension functional type is used
It should check is extension functional type imported from companion
is actually called on companion instance

 #KT-19011 fixed
2017-07-21 03:08:06 +03:00
Dimach
65e603c1ed KT-13552: Fix J2K to generate else block while converting switch
#KT-13552 fixed
2017-07-20 23:35:11 +03:00
Mikhail Glukhikh
44790eccaf Use "unnecessary variable" inspection in J2K
Unused variables are no more treated as unnecessary
Related to KT-15958
2017-07-20 17:48:27 +03:00
Mikhail Glukhikh
39f1ef390e Do not report "redundant Unit" for generic calls coerced to Unit
So #KT-18999 Fixed
2017-07-20 17:48:20 +03:00
Mikhail Glukhikh
c554bfa20d Move: RemoveSetterParameterTypeInspection to inspections package 2017-07-20 17:48:14 +03:00
Mikhail Glukhikh
e154e4cf75 Move: RedundantUnitReturnTypeInspection to inspections package 2017-07-20 17:48:07 +03:00
Simon Ogorodnik
8f78446bff Minor: Clarify code for KT-18786: Fix J2K to move properties to top 2017-07-20 16:04:07 +03:00
Dmitry Jemerov
9213c4a1ab EA-104855 - (1.1.4) NPE: KotlinCommonBlockKt.isFirstParameter 2017-07-20 12:50:12 +02:00
Dmitry Jemerov
fbcc519098 Fix tests affected by annotation wrapping changes 2017-07-20 12:32:48 +02:00
Alexander Udalov
5128b8a409 Add default implementation for Annotations.findAnnotation 2017-07-20 13:27:34 +03:00
Alexander Udalov
def3f73fdd Use AnnotationDescriptor.fqName instead of type
Also use the annotationClass extension property instead of
TypeUtils.getClassDescriptor(annotation.type)
2017-07-20 13:26:13 +03:00
Alexander Udalov
541b9dab52 Introduce optimized BuiltInAnnotationDescriptor for built-in annotations
It's built on a FQ name and avoids resolution of the annotation class
descriptor as much as possible
2017-07-20 13:26:13 +03:00
Alexander Udalov
f39106f75c Do not use parameter descriptors in AnnotationDescriptorImpl 2017-07-20 13:26:13 +03:00
Alexander Udalov
eb205f620c Do not use parameter descriptors in most annotation implementations
Except AnnotationDescriptorImpl, which is refactored in the subsequent
commit.

Note that we no longer check the presence of parameters with the
corresponding names in the annotation class in
LazyJavaAnnotationDescriptor, this is why test data changed
2017-07-20 13:25:39 +03:00
Alexander Udalov
cc7ed2ba54 Change map key type in AnnotationDescriptor.getAllValueArguments
Turns out, only the parameter's name is needed at all usages of this
method. Such a map is both easier to use (no need to call
ValueParameterDescriptor.getName) and easier to construct (no need to
resolve annotation class, its constructor, its parameters). In this
commit, only usages have changed but the implementations are still using
the old logic, this is going to be refactored in subsequent commits
2017-07-20 13:25:39 +03:00
Alexander Udalov
41ea0e8ef8 Introduce AnnotationDescriptor.fqName
Could be used instead of ".annotationClass.fqName" to avoid the unneeded
resolution of the annotation class descriptor
2017-07-20 13:25:38 +03:00
Alexander Udalov
1d64b61a8f J2K AnnotationDescriptor, refactor implementations 2017-07-20 13:25:38 +03:00
Alexander Udalov
7ec67505c5 Optimize Annotations.isEmpty in some implementations 2017-07-20 13:25:38 +03:00
Alexander Udalov
9ee4b39e1b Provide default implementation for Annotations.findExternalAnnotation 2017-07-20 13:25:38 +03:00
Alexander Udalov
5636318eb4 Optimize DeserializedAnnotations in terms of memory traffic
Do not wrap every annotation object into an AnnotationWithTarget
2017-07-20 13:25:38 +03:00
Alexander Udalov
21197b53aa Do not load annotations on value parameter if there are none
Also fix an error in the doc in descriptors.proto
2017-07-20 13:25:38 +03:00
Alexander Udalov
c197db9c69 Remove some unnecessary lazy computations in LazyJavaClassDescriptor 2017-07-20 13:25:38 +03:00
Mikhail Glukhikh
bdc44ff4cf Unnecessary variable: do not start inlining in write action
So #KT-19110 Fixed

(cherry picked from commit 6325fb1)
2017-07-20 12:39:52 +03:00
Ilya Chernikov
e38aaf3e07 Fix xmx setting for the daemon in tests 2017-07-20 10:54:05 +02:00
Ilya Chernikov
17a189a24b Improve logging and exception handling in the daemon 2017-07-20 10:54:05 +02:00
Denis Zharkov
904c7f9c64 Fix nullable variables spilling in coroutines
See the last comment in testData for clarification

 #KT-18983 Fixed
2017-07-20 10:53:32 +03:00
Denis Zharkov
90e894b171 Use known jvm binary class for package part if possible 2017-07-20 10:53:09 +03:00
Denis Zharkov
99a10d8d63 Minor. Rename compactIfPossible -> compact
As ArrayList can always be compacted
2017-07-20 10:53:09 +03:00
Denis Zharkov
f454858bbb Optimize memory footprint for case of empty annotations in types
It seems that most of the simple types don't have any annotations,
so for that case it's worth removing the field from SimpleTypeImpl

Also introduce a NotNullSimpleType being used when replacing nullability
2017-07-20 10:53:09 +03:00
Denis Zharkov
f8a12a0ec3 Optimize JavaTypeResolver by avoiding using some language features
It's quite a hot point and using local functions with default
parameters seem to affect negatively to overall performance
(at least some of compiler benchmark have shown it)
2017-07-20 10:53:09 +03:00
Denis Zharkov
d7cee95d95 Call compactIfPossible where it's possible in BinaryJava*
It helps to avoid retaining a lot of redundant empty SmartList's
instances
2017-07-20 10:53:09 +03:00
Denis Zharkov
e2ce285ec3 Reduce memory footprint after functions substitution
Do not recreate new instances if descriptors' parts remain
effectively the same
2017-07-20 10:53:09 +03:00
Denis Zharkov
4a73fbb70a Reduce memory footprint of TypeSubstitutor
Avoid creating new instances if types remain unchanged
2017-07-20 10:53:09 +03:00
Denis Zharkov
4385ce8828 Reduce memory footprint for basic case of flexible types
The case is when we have a simple type constructor
(not array nor collection) and type is not raw:
A<T1, >..A<T1>?

Actually these types are almost equal besides of nullability,
but we create and resolve two different simple types,
they have different arguments' lists, etc.

The idea is to add NullableSimpleType subclass with delegate
to another simple type

It should help a lot both with common cases and with corner ones:
flexibles types in spark for Function22 having exponential size
because of its flexibility

 #KT-14375 Fixed
 #KT-14323 Fixed
2017-07-20 10:53:09 +03:00
Denis Zharkov
59f2ba98a6 Avoid creating SimpleType instances for default type 2017-07-20 10:53:09 +03:00
Denis Zharkov
8576054788 Use SmartList instead of SmartSet for overridden descriptors
SmartSet was used because it was the only lightweight collection
available in core, but now there is org.jetbrains.kotlin.utils.SmartList
2017-07-20 10:53:09 +03:00
Denis Zharkov
729f20ed81 Reduce memory size retained by LookupTrackerImpl
By default SmartList is used there for storing values of a multimap,
so a lot of duplicated items is stored there (file names are being
duplicated).

Even although there is a separate interner for these values,
retained memory size has been reduced for 30M when compiling `idea`
module in Kotlin project
2017-07-20 10:53:09 +03:00
Denis Zharkov
c7e6f200da Use SmartList for storing annotations in binary classes
Looks like in the most cases there are <= 1 annotations
in real declarations
2017-07-20 10:53:09 +03:00
Simon Ogorodnik
36ab31f2f7 Minor: fix test after merge 2017-07-20 02:30:34 +03:00
Toshiaki Kameyama
fe599463ac KT-18978 Intention Move to class body generates incorrect code for vararg val/var (#1188)
Intention Move to class body generates incorrect code for vararg val/var #KT-18978 Fixed
2017-07-20 01:29:56 +03:00
Dimach
a59021a25e KT-18786: J2K should move all properties to top of class
#KT-18786 fixed
2017-07-20 01:15:15 +03:00
Simon Ogorodnik
ccfcfd8721 Add benchmark for local completion and improve benchmarking 2017-07-19 21:18:58 +03:00
Dmitry Jemerov
4df6db141c Advance source stub version which wasn't advanced in 5d87276cf
#KT-19113 Fixed
2017-07-19 18:52:29 +02:00
Dmitry Petrov
891799c853 Generate 'Deprecated' annotation on invisible companion object field
Design decision: if the field for a companion object should have
non-public visibility, generate it with @Deprecated annotation in
language version 1.2.

TODO: generate it with proper visibility in 1.3 and later.

KT-11567 Companion object INSTANCE field more visible than companion object class itself
2017-07-19 17:38:17 +03:00
Dmitry Jemerov
951392005b Add options for wrapping local variable and property annotations
#KT-14950 Fixed
2017-07-19 15:03:00 +02:00
Dmitry Jemerov
050ff03b07 Implement wrapping options for enum constants
#KT-14126 Fixed
2017-07-19 15:02:59 +02:00
Dmitry Jemerov
7555bb6c3c Support formatting of 'where' clauses
#KT-14083 Fixed
2017-07-19 15:02:58 +02:00
Dmitry Jemerov
325e950bfe Reformat expression body property accessors
#KT-17394 Fixed
2017-07-19 15:02:52 +02:00
Dmitry Jemerov
4db8639bf8 Consistent name for option controlling spaces around .. 2017-07-19 15:02:50 +02:00
Dmitry Jemerov
31840fa328 Fix GradleLanguageFeatureQuickFixTest on Windows 2017-07-19 13:56:00 +02:00
Toshiaki Kameyama
366b9d1d79 KT-12195 Quickfix @JvmStatic on main() method in an object (#1192)
* Quickfix @JvmStatic on main() method in an object #KT-12195 Fixed

* Fixed #KT-12195
2017-07-19 13:37:12 +02:00
Toshiaki Kameyama
a8da79a130 KT-12504 Intention to make open class with only private constructors sealed (#1193)
* Intention to make open class with only private constructors sealed #KT-12504 Fixed

* Fixed #KT-12504
2017-07-19 13:36:36 +02:00
Nikolay Krasko
dd2a87dbf7 Rewrite test class to make it work on Windows
Stop using dummy file and assert result with assertEqualsToFile().

Previous version didn't work on Windows because of `\r`.
2017-07-19 13:25:17 +03:00
Nikolay Krasko
4e76975a52 Force OOB in accessors for properties without explicit type (KT-19062)
#KT-19062 Fixed
2017-07-19 12:45:06 +03:00
Nikolay Krasko
bcbff98382 Check OOB stays the same for string in super type constructor call 2017-07-19 12:45:06 +03:00
Pavel V. Talanov
41276c950b Update CodegenTestCase after rebasing on latest changes 2017-07-19 12:29:27 +03:00
Pavel V. Talanov
5faad493b4 Catch and report exceptions from DependenciesResolver 2017-07-19 12:29:25 +03:00
Pavel V. Talanov
eb5be038fa ScriptDependenciesUpdater: compute script contents synchronously 2017-07-19 12:29:22 +03:00
Pavel V. Talanov
9eb8cec5cf ScriptDependenciesUpdater: set job to null after processing result
Fix inconsistency introduced after extracting ScriptDependenciesUpdater
2017-07-19 12:29:20 +03:00
Pavel V. Talanov
537b1689b7 DependenciesCache: remove ad-hoc ScriptDependencies comparison 2017-07-19 12:29:17 +03:00
Pavel V. Talanov
b1ac451959 Make sure template classpath is always among script dependencies 2017-07-19 12:29:15 +03:00
Pavel V. Talanov
f84cc7fb5b Offload legacy dependency resolver work to a separate thread pool
This is mainly to improve experience for kdsl users before gradle migrates to new API
2017-07-19 12:29:12 +03:00
Pavel V. Talanov
bc399444ab Fix creating DependenciesResolver with default arguments 2017-07-19 12:29:09 +03:00
Pavel V. Talanov
7aee51fd77 Refactor ScriptDependenciesUpdater: improve readability a bit 2017-07-19 12:29:07 +03:00
Pavel V. Talanov
c0e08c61ee Minor: extract ScriptContentLoader::getEnvironment 2017-07-19 12:29:04 +03:00
Pavel V. Talanov
42629d6f8d ScriptDependenciesUpdater: use Job explicitly instead of futures
Cancel jobs without interrupting
2017-07-19 12:29:02 +03:00
Pavel V. Talanov
999c3c5e76 Rename services related to script dependencies
KotlinScriptConfigurationManager -> ScriptDependenciesManager
KotlinScriptExternalImportsProvider -> ScriptDependenciesProvider
2017-07-19 12:28:59 +03:00
Pavel V. Talanov
96db16a988 ScriptDependenciesUpdater, minor: improve isLastSentRequestCheck 2017-07-19 12:28:56 +03:00
Pavel V. Talanov
aacb9a437a Rename: dependenciesClasspath -> templateClasspath
Clearer distinction from additionalResolverClasspath
2017-07-19 12:28:54 +03:00
Pavel V. Talanov
96d8f685e9 Refactor KotlinScriptConfigurationManager: extract parts
Introduce ScriptDependenciesUpdater, DependenciesCache and ScriptContentLoader
2017-07-19 12:28:51 +03:00
Pavel V. Talanov
1b42095dc1 Support @AcceptedAnnotations for different kinds of resolvers 2017-07-19 12:28:49 +03:00
Pavel V. Talanov
1c412b4068 AsyncDependenciesResolver: provide implementation for sync resolve 2017-07-19 12:28:46 +03:00
Pavel V. Talanov
008c27d547 Compiler build depends on kotlinx-coroutines-core 2017-07-19 12:28:43 +03:00
Pavel V. Talanov
ee70a64e1c Minor, template providers: don't create classloader for empty classpath 2017-07-19 12:28:41 +03:00
Pavel V. Talanov
beb28a1c7d Gradle Kotlin DSL uses compiler-embdeddable jar when loading resolver 2017-07-19 12:28:38 +03:00
Pavel V. Talanov
5c18ab750b GradleScriptTemplateProvider: avoid duplicating template loading code 2017-07-19 12:28:36 +03:00
Pavel V. Talanov
6c3ce7adc1 ScriptTemplatesProvider: refactor dependency loading
Change dependenciesClasspath is of type List<File>
Add additionalResolverClasspath
2017-07-19 12:28:33 +03:00
Pavel V. Talanov
a77cd0ab09 Catch errors when instantiating script templates
If we throw from this code IDE becomes unusable

 #KT-18945 Fixed
2017-07-19 12:28:31 +03:00
Pavel V. Talanov
8ac17400ae ScriptDependenciesFileAttribute: fix TODOs 2017-07-19 12:28:28 +03:00
Pavel V. Talanov
75220e145b Minor: suppress deprecation warning 2017-07-19 12:28:26 +03:00
Pavel V. Talanov
cf57e5a7a1 Script templates: search for parameterless constructor of resolver 2017-07-19 12:28:23 +03:00
Pavel V. Talanov
10e14103b6 Propagate reports from script dependency resolver
Compiler: show as compiler messages
IDE: annotate code in a separate highlighting pass
2017-07-19 12:28:20 +03:00
Pavel V. Talanov
96c2a589c0 Support legacy resolver interface 2017-07-19 12:28:18 +03:00
Pavel V. Talanov
65dba3615c Update project code to use new script.runtime APIs 2017-07-19 12:28:15 +03:00
Pavel V. Talanov
375b058a28 Add coroutines-jdk8 to project 2017-07-19 12:28:13 +03:00
Pavel V. Talanov
1012a24afc Refactor: move KotlinScriptExternalImportsProviderImpl to 'cli' module 2017-07-19 12:28:10 +03:00
Pavel V. Talanov
b6a7d831bf Script IDE API: remove <TF: Any> 2017-07-19 12:28:08 +03:00
Pavel V. Talanov
581176fa90 AbstractScriptConfigurationTest: adapt to changes in API 2017-07-19 12:28:05 +03:00
Pavel V. Talanov
788eaf8a18 Refactor getting dependencies for script files API
Deprecate KotlinScriptDefinition#getDependenciesFor
Expose dependencyResolver as a property
KotlinScriptExternalImportsProvider is the component clients should be asking for dependencies
2017-07-19 12:28:02 +03:00
Pavel V. Talanov
ff391628de KSCM: fix wrong update on null return from Template.getDependenciesFor 2017-07-19 12:28:00 +03:00
Pavel V. Talanov
1834721880 KSCM: persist script dependencies between idea launches 2017-07-19 12:27:55 +03:00
Pavel V. Talanov
930d502b12 KSCM: rework async requests 2017-07-19 12:27:53 +03:00
Pavel V. Talanov
3c511f3f40 KSCM: temporary workaround gradle returning results in unstable order 2017-07-19 12:27:50 +03:00
Pavel V. Talanov
fb0e0e3767 Introduce ScriptDependenciesFileAttribute to persist script dependencies 2017-07-19 12:27:48 +03:00
Pavel V. Talanov
a2aeda7b2c Support async script dependency updates for annotation based templates
Do not try to cache dependencies for every script on startup
Schedule cache updates upon request as opposed to updating them synchronously
2017-07-19 12:27:45 +03:00
Pavel V. Talanov
b7fc909821 Split compiler and ide specific parts of script dependency caching
Move all caching logic to ide specific KotlinScriptConfigurationManager
Clean up apis
Remove logging when updating caches
2017-07-19 12:27:43 +03:00
Anton Bannykh
e43a145614 fixup: updated EXPECTED_REACHABLE_NODES 2017-07-19 12:24:09 +03:00
Anton Bannykh
6ed7eaf546 JS tests: changes to kotlin.test + the way compiler tests are generated. 2017-07-19 12:24:09 +03:00
Alexey Sedunov
eda747c0bf Minor: Fix tests 2017-07-19 11:34:30 +03:00
Roman Elizarov
f2b5f37b22 Support inline suspend functions built with compiler version less than 1.1.4/1.2-M1
The error message is removed and is replaced with a code that adapts
inline suspend functions produced by the old compiler with the
suspension markers that new compiler expects.
2017-07-19 08:59:55 +03:00
Roman Elizarov
9f0810f723 Pull implementations up from AbstractCoroutineContextElemenet
Fixes KT-18671
2017-07-19 08:59:43 +03:00
Alexander Udalov
c9b14c5a45 Reduce classpath for class loader in CodegenTestCase
There's no point in adding JDK (mock or full) roots to it, as well as
stdlib/reflect/test (they are loaded by the parent class loader, created
in ForTestCompileRuntime)
2017-07-18 20:10:07 +03:00
Alexander Udalov
743278d456 Fix ReplInterpreter on Java 9 2017-07-18 20:10:05 +03:00
Alexander Udalov
aa53fa7e15 Fix execution of simple .kts scripts on Java 9 2017-07-18 20:10:05 +03:00
Alexander Udalov
bc2c958a2e Remove unused class GenericRepl 2017-07-18 20:10:05 +03:00
Alexander Udalov
36001ff931 Do not allow to access compiler internals in .kts scripts
Set parent class loader to null explicitly instead of the system class
loader
2017-07-18 20:10:05 +03:00
Alexander Udalov
d1603c4329 Minor, move deserializeToDescriptor to package kotlin.reflect.jvm.internal
To prevent binary-compatibility-validator from reporting it as a public
API; that happens because the signature is different after the
gradle-shadow-plugin is applied
2017-07-18 20:09:24 +03:00
Yan Zhulanow
00225b3de3 Use compiling evaluator only if there is non-inline lambda or a loop in the bytecode 2017-07-18 18:22:30 +03:00
Yan Zhulanow
a6925e0d0f Minor: Fixes after review 2017-07-18 18:22:29 +03:00
Yan Zhulanow
904b693571 Pass byte array more efficiently
Filling byte[] values is especially slow on Android (>3000ms to fill a byte[3000] on emulator).
2017-07-18 18:22:28 +03:00
Yan Zhulanow
069579fd79 Debugger: Disable code interpreting by default in evaluator
Provide the compiled bytecode to debugger instead of interpreting the expression by default.
This significantly increases evaluation speed in numerous cases, e.g. `(1..10000).map { it.toString() }.count()`.
Leave interpreter mode as a fallback.

Android does not provide decent in-memory class loading support.
Moreover, we need to run dex on the compiled classes, and it required significant time.
So for now compiling evaluator for Android is available only in Android O, and only if there're any local classes or non-inline lambdas (evaluator didn't work for them before so we may consider this change as an improvement).
2017-07-18 18:22:28 +03:00
Yan Zhulanow
4851a83a83 Android Extensions: put new functionality under the flag 2017-07-18 18:10:30 +03:00
Yan Zhulanow
77eafb9716 Kapt: Map kaptGenerateStubsKotlin task classpath properly, ensure the destination for compileKotlin isn't in it (KT-18799) 2017-07-18 18:10:29 +03:00
Yan Zhulanow
83f9835e00 Android Exensions: Add kotlin-android-extensions-runtime dependency automatically in Gradle plugin 2017-07-18 18:10:28 +03:00
Yan Zhulanow
b303fa9caa Android Extensions: Fixes after review 2017-07-18 18:10:27 +03:00
Yan Zhulanow
7b238e0b21 Android Extensions: Add SparseArray implementation for the View cache (KT-18250) 2017-07-18 18:10:26 +03:00
Yan Zhulanow
fbfd51e97e Minor: Group plugin modules 2017-07-18 18:10:25 +03:00
Yan Zhulanow
820f914d35 Remove obsolete kapt2 implementation 2017-07-18 18:10:24 +03:00
Yan Zhulanow
423a09e46a Android Extensions: Support LayoutContainer in code generation 2017-07-18 18:10:23 +03:00
Yan Zhulanow
a69f9729e0 Android Extensions: Use Activity and Fragment supertypes in INVOKE_VIRTUAL calls instead of the user implementation class names 2017-07-18 18:10:22 +03:00
Yan Zhulanow
d4b4bc71ee Android Extensions: Support @ContainerOptions in compiler plugin 2017-07-18 18:10:21 +03:00
Yan Zhulanow
6e1dd08fbb Android Extensions: Add runtime library with LayoutContainer and its options 2017-07-18 18:10:20 +03:00
Yan Zhulanow
1a1db5a6f1 Android Extensions: Support cache in custom Views 2017-07-18 18:10:19 +03:00
Yan Zhulanow
c9cd1a4d75 Minor: Android Extensions compiler plugin refactoring 2017-07-18 18:10:18 +03:00
Yan Zhulanow
0494862ce5 Minor: Move Android Extensions compiler plugin tests to some other package 2017-07-18 18:10:17 +03:00
Yan Zhulanow
303b246a49 Minor: Move AndroidExtensionsReportSubmitter to other KAE files 2017-07-18 18:10:16 +03:00
Yan Zhulanow
e037cafe18 Use descriptor modality in IDE inspections/intentions
This fixes KT-18160, KT-18194, KT-18195, KT-18197 ~
2017-07-18 18:10:15 +03:00
Yan Zhulanow
942fa7719a Android Extensions: Add synthetic property highlighting 2017-07-18 18:08:33 +03:00
Yan Zhulanow
f7786a42ab Android Extensions: Show warning on a dot-call of a reference which is missing in some configurations (KT-18012)
When more than one layout configuration is available, a particular resource (view or fragment) may be absent in some of them.
We should show a warning on such resource reference calls as the call may lead to NPE.
2017-07-18 18:08:32 +03:00
Yan Zhulanow
f4acf404ca Android Extensions: Support Android variants and library dependencies (KT-14086, KT-16934) 2017-07-18 18:08:31 +03:00
Yan Zhulanow
8e9a62d553 Kapt: Add gradle warnings for Android projects
1. When the old kapt (aka kapt1) is used
2. (for Android projects) When Kotlin plugin is applied but annotationProcessor (Java-only) dependencies are found
2017-07-18 18:08:29 +03:00
Toshiaki Kameyama
865f9d4c7e Wrong caption "Change to property access" for Quick Fix to convert class instantiation to object reference #KT-13870 Fixed (#1189) 2017-07-18 15:47:43 +02:00
Mikhail Glukhikh
987c7f5be8 Add "unnecessary local variable" inspection #KT-15958 Fixed 2017-07-18 16:37:47 +03:00
Dmitry Neverov
9d06a80519 Do not report "property can be private" on JvmField properties
So #KT-18970 Fixed
2017-07-18 15:48:10 +03:00
Nikolay Krasko
5281602381 Don't ignore filters in smart step over for inline calls 2017-07-18 14:39:55 +03:00
Nikolay Krasko
f664ffb06b Check correspondent call on end token for better step over (KT-18949)
#KT-18949 Fixed
2017-07-18 14:39:54 +03:00
Nikolay Krasko
d282f14eac Don't add double linenumber when return expression is absent (KT-18949)
#KT-18949 Fixed
2017-07-18 14:39:54 +03:00
Nikolay Krasko
a41c9d2476 Avoid state machine build for suspend function with single inline call
#KT-18949 Fixed
2017-07-18 14:39:54 +03:00
Nikolay Krasko
ce4f923ba0 Replace return with nop to avoid merging line instructions (KT-18949)
Dex ignores subsequent line numbers for same instructions and interprets
instruction after inline as if they were inlined. This makes debugger
behaves as if there's nowhere to stop on line with breakpoint.

This also makes stepping through inline function consistent with
non-inline analog. In both context debugger now stops on '}'.

 #KT-18949 Fixed
 #KT-17120 Fixed
2017-07-18 14:39:54 +03:00
Nikolay Krasko
fc685aa03f Refactoring: extract common part to function 2017-07-18 14:39:54 +03:00
Nikolay Krasko
179ec84684 Refactoring: mark getTopmostElementAtOffset() as not-null 2017-07-18 14:39:54 +03:00
Mikhail Glukhikh
c0e1b3ef2d CFG: fix label binding for last instruction of finally block
So #KT-18698 Fixed
2017-07-18 14:37:13 +03:00
Mikhail Glukhikh
ab0e734e7d PseudocodeLabel: add slightly better exception diagnostics 2017-07-18 14:36:42 +03:00
Mikhail Glukhikh
9a5b5393f5 Code cleanup: CFG (several inspections applied) 2017-07-18 14:36:18 +03:00
Mikhail Glukhikh
43f9035d07 Minor test fix 2017-07-18 13:51:27 +03:00
Toshiaki Kameyama
f8cf0f2ab9 Misleading quick fix message for an 'open' modifier on an interface member #KT-18738 Fixed 2017-07-18 18:59:22 +09:00
Alexey Sedunov
d2dbc47454 Create from Usage: Remove extra space before type parameters list
#KT-16352 Fixed
2017-07-17 16:09:57 +03:00
Alexey Sedunov
e98af7bfc1 Create Class from Usage: Use type parameter bounds as supertypes
#KT-15242 Fixed
2017-07-17 16:09:55 +03:00
Alexey Sedunov
95769dc9d3 Create from Usage: Make property lateinit where possible
#KT-17651 Fixed
2017-07-17 16:09:54 +03:00
Alexey Sedunov
e9bf1d2ab8 Create from Usage: Add test for KT-17537
#KT-17537 Fixed
2017-07-17 16:09:53 +03:00
Alexey Sedunov
0365d3a3d6 Create from Usage: Do not create type parameter by constuctor reference
#KT-17353 Fixed
2017-07-17 16:09:52 +03:00
Alexey Sedunov
2e76a76088 Control Flow: Fix CFG usage info for double-colon expressions
#KT-12551 Fixed
 #KT-17092 Fixed
2017-07-17 16:09:51 +03:00
Alexey Sedunov
216b28ec55 Implement Members: Do not generate 'header' keyword
#KT-18466 Fixed
2017-07-17 16:09:50 +03:00
Alexey Sedunov
26d6088c82 Create from Usage: Infer expected type for lambda body
#KT-18186 Fixed
2017-07-17 16:09:49 +03:00
Alexey Sedunov
b48feb257c Create from Usage: Create data class property from destructuring entry
#KT-18540 Fixed
2017-07-17 16:09:48 +03:00
Simon Ogorodnik
a212a1bf72 Put all internal actions under Tools | Kotlin | Internal group 2017-07-17 16:03:10 +03:00
Simon Ogorodnik
4cdc3fdde9 KT-14606: Never compute decompiled text in BasicLookupElementFactory
#KT-14606 fixed
2017-07-17 16:03:07 +03:00
Simon Ogorodnik
6036c95511 Prevent KotlinDecompiledFileViewProvider from reading vfile when possible 2017-07-17 16:03:04 +03:00
Simon Ogorodnik
bc5872dd8f Add completion benchmark to check completion speed 2017-07-17 16:03:02 +03:00
Nikolay Krasko
dfef1f4921 Add reference equality shortcut for equals() in light members 2017-07-17 14:50:59 +03:00
Nikolay Krasko
44ed903303 Implement equivalence of light members by origin when possible
Previous implementation worked through equality that used equality
of method stubs (see LightMemberOriginForCompiledMethod). But method
stubs for compiled element can be recreated when caches are outdated,
including weak reference cleaning (see ClsJavaStubByVirtualFileCache).

This could cause misbehave of find usages when java reference has an
outdated version of light element in resolution cache.
2017-07-17 14:50:59 +03:00
Toshiaki Kameyama
fda097fc3b Correct "before" sample in description for intention Convert to enum class #KT-18722 Fixed (#1196) 2017-07-17 13:03:15 +02:00
Dmitry Jemerov
6baa8614e6 Fix JS tests in AbstractConfigureKotlinTest 2017-07-17 12:09:11 +02:00
Dmitry Jemerov
2c2b64d44a AbstractConfigureKotlinTest: J2K 2017-07-17 12:09:10 +02:00
Dmitry Jemerov
4198a5c3ec AbstractConfigureKotlinTest: rename to .kt 2017-07-17 12:09:09 +02:00
Dmitry Jemerov
0e6c9a96c7 Specify library kind when configuring library in tests 2017-07-17 12:09:04 +02:00
Dmitry Jemerov
060b8e0025 ConfigLibraryUtil: J2K 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
921db30c90 ConfigLibraryUtil: rename to .kt 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
0fa09adf17 Provide library kind for common libraries; get rid of autodetection 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
c7e85ea28f Better encapsulate JS library detection 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
b8d453eec3 Set library kind when importing projects from Maven 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
608f5892f9 Set library kind when importing projects from Gradle 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
902fe1f5ce Implement explicit library kind for JS libraries, don't autodetect 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
1367e6f303 Get library versions directly, not through LibraryPresentationProvider 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
2d1ac69986 JSLibraryStdDescription: J2K 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
5f3366d60b JSLibraryStdDescription: J2K 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
c185730846 KotlinJsModuleConfigurator: J2K 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
ffb3e2fcbc KotlinJsModuleConfigurator: rename to .kt 2017-07-17 11:58:57 +02:00
Dmitry Jemerov
1f6788ac31 Fix CodeConformanceTest on Windows 2017-07-17 11:57:03 +02:00
Nikolay Krasko
b3e9dfcea9 Minor: fix weak warnings and formatting in KotlinReferencesSearcher.kt 2017-07-17 12:25:06 +03:00
Nikolay Krasko
d93e0adc4f Do not wrap to light elements if Kotlin search is requested (KT-19054)
#KT-19054 Fixed
2017-07-17 12:25:06 +03:00
Dmitry Petrov
8c7352e668 Generate constant "" for effectively empty string 2017-07-17 09:18:41 +03:00
Knize
389c7d03b7 KT-6676 Show enum ordinal in quickdoc (#1165)
KT-6676: Show enum ordinal in quickdoc

 #KT-6676 fixed
2017-07-14 22:28:16 +03:00
Simon Ogorodnik
cc8933c82b KT-17074: Make completion respect DslMarker's
#KT-17074 fixed
2017-07-14 21:06:43 +03:00
Alexander Udalov
3c04ca4397 Update KotlinVersion.CURRENT to 1.1.5 2017-07-14 21:03:06 +03:00
Alexander Udalov
2611c7de7e Restore anonymous classes for local delegate metadatas in inline functions
The problem is that now that the local delegated property metadata is in
the $$delegatedProperties array of the containing class, the access to
it from code calling an inline function with a local delegated property
is illegal.

Currently it seems to be a lot of work to support this rather rare case
properly (see the comment in ExpressionCodegen.getVariableMetadataValue)
so we postpone it and return the old behavior of using the anonymous
KProperty subclass for metadata
2017-07-14 15:13:12 +03:00
Alexander Udalov
616d575fb6 Support reflection for local delegated properties
#KT-15222 Fixed
2017-07-14 15:13:12 +03:00
Alexander Udalov
c444c4d10b Ignore $$delegatedProperties in light analysis mode tests
For tests with local delegated properties, this field is generated in
the full mode, but is not generated in the lite mode because local
variables are not analyzed properly in the lite mode
2017-07-14 15:04:05 +03:00
Alexander Udalov
db27a885f1 Rework property metadata generation for local delegated properties
Instead of generating an anonymous class for each delegated local
variable, store metadatas in the $$delegatedProperties array of the
containing class, as is done for member properties
2017-07-14 15:04:05 +03:00
Alexander Udalov
9344f7f42f Remove unused and obsolete code in JVM backend 2017-07-14 15:04:05 +03:00
Alexander Udalov
728de91140 Refactor generation of metadata for delegated properties
In CodegenAnnotatingVisitor, store all delegated properties whose
metadata should be generated in each class (identified by ASM Type).
Use the stored information later, both in the $$delegatedProperties
array generation and in the access to it from property's accessor
methods, instead of an heuristical indexOfDelegatedProperty()
2017-07-14 15:04:04 +03:00
Alexander Udalov
b97589b33e Remove CodegenBinding.LOCAL_VARIABLE_DELEGATE
Calculate this value at call sites explicitly instead
2017-07-14 15:04:04 +03:00
Alexander Udalov
66ea288be7 Minor, extract fakeDescriptorsForReferences.kt 2017-07-14 15:04:04 +03:00
Stanislav Erokhin
9e98c11114 [NI] Minor. Change return type substitute function to not null 2017-07-14 12:43:09 +03:00
Stanislav Erokhin
2602216039 [NI] Use NewTypeSubstitutor when create descriptor with fresh variables. 2017-07-14 12:43:09 +03:00
Stanislav Erokhin
652676dc71 [NI] Introduce transactions for constraint system.
This will be used for callable reference resolution.
2017-07-14 12:43:09 +03:00
Stanislav Erokhin
cb494c46d7 [NI] Add initial constraint to IncorporationConstraintPosition 2017-07-14 12:43:08 +03:00
Stanislav Erokhin
c767545d4c Minor. Remove unused CandidateWithBoundDispatchReceiver#copy 2017-07-14 12:43:08 +03:00
Stanislav Erokhin
ac06060260 [NI] Minor. Drop unused CommonSupertypeCalculator 2017-07-14 12:43:08 +03:00
Stanislav Erokhin
0404fbc092 [NI] Minor. Rename LambdaAnalyzer to KotlinResolutionCallbacks 2017-07-14 12:43:08 +03:00
Dmitry Petrov
178e3e2c98 [NI] Update argument types on call completion using nested calls resolution 2017-07-14 12:43:07 +03:00
Dmitry Petrov
4448637727 [NI] Support calling abstract class constructor in delegating call 2017-07-14 12:43:07 +03:00
Dmitry Petrov
549e8ba668 [NI] Use ALWAYS_SUITABLE_RECEIVER when no receiver is available
(as in "old" resolution & inference)

This fixes issues with Java static members access.
2017-07-14 12:43:07 +03:00
Dmitry Petrov
2bdeef7970 [NI] Postprocess lambda result expressions on call completion
Should update type to denotable, e.g.,
IntegerValueType(x) to proper numeric type.

TODO extract common code into some ValueArgumentPostprocessor
2017-07-14 12:43:07 +03:00
Dmitry Petrov
1d6ed4ef8e [NI] Update lambda result types.
When completing calls, update return types for functional descriptors
for lambdas using type inference results.

Add toString to some Call subclasses (for debugging purposes).
2017-07-14 12:43:06 +03:00
Dmitry Petrov
2bf252afe6 [NI] Introduce lambda result dependency edges
Given a lambda result type R_L with constraint R_L <: T,
for each constituent type variable V in T with variance matching
approximation direction for V, consider a dependency edge V -> R
(lambda-result-dependency).

E.g., given a constraint:
    R <: Out<V>
where V is approximated down (to sub-type).
After R is fixed, we obtain constraint
    Out<T> <: Out<V>
which is incorporated as
    T <: V
which is a relevant constraint for V.
2017-07-14 12:43:06 +03:00
Dmitry Petrov
13e8720ddc [NI] Keep track of fresh type variables created for particular call candidate
Otherwise we can't obtain inferred type arguments for the call,
which is required for reification.
2017-07-14 12:43:06 +03:00
Dmitry Petrov
eb7e9196b5 [NI] Fix some argument mapping problems
1. Value arguments for the resolved call are indexed with resulting
descriptor value parameters (which can be substituted).

2. Simple argument can be a single vararg element if the corresponding
value parameter is a vararg parameter.

3. Resulting descriptor should be approximated to super-type.
This doesn't affect type inference, but the JVM BE expects types with
proper classifiers.
2017-07-14 12:43:06 +03:00
Stanislav Erokhin
0c79949cf1 [NI] Implement NewTypeSubstitutor 2017-07-14 12:43:05 +03:00
Stanislav Erokhin
ff8a57dc26 [NI] Implement New CommonSuperTypeCalculation 2017-07-14 12:43:05 +03:00
Stanislav Erokhin
6aac67aa7e [NI] Approximate captured types when set them into variable.
Also do not store type with captured type inside possible types.
It is hack for now, but without it captured types can flow to
resolution and exception will be thrown.
2017-07-14 12:43:05 +03:00
Stanislav Erokhin
397103f9d0 [NI] Fix smart cast for expression with captured input type. 2017-07-14 12:43:05 +03:00
Stanislav Erokhin
73cc1fdd9c [NI] Resolve type variable to Nothing for TO_SUBTYPE direction. 2017-07-14 12:43:04 +03:00
Stanislav Erokhin
6e24b0f89d [NI] Approximate captured types when we resolve type variable TO_SUPER. 2017-07-14 12:43:04 +03:00
Stanislav Erokhin
53caa84db9 [NI] Add constrains even we try add constraint like TypeVariable <: CapturedType from subtyping.
If such captured type has lower type, then from TypeVariable <: lowerType => TypeVariable <: CapturedType.
2017-07-14 12:43:04 +03:00
Stanislav Erokhin
657c332a1f [NI] Do not run "or" branches for constraint subtyping.
We should never do that, because otherwise we can get unexpected result.
  Example for input constraint: C(in String) <: T.
  If we run usual subtyping algorithm, then we get 2 constraints:
  C(in String) <: T and T <: String.
  Of course such system has contradiction.
2017-07-14 12:43:04 +03:00
Stanislav Erokhin
0fadf0bf70 [NI] Approximate captured types before type variable fixation.
We prefer denotable types when we solve constraint system.
I.e. if for T we have not equality constraint with captured type we can approximate captured type to denotable type.
2017-07-14 12:43:03 +03:00
Stanislav Erokhin
b4bf534d29 [NI] Capture from supertypes of type parameter.
This works by accident in OI, so this should be supported by new inference.
2017-07-14 12:43:03 +03:00
Stanislav Erokhin
c4ddc7a3a6 [NI] Store stub resolved call to trace because some clients read this before all calls are completed.
This is bad idea, but this is how it works in old inference.
Now we just save old behaviour.
Future plan: fix checks where we get unfinished resolved calls.
2017-07-14 12:43:03 +03:00
Stanislav Erokhin
78f8d29a4c [NI] Fix find maximally specific for NI. 2017-07-14 12:43:03 +03:00
Dmitry Petrov
d67b51e91a [NI] Support wrong number of type arguments and integer constants.
- report WRONG_NUMBER_OF_TYPE_ARGUMENTS
- make integral types work again: IntegerValueType is represented as {Int & Byte & Short & Long} in the constraint system
2017-07-14 12:43:02 +03:00
Dmitry Petrov
f5c59b1343 [NI] Report special error message on constant expression type mismatch. 2017-07-14 12:43:02 +03:00
Dmitry Petrov
5afd3e72d6 [NI] Report diagnostic on abstract class instantiation. 2017-07-14 12:43:02 +03:00
Stanislav Erokhin
b012681a53 [NI] New inference -- initial commit. 2017-07-14 12:43:02 +03:00
Dmitry Petrov
036090be91 Support intersection type in TypeUtils.contains(...) 2017-07-14 12:43:01 +03:00
Stanislav Erokhin
e8501c7d54 Add method replaceType for ReceiverValue.
This method will used for capturing from expressions before call resolution.
2017-07-14 12:43:01 +03:00
Nikolay Krasko
1dcdb72a49 Process UastContext service absence (EA-100670) 2017-07-14 12:39:13 +03:00
Dmitry Jemerov
448dba3f78 License-related cleanup 2017-07-14 11:09:45 +02:00
Ilya Chernikov
84a812df19 Drop forced in-process compilation (as interface compatibility is resolved) 2017-07-13 15:45:34 +02:00
Dmitry Jemerov
9b37e76b14 Don't trigger update check when an in-memory file is modified
#KT-18954 Fixed
2017-07-13 12:50:15 +02:00
Mikhail Zarechenskiy
2d3ce89afc Use only completed arguments of special call 2017-07-13 12:26:03 +03:00
Dmitry Petrov
a687dea898 Introduce special IrDeclarationOrigin's for for-loop variables
FOR_LOOP_ITERATOR
 - temporary variable for for-loop iterator

FOR_LOOP_VARIABLE
 - `x` in `for (x in xs)`

FOR_LOOP_IMPLICIT_VARIABLE
 - temporary variable for for-loop with destructuring, e.g.:
   for ((x, y) in xys)
   =>
   for (tmp in xys) {
     val (x, y) = tmp
   }
2017-07-13 10:59:51 +03:00
Andrius Semionovas
1cab0d09ab KT-18979 Add val to proper place for 'Add val/var' intent 2017-07-13 01:20:24 +03:00
Alexander Udalov
f01de3a935 Minor, move lateinit tests into a subdirectory 2017-07-12 18:59:02 +03:00
Alexander Udalov
b2b492447f Maven plugin: initial support for Java 9 modules 2017-07-12 18:58:36 +03:00
Alexander Udalov
848edc14cb Maven plugin: fix warnings, update copyrights 2017-07-12 18:58:35 +03:00
Alexander Udalov
1d46070bd5 Minor, remove unneeded codegen test
This test is already present in compiler/testData/cli/jvm/
2017-07-12 18:58:35 +03:00
Mikhael Bogdanov
b2a7fb9534 Update ChangeLog.md for 1.1.4-EAP-11 2017-07-12 16:33:25 +02:00
Mikhael Bogdanov
b15cfeb0a0 Add 1.1.3-2 changes 2017-07-12 16:33:25 +02:00
Mikhael Bogdanov
ef003db020 Update ChangeLog.md for 1.1.3 2017-07-12 16:33:25 +02:00
baratynskiy
0b6ef5f291 Make idea-full exported in tests-common module because kapt3 tests use KotlinTestUtils.assertEqualsToFile which uses Editor defined in idea-full 2017-07-12 17:25:32 +03:00
baratynskiy
a288b8d318 Add jsr305.jar to intellij-core because guava-19.0 jar depends on Nullable defined in jsr305.jar 2017-07-12 17:25:32 +03:00
Anton Bannykh
0935ed41d4 JS: return exit code from the NodeJs kotlinc-js wrapper 2017-07-12 17:19:59 +03:00
Dmitry Petrov
da404de51e Add comment regarding testData generation to RangeValues.kt 2017-07-12 16:23:36 +03:00
Dmitry Petrov
2849e19af5 Add test for indices.reversed() 2017-07-12 15:56:29 +03:00
Dmitry Petrov
6a673a03e4 Generate test data for in-expression tests, fix bug with indices 2017-07-12 15:56:29 +03:00
Igor Chevdar
890c6a9983 Regenerated box tests 2017-07-12 15:12:34 +03:00
Igor Chevdar
fd380f7545 Split up test on map access onto two tests: stdlib & compiler box test 2017-07-12 15:12:33 +03:00
Mikhail Zarechenskiy
14890890b1 Minor, get rid of unchecked cast 2017-07-12 14:37:27 +03:00
Mikhail Zarechenskiy
ee173077c0 Simplify diagnostic when there are wrong number of type arguments
#KT-12767 Fixed
2017-07-12 14:37:27 +03:00
Mikhail Zarechenskiy
e82c909f75 Use more specific status to report diagnostics
#KT-12737 Fixed
2017-07-12 14:37:26 +03:00
Mikhail Zarechenskiy
178bb900b4 Introduce inapplicable wrong receiver status to improve diagnostics
#KT-10754 Fixed
2017-07-12 14:37:26 +03:00
Mikhail Zarechenskiy
79ee8f452c Add test for obsolete issue
#KT-12688 Obsolete
2017-07-12 14:37:26 +03:00
Toshiaki Kameyama
848f7423ee Do not report "can be private" on properties of private class
So #KT-18822 Fixed
2017-07-12 10:35:10 +03:00
Dmitry Petrov
f4d63158cc Take into account JvmName annotation when generating accessors
#KT-17444 Fixed Target versions 1.1.5
2017-07-12 09:37:16 +03:00
Dmitry Petrov
efb6756cbc Initialize property metadata array before class body generation
Initialization of companion object members (e.g., delegate properties
using provideDelegate convention) can depend on property metadata array,
which in turn can be initialized before other class members.

 #KT-18902 Fixed Target versions 1.1.5
2017-07-12 09:37:16 +03:00
Dmitry Petrov
8a9707c140 Generate proper initialization for possibly nullable SAM wrapper
#KT-18916 Fixed Target versions 1.1.5
2017-07-12 09:37:16 +03:00
Yan Zhulanow
b99007961f NoArg: Do not invoke initializers by default. Require "invokeInitializers" option to be set explicitly (KT-18667, KT-18668) 2017-07-12 00:17:24 +03:00
Yan Zhulanow
a983137978 Kapt: Handle parameter with Java names clashing with Java keywords properly (KT-18377) 2017-07-12 00:17:23 +03:00
Alexey Tsvetkov
e56e3d78c8 Use ANSI escape codes only with CLI tools
Before this change jansi was used by the compiler,
unless "kotlin.colors.enabled" is not set to false.
This caused multiple issues in different build systems,
where newer or older version of jansi could crash the JVM
since it uses native code.

The following short term solutions were discussed:
* Set "kotlin.colors.enabled" to false where jansi is not needed
(basically in any build system).
* Set "kotlin.colors.enabled" to true where jansi is needed,
and use it only when the system property is set to true.

Escaped codes are only needed in CLI tools (kotlinc, REPL),
so the second solution is preferred (less places to set the property).

     #KT-17031 fixed
     #KT-18874 fixed
     #KT-18927 fixed
2017-07-11 21:03:11 +03:00
Kirill Rakhman
cb19a86c44 Add "simplify if with constant" inspection #KT-17919 Fixed 2017-07-11 20:00:33 +03:00
Alexey Andreev
7634673213 Fix module re-importing when inlining functions in JS BE
When inliner reads function's body from other module, it performs
substitution _ -> moduleAlias. However, local alias can't be used
for this purpose, since call site can be in public inline function
itself, so the correct substitution would be -> _.$$imports$$.alias
2017-07-11 19:27:08 +03:00
Mikhail Glukhikh
cc4e55b829 Add groupPath/Name, change displayName for null checks -> safe call
Related to KT-14799
2017-07-11 19:25:38 +03:00
Dimach
7407083624 Add inspection to simplify successive null checks #KT-14799 Fixed 2017-07-11 18:47:26 +03:00
Ilya Chernikov
fc12f37105 Rolling back commits related to Unit -> Void? confersion in RMI interface
since it breaks the compatibility and doesn't actually help - the problem
with NoClassDef Unit is apparently elsewhere.
2017-07-11 15:06:38 +02:00
Ilya Chernikov
3da5ba4efe Switch to the newer gradle plugin, fix jansi problem, in-process compiling in gradle parts
Switching to in-process to avoid compilation warnings caused by introduced
daemon interface changes.
Switching to the gradle plugin 1.1.3 causes jansi incompatibility in
in-process compilation mode, so disabling jansi usage to avoid it.
2017-07-11 15:06:37 +02:00
Mikhail Glukhikh
0ca5c0fcc6 Refactoring (clone remove) of LiftAssignmentOutOfTryFix
Related to KT-18830
2017-07-11 15:28:45 +03:00
Toshiaki Kameyama
8cc9330e63 Introduce "Lift return out of try" intention #KT-18830 Fixed 2017-07-11 15:14:30 +03:00
Toshiaki Kameyama
8f9b680fc6 Support generic type parameters in 'Specify return type explicitly'
So #KT-18074 Fixed
2017-07-11 14:39:22 +03:00
Toshiaki Kameyama
0af3c6542d Correct "after" sample for intention "Convert to apply" #KT-18723 Fixed 2017-07-11 14:06:01 +03:00
Alexey Andreev
5a9adcca2d Improve performance of JS tests
* Do not read protos for descriptors of stdlib and kotlin-tests
  repeatedly
* Parse libraries lazily in inline, so that when no inline function
  exist in a test, we won't parse huge kotlin.js file
* Speed-up source map parser
2017-07-11 11:06:52 +03:00
Dmitry Petrov
83ec8aa918 typealias expansion fixes
- Exception on dynamic type in typealias argument expansion
 #KT-18858 Fixed Target versions 1.1.5
- Wrong report location for repeated annotations in typealias arguments
 #KT-18940 Fixed Target versions 1.1.5
- Don't drop type annotations for dynamic type
 #KT-18944 Fixed Target versions 1.1.5
2017-07-11 10:33:39 +03:00
Nikolay Krasko
a0f11f773b Better diagnostic for error configuration in debugger tests 2017-07-10 15:32:42 +03:00
Nikolay Krasko
68e0727894 Force space between { and first enum entry (KT-18863)
#KT-18863 Fixed
2017-07-10 15:32:42 +03:00
Nikolay Krasko
7f8d6b3008 Don't move line and /**/ comments during reformat (KT-18805)
#KT-18805 Fixed
2017-07-10 15:32:42 +03:00
Mikhail Glukhikh
ebdadf30d8 Get rid of redundant toMap() calls in DelegatingDataFlowInfo 2017-07-10 14:51:52 +03:00
Mikhail Glukhikh
8c9ace7d40 Get rid of Guava in DelegatingDataFlowInfo (except Multimap things) 2017-07-10 14:35:01 +03:00
Mikhail Glukhikh
564cc27a1d Get rid of Guava in CFA (except Multimap things) 2017-07-10 14:34:48 +03:00
Mikhail Glukhikh
dfe2c16bc7 More cleanup: lift return / assignment out 2017-07-10 12:59:58 +03:00
Alexander Udalov
9269de721e JPS: use module path instead of classpath for modular projects
No test added because it would involve running javac 9 and because tests
run JavaBuilder in the same process, this would require either a new
module in our project with dependency on JDK 9 (which would require
everyone to install JDK 9), or complex code that runs javac in another
process
2017-07-10 12:48:21 +03:00
Alexander Udalov
03a6488464 Use module path instead of class path for stdlib on Java 9
Also report the "named does not read unnamed" error, which was not
possible previously because we wouldn't be able to read anything from
kotlin-stdlib (because it was added to the unnamed module by default)
2017-07-10 12:48:21 +03:00
Alexander Udalov
c94b21edd5 Remove obsolete code about runtime versions conflict 2017-07-10 12:48:21 +03:00
Alexander Udalov
4128064f87 Move JavaModuleGraph from 'frontend.java' to 'cli' 2017-07-10 12:48:21 +03:00
Alexander Udalov
5b8e58fe36 Implement module accessibility checks differently in compiler and IDE
Essentially, the logic that was previously in
JvmModuleAccessibilityChecker.diagnosticFor, is moved into a new
abstract method JavaModuleResolver.checkAccessibility, which is
implemented differently in the compiler and in the IDE. In the compiler,
we use our JavaModuleInfo and JavaModuleGraph, as previously. In the
IDE, we use intellij's PsiJavaModule and JavaModuleGraphUtil.

This fixes strange behavior in IDE where some modules could be observed
in an invalid state. The cause of that was the JavaModuleGraph instance
caching modules in IdeJavaModuleResolver, which is a project component.

Moreover, this will allow to report an error "named module does not read
unnamed module" in the compiler, and avoid reporting it in the IDE (see
the comment in IdeJavaModuleResolver about that)
2017-07-10 12:48:21 +03:00
Alexey Andreev
7edb352aeb Copy stdlib-js source map during JPS build 2017-07-10 12:42:33 +03:00
Dmitry Petrov
0ce6bac7eb Generate proper 'compareTo' calls for non-primitive 'a in x .. y'
When we have some custom implementation of Comparable, it's important
that we compare values exactly as 'lowBound <= a && a <= highBound'.

Make sure that evaluation order and compareTo calls match for
optimized and non-optimized case.
2017-07-10 10:51:26 +03:00
Dmitry Petrov
dd5bb78178 Minor: don't use StringBuilder#setLength(0) - absent in JS 2017-07-10 10:51:26 +03:00
Dmitry Petrov
0962aec456 Minor: don't use java.lang.Integer in common test 2017-07-10 10:51:26 +03:00
Dmitry Petrov
aa7db727ba Fold I2L with ICONST_n when beneficial
ICONST_0; I2L -> LCONST_0
ICONST_1; I2L -> LCONST_1
2017-07-10 10:51:26 +03:00
Dmitry Petrov
ad80c3cd7f If at least one of the range bounds is "pure", order doesn't matter 2017-07-10 10:51:26 +03:00
Dmitry Petrov
22e12dc139 Minor: use method names in bytecode text tests 2017-07-10 10:51:26 +03:00
Dmitry Petrov
905a16e1df Maintain proper evaluation order for 'a in x .. y'
As of Kotlin 1.0 and 1.1, expression 'a in x .. y' is considered
equivalent to 'x.rangeTo(y).a', and should be evaluated in the following
order:
1. x
2. y
3. a
4. compare x with a
5. compare y with a (if needed)
2017-07-10 10:51:26 +03:00
Dmitry Petrov
fc3e9318d9 Handle DUPnXm instructions in PopBackwardPropagationTransformer 2017-07-10 10:51:26 +03:00
Dmitry Petrov
6a3ff5ca46 Add tests for intrinsified in/!in and mismatching range types 2017-07-10 10:51:26 +03:00
Dmitry Petrov
850e1b11fc Minor: test modification after review 2017-07-10 10:51:26 +03:00
Dmitry Petrov
64f880ba71 Add test for in/!in in a custom object range 2017-07-10 10:51:26 +03:00
Dmitry Petrov
9d1901fc7c Intrinsify some mismatching range/element combinations for in/in!
It's safe to upcast integer types to Long,
floating-point types to Double.
So we don't have to create a range instance for cases such as

fun testLongInInt(x: Long, a: Int, b: Int) =
    x in a .. b

which is equivalent to

fun testLongInInt(x: Long, a: Int, b: Int) =
    x in a.toLong() .. b.toLong()
2017-07-10 10:51:26 +03:00
Dmitry Petrov
d137b04b0a Pull up logic for ComparisonGenerator selection 2017-07-10 10:51:26 +03:00
Dmitry Petrov
ea95f31f99 Simplify some basic instructions using peephole optimization
DUP_X1; POP = SWAP

p1_a; p1_b; SWAP = p1_b; p1_a
where p1_a, p1_b are instructions without side effects pushing value of
size 1 on stack.
E.g.: ACONST_NULL; ALOAD 0; SWAP = ALOAD 0; ACONST_NULL

NOP; NOP = NOP
2017-07-10 10:51:26 +03:00
Dmitry Petrov
224848163d Use InContinuousRangeExpressionGenerator for primitive range intrinsics 2017-07-10 10:51:26 +03:00
Dmitry Petrov
c855b5c889 Extract SimpleBoundedValue class 2017-07-10 10:51:26 +03:00
Dmitry Petrov
a3409b46b0 Primitive number range literal as BoundedValue 2017-07-10 10:51:26 +03:00
Dmitry Petrov
b693b54a2c Fix DUPn_Xm handling in PopBackwardPropagationTransformer
DUPn_Xm instructions implicitly depend on elements directly under stack
top (which are not "copied", but still required). We can't analyze them
precisely now, and should skip methods containing these instructions.
Fortunately, we didn't generate these instructions under POP before,
but with new range check code generation and constant conditions
elimination such combination of instructions becomes possible.
2017-07-10 10:51:26 +03:00
Dmitry Petrov
4480a9bdfb Introduce BoundedValue as a generalization of (low..high) range
Provide BoundedValue-based implementation of InExpressionGenerator,
test it on range of comparable values.
Drop unneeded test (range of comparables is already tested by
ranges/contains/inComparableRanges.kt).
2017-07-10 10:51:26 +03:00
Dmitry Petrov
f4ea1a2f41 Minor: move RangeValue-related classes to proper packages 2017-07-10 10:51:26 +03:00
Dmitry Petrov
d19eb05382 Introduce AbstractForInProgressionLoopGenerator
AbstractForInProgressionLoopGenerator is a base class for
progression-based 'for' loop generators with progression step unknown
at compile time.
2017-07-10 10:51:26 +03:00
Dmitry Petrov
83ff1a2ef3 Minor: refactor ForInProgressionExpressionLoopGenerator initialization 2017-07-10 10:51:26 +03:00
Dmitry Petrov
6551fdc695 Add test for nullable primitive in range 2017-07-10 10:51:26 +03:00
Dmitry Petrov
db1dcc68ff Minor: cleanup in ExpressionCodegen 2017-07-10 10:51:26 +03:00
Dmitry Petrov
614d90d6ef Skip NOP instructions in fast pop backward propagation 2017-07-10 10:51:26 +03:00
Dmitry Petrov
36cbc0defd Ensure that {Collection, CharSequence}.indices intrinsic works with 'in' 2017-07-10 10:51:26 +03:00
Dmitry Petrov
ec99fa2142 Ensure that 'in/!in x until y' intrinsic works 2017-07-10 10:51:26 +03:00
Dmitry Petrov
05cad83c79 Fix tests for in/in! with primitive range literals
- ClosedFloatingPointRange<T>
- IntRange, etc
- extensions in kotlin.ranges for ranges of Byte/Int/Short
2017-07-10 10:51:26 +03:00
Dmitry Petrov
5decf65d6a Ensure that no range instance is created for 'x in array.indices' 2017-07-10 10:51:26 +03:00
Dmitry Petrov
4320b63922 Ensure that no boolean negation is generated for !in expression
#KT-18777 Fixed Target versions 1.1.4
2017-07-10 10:51:26 +03:00
Dmitry Petrov
b9c0ecf2b1 Ensure that ranges are not created for in-Comparable-range-literal
#KT-6247 Fixed Target versions 1.1.4
2017-07-10 10:51:26 +03:00
Dmitry Petrov
7175361c97 Ensure that BranchedValue for in/!in work well with boolean operations 2017-07-10 10:51:26 +03:00
Dmitry Petrov
a3cd4f415a Add test for comparison used for primitives and Comparable
There's a subtle difference in behavior between comparing
primitive Float/Double (comparison follows IEEE standard)
and boxed Float/Double (comparison is a total order).
Make sure this corner case is preserved.
2017-07-10 10:51:26 +03:00
Dmitry Petrov
fd402cb76c Provide intrinsic for in/in! expression with range of Comparable 2017-07-10 10:51:26 +03:00
Dmitry Petrov
bd2021411c Don't use intrinsic 'in' generator for non-intrinsified 'in' expressions 2017-07-10 10:51:26 +03:00
Dmitry Petrov
a7071ae7af Provide intrinsic generators for in/!in expression
TODO some tests should fail because range of comparables
(e.g., '"Alpha" .. "Omega"') is currently not implemented
2017-07-10 10:51:26 +03:00
Dmitry Petrov
e3320c53f5 Minor: AbstractForInRangeWithGivenBoundsLoopGenerator 2017-07-10 10:51:26 +03:00
Dmitry Petrov
e261b8edf8 Minor: extract high-level interface for ForLoopGenerator 2017-07-10 10:51:26 +03:00
Dmitry Petrov
c870eeac2e RangeCodegenUtil: convert to Kotlin + cleanup 2017-07-10 10:51:26 +03:00
Dmitry Petrov
304e4e8dce RangeCodegenUtil: .java -> .kt 2017-07-10 10:51:26 +03:00
Dmitry Petrov
6140f29818 Ranges: introduce RangeValue class
The overall idea is to unify intrinsics for 'for-in' loop generation
and for 'in'/'!in' expression generation.
2017-07-10 10:51:26 +03:00
1127 changed files with 35209 additions and 13751 deletions

View File

@@ -61,7 +61,6 @@
<element id="module-output" name="ir.psi2ir" />
<element id="module-output" name="annotation-based-compiler-plugins-ide-support" />
<element id="module-output" name="frontend.script" />
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/json-org.jar" path-in-jar="/" />
</element>
<element id="library" level="project" name="javax.inject" />
<element id="directory" name="jps">

View File

@@ -1,10 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="yan">
<words>
<w>deserializes</w>
<w>impls</w>
<w>kapt</w>
<w>parceler</w>
<w>uast</w>
</words>
</dictionary>

View File

@@ -18,12 +18,14 @@
<root url="jar://$PROJECT_DIR$/ideaSDK/core/util.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/core/xpp3-1.1.4-min.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/core/xstream-1.4.8.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/jsr305.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/guava-19.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/sources/sources.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/asm-src.zip!/" />
<root url="jar://$PROJECT_DIR$/ideaSDK/lib/jsr305.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -1,59 +0,0 @@
<component name="libraryTable">
<library name="robolectric">
<CLASSES>
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/accessibility-test-framework-2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/ant-1.8.0.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/ant-launcher-1.8.0.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-5.0.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-commons-5.0.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/asm-tree-5.0.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/assertj-core-2.6.0.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/backport-util-concurrent-3.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/bcprov-jdk16-1.46.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/classworlds-1.1-alpha-2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/guava-20.0.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/hamcrest-core-1.3.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/hamcrest-library-1.3.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/icu4j-53.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-ant-tasks-2.1.3.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-artifact-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-artifact-manager-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-error-diagnostics-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-model-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-plugin-registry-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-profile-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-project-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-repository-metadata-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/maven-settings-2.2.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/nekohtml-1.9.6.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/plexus-container-default-1.0-alpha-9-stable-1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/plexus-interpolation-1.11.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/plexus-utils-1.5.15.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/protobuf-java-2.6.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-annotations-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-junit-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-resources-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-sandbox-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-utils-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/shadow-api-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/shadows-core-3.3.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/sqlite4java-0.282.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/wagon-file-1.0-beta-6.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/wagon-http-lightweight-1.0-beta-6.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/wagon-http-shared-1.0-beta-6.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/wagon-provider-api-1.0-beta-6.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xercesMinimal-1.9.6.2.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xmlpull-1.1.3.1.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xpp3_min-1.1.4c.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/xstream-1.4.8.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.3.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.3.2-sources-source.jar!/" />
<root url="jar://$PROJECT_DIR$/dependencies/robolectric/robolectric-3.3.2-sources.jar!/" />
</SOURCES>
</library>
</component>

File diff suppressed because it is too large Load Diff

View File

@@ -22202,8 +22202,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22213,8 +22213,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22419,8 +22419,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22432,8 +22432,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22913,8 +22913,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22926,8 +22926,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22939,8 +22939,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>
@@ -22955,8 +22955,8 @@ public final class DebugProtoBuf {
* <code>optional int32 flags = 1 [default = 0];</code>
*
* <pre>
*declaresDefault
*hasAnnotations
*declaresDefault
*isCrossinline
*isNoinline
* </pre>

View File

@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated;
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.AnnotationChecker;
import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
@@ -291,32 +293,27 @@ public abstract class AnnotationCodegen {
@Nullable
private String genAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) {
ClassifierDescriptor classifierDescriptor = getAnnotationClass(annotationDescriptor);
assert classifierDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor;
RetentionPolicy rp = getRetentionPolicy(classifierDescriptor);
ClassDescriptor classDescriptor = getAnnotationClass(annotationDescriptor);
assert classDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor;
RetentionPolicy rp = getRetentionPolicy(classDescriptor);
if (rp == RetentionPolicy.SOURCE && !typeMapper.getClassBuilderMode().generateSourceRetentionAnnotations) {
return null;
}
String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
innerClassConsumer.addInnerClassInfoFromAnnotation(classDescriptor);
if (classifierDescriptor instanceof ClassDescriptor) {
innerClassConsumer.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor));
}
AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME);
String asmTypeDescriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
AnnotationVisitor annotationVisitor = visitAnnotation(asmTypeDescriptor, rp == RetentionPolicy.RUNTIME);
genAnnotationArguments(annotationDescriptor, annotationVisitor);
annotationVisitor.visitEnd();
return descriptor;
return asmTypeDescriptor;
}
private void genAnnotationArguments(AnnotationDescriptor annotationDescriptor, AnnotationVisitor annotationVisitor) {
for (Map.Entry<ValueParameterDescriptor, ConstantValue<?>> entry : annotationDescriptor.getAllValueArguments().entrySet()) {
ValueParameterDescriptor descriptor = entry.getKey();
String name = descriptor.getName().asString();
genCompileTimeValue(name, entry.getValue(), annotationVisitor);
for (Map.Entry<Name, ConstantValue<?>> entry : annotationDescriptor.getAllValueArguments().entrySet()) {
genCompileTimeValue(entry.getKey().asString(), entry.getValue(), annotationVisitor);
}
}
@@ -475,16 +472,13 @@ public abstract class AnnotationCodegen {
}
AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
if (retentionAnnotation != null) {
Collection<ConstantValue<?>> valueArguments = retentionAnnotation.getAllValueArguments().values();
if (!valueArguments.isEmpty()) {
ConstantValue<?> compileTimeConstant = valueArguments.iterator().next();
if (compileTimeConstant instanceof EnumValue) {
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
if (classObjectType != null) {
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
return RetentionPolicy.valueOf(enumEntry.getName().asString());
}
ConstantValue<?> compileTimeConstant = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values());
if (compileTimeConstant instanceof EnumValue) {
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
if (classObjectType != null) {
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
return RetentionPolicy.valueOf(enumEntry.getName().asString());
}
}
}

View File

@@ -140,10 +140,18 @@ public class AsmUtil {
return primitiveTypeByBoxedType.get(boxedType);
}
public static boolean isBoxedTypeOf(@NotNull Type boxedType, @NotNull Type unboxedType) {
return unboxPrimitiveTypeOrNull(boxedType) == unboxedType;
}
public static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
public static boolean isIntOrLongPrimitive(Type type) {
return isIntPrimitive(type) || type == Type.LONG_TYPE;
}
public static boolean isNumberPrimitiveOrBoolean(Type type) {
return isNumberPrimitive(type) || type.getSort() == Type.BOOLEAN;
}
@@ -709,7 +717,7 @@ public class AsmUtil {
if (innerType.getSort() == Type.OBJECT || innerType.getSort() == Type.ARRAY) {
v.dup();
v.visitLdcInsn(runtimeAssertionInfo.getMessage());
v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkExpressionValueIsNotNull",
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkExpressionValueIsNotNull",
"(Ljava/lang/Object;Ljava/lang/String;)V", false);
}
StackValue.coerce(innerType, type, v);
@@ -799,6 +807,16 @@ public class AsmUtil {
}
}
public static void pop2(@NotNull MethodVisitor v, @NotNull Type type) {
if (type.getSize() == 2) {
v.visitInsn(Opcodes.POP2);
v.visitInsn(Opcodes.POP2);
}
else {
v.visitInsn(Opcodes.POP2);
}
}
public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) {
dup(v, type.getSize());
}
@@ -815,6 +833,22 @@ public class AsmUtil {
}
}
public static void dupx(@NotNull InstructionAdapter v, @NotNull Type type) {
dupx(v, type.getSize());
}
private static void dupx(@NotNull InstructionAdapter v, int size) {
if (size == 2) {
v.dup2X2();
}
else if (size == 1) {
v.dupX1();
}
else {
throw new UnsupportedOperationException();
}
}
public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) {
if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) {
return;

View File

@@ -0,0 +1,308 @@
/*
* Copyright 2010-2017 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 com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
abstract class NumberLikeCompare(
left: StackValue,
right: StackValue,
operandType: Type,
private val opToken: IElementType
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
NumberCompare.patchOpcode(opcode, v, opToken, operandType)
}
abstract class SafeCallFusedWithPrimitiveEqualityBase(
opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue
) : NumberLikeCompare(left, right, operandType, opToken) {
private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ
protected abstract fun cleanupOnNullReceiver(v: InstructionAdapter)
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
val endLabel = Label()
arg1.put(operandType, v)
arg2!!.put(operandType, v)
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
v.goTo(endLabel)
cleanupOnNullReceiver(v)
if (jumpIfFalse == trueIfEqual) {
v.goTo(jumpLabel)
}
v.mark(endLabel)
}
override fun putSelector(type: Type, v: InstructionAdapter) {
val falseLabel = Label()
val endLabel = Label()
arg1.put(operandType, v)
arg2!!.put(operandType, v)
v.visitJumpInsn(patchOpcode(opcode, v), falseLabel)
if (!trueIfEqual) {
val trueLabel = Label()
v.goTo(trueLabel)
cleanupOnNullReceiver(v)
v.mark(trueLabel)
}
v.iconst(1)
v.goTo(endLabel)
if (trueIfEqual) {
cleanupOnNullReceiver(v)
}
v.mark(falseLabel)
v.iconst(0)
v.mark(endLabel)
coerceTo(type, v)
}
}
class SafeCallToPrimitiveEquality(
opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue,
private val safeReceiverType: Type,
private val safeReceiverIsNull: Label
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
v.mark(safeReceiverIsNull)
AsmUtil.pop(v, safeReceiverType)
}
}
class PrimitiveToSafeCallEquality(
opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue,
private val safeReceiverType: Type,
private val safeReceiverIsNull: Label
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
v.mark(safeReceiverIsNull)
AsmUtil.pop(v, safeReceiverType)
AsmUtil.pop(v, arg1.type)
}
}
class BoxedToPrimitiveEquality private constructor(
leftBoxed: StackValue,
rightPrimitive: StackValue,
primitiveType: Type,
private val frameMap: FrameMap
) : NumberLikeCompare(leftBoxed, rightPrimitive, primitiveType, KtTokens.EQEQ) {
private val boxedType = arg1.type
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (arg2!!.canHaveSideEffects()) {
val tmp = frameMap.enterTemp(operandType)
doJump(
v, jumpLabel, jumpIfFalse,
{
arg1.put(boxedType, v)
arg2.put(operandType, v)
v.store(tmp, operandType)
},
{ v.load(tmp, operandType) }
)
frameMap.leaveTemp(operandType)
}
else {
doJump(
v, jumpLabel, jumpIfFalse,
{ arg1.put(boxedType, v) },
{ arg2.put(operandType, v) }
)
}
}
private inline fun doJump(
v: InstructionAdapter,
jumpLabel: Label,
jumpIfFalse: Boolean,
putArg1: () -> Unit,
putArg2: () -> Unit
) {
val notNullLabel = Label()
val endLabel = Label()
putArg1()
AsmUtil.dup(v, boxedType)
v.ifnonnull(notNullLabel)
AsmUtil.pop(v, boxedType)
if (jumpIfFalse) v.goTo(jumpLabel) else v.goTo(endLabel)
v.mark(notNullLabel)
coerce(boxedType, operandType, v)
putArg2()
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
v.mark(endLabel)
}
companion object {
@JvmStatic
fun create(
opToken: IElementType,
left: StackValue,
leftType: Type,
right: StackValue,
rightType: Type,
frameMap: FrameMap
): BranchedValue =
if (!isApplicable(opToken, leftType, rightType))
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
else when (opToken) {
KtTokens.EQEQ -> BoxedToPrimitiveEquality(left, right, rightType, frameMap)
KtTokens.EXCLEQ -> Invert(BoxedToPrimitiveEquality(left, right, rightType, frameMap))
else -> throw AssertionError("Unexpected opToken: $opToken")
}
@JvmStatic
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
AsmUtil.isIntOrLongPrimitive(rightType) &&
AsmUtil.isBoxedTypeOf(leftType, rightType)
}
}
abstract class PrimitiveToSomethingEquality
protected constructor(
leftPrimitive: StackValue,
right: StackValue,
primitiveType: Type
) : NumberLikeCompare(leftPrimitive, right, primitiveType, KtTokens.EQEQ) {
protected val primitiveType = leftPrimitive.type
protected val rightType = right.type
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
val notNullLabel = Label()
val endLabel = Label()
arg1.put(primitiveType, v)
arg2!!.put(rightType, v)
AsmUtil.dup(v, rightType)
jumpIfCanCompareTopWithPrimitive(v, notNullLabel)
AsmUtil.pop(v, rightType)
AsmUtil.pop(v, primitiveType)
if (jumpIfFalse) v.goTo(jumpLabel) else v.goTo(endLabel)
v.mark(notNullLabel)
coerceRightToPrimitive(v)
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
v.mark(endLabel)
}
protected abstract fun jumpIfCanCompareTopWithPrimitive(v: InstructionAdapter, label: Label)
protected abstract fun coerceRightToPrimitive(v: InstructionAdapter)
}
class PrimitiveToBoxedEquality private constructor(
leftPrimitive: StackValue,
rightBoxed: StackValue,
primitiveType: Type
) : PrimitiveToSomethingEquality(leftPrimitive, rightBoxed, primitiveType) {
private val boxedType = rightBoxed.type
override fun jumpIfCanCompareTopWithPrimitive(v: InstructionAdapter, label: Label) {
v.ifnonnull(label)
}
override fun coerceRightToPrimitive(v: InstructionAdapter) {
coerce(boxedType, primitiveType, v)
}
companion object {
@JvmStatic
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
if (!isApplicable(opToken, leftType, rightType))
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
else when (opToken) {
KtTokens.EQEQ -> PrimitiveToBoxedEquality(left, right, leftType)
KtTokens.EXCLEQ -> Invert(PrimitiveToBoxedEquality(left, right, leftType))
else -> throw AssertionError("Unexpected opToken: $opToken")
}
@JvmStatic
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
AsmUtil.isIntOrLongPrimitive(leftType) &&
AsmUtil.isBoxedTypeOf(rightType, leftType)
}
}
class PrimitiveToObjectEquality private constructor(
leftPrimitive: StackValue,
rightObject: StackValue,
primitiveType: Type
) : PrimitiveToSomethingEquality(leftPrimitive, rightObject, primitiveType) {
private val boxedType = AsmUtil.boxType(primitiveType)
override fun jumpIfCanCompareTopWithPrimitive(v: InstructionAdapter, label: Label) {
v.instanceOf(boxedType)
v.ifne(label)
}
override fun coerceRightToPrimitive(v: InstructionAdapter) {
coerce(rightType, boxedType, v)
coerce(boxedType, primitiveType, v)
}
companion object {
@JvmStatic
fun create(opToken: IElementType, left: StackValue, leftType: Type, right: StackValue, rightType: Type): BranchedValue =
if (!isApplicable(opToken, leftType, rightType))
throw IllegalArgumentException("Not applicable for $opToken, $leftType, $rightType")
else when (opToken) {
KtTokens.EQEQ -> PrimitiveToObjectEquality(left, right, leftType)
KtTokens.EXCLEQ -> Invert(PrimitiveToObjectEquality(left, right, leftType))
else -> throw AssertionError("Unexpected opToken: $opToken")
}
@JvmStatic
fun isApplicable(opToken: IElementType, leftType: Type, rightType: Type) =
(opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ) &&
AsmUtil.isIntOrLongPrimitive(leftType) &&
rightType.sort == Type.OBJECT
}
}

View File

@@ -54,9 +54,7 @@ open class BranchedValue(
condJump(jumpLabel, v, jumpIfFalse)
}
protected open fun patchOpcode(opcode: Int, v: InstructionAdapter): Int {
return opcode
}
protected open fun patchOpcode(opcode: Int, v: InstructionAdapter): Int = opcode
companion object {
val negatedOperations = hashMapOf<Int, Int>()
@@ -120,13 +118,9 @@ open class BranchedValue(
negatedOperations.put(negatedOp, op)
}
fun booleanConstant(value: Boolean): BranchedValue {
return if (value) TRUE else FALSE
}
fun booleanConstant(value: Boolean): BranchedValue = if (value) TRUE else FALSE
fun createInvertValue(argument: StackValue): StackValue {
return Invert(condJump(argument))
}
fun createInvertValue(argument: StackValue): StackValue = Invert(condJump(argument))
fun condJump(condition: StackValue, label: Label, jumpIfFalse: Boolean, iv: InstructionAdapter) {
condJump(condition).condJump(label, iv, jumpIfFalse)
@@ -136,14 +130,11 @@ open class BranchedValue(
condJump(condition).loopJump(label, iv, jumpIfFalse)
}
fun condJump(condition: StackValue): CondJump {
return CondJump(if (condition is BranchedValue) {
condition
}
else {
BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ)
}, IFEQ)
}
fun condJump(condition: StackValue): CondJump =
CondJump(
condition as? BranchedValue ?: BranchedValue(condition, null, Type.BOOLEAN_TYPE, IFEQ),
IFEQ
)
fun cmp(opToken: IElementType, operandType: Type, left: StackValue, right: StackValue): StackValue =
if (operandType.sort == Type.OBJECT)
@@ -203,7 +194,7 @@ class CondJump(val condition: BranchedValue, op: Int) : BranchedValue(condition,
}
class NumberCompare(
val opToken: IElementType,
private val opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue
@@ -213,17 +204,15 @@ class NumberCompare(
patchOpcode(opcode, v, opToken, operandType)
companion object {
fun getNumberCompareOpcode(opToken: IElementType): Int {
return when (opToken) {
KtTokens.EQEQ, KtTokens.EQEQEQ -> IFNE
KtTokens.EXCLEQ, KtTokens.EXCLEQEQEQ -> IFEQ
KtTokens.GT -> IFLE
KtTokens.GTEQ -> IFLT
KtTokens.LT -> IFGE
KtTokens.LTEQ -> IFGT
else -> {
throw UnsupportedOperationException("Don't know how to generate this condJump: " + opToken)
}
fun getNumberCompareOpcode(opToken: IElementType): Int = when (opToken) {
KtTokens.EQEQ, KtTokens.EQEQEQ -> IFNE
KtTokens.EXCLEQ, KtTokens.EXCLEQEQEQ -> IFEQ
KtTokens.GT -> IFLE
KtTokens.GTEQ -> IFLT
KtTokens.LT -> IFGE
KtTokens.LTEQ -> IFGT
else -> {
throw UnsupportedOperationException("Don't know how to generate this condJump: " + opToken)
}
}
@@ -258,100 +247,11 @@ class ObjectCompare(
) : BranchedValue(left, right, operandType, ObjectCompare.getObjectCompareOpcode(opToken)) {
companion object {
fun getObjectCompareOpcode(opToken: IElementType): Int {
return when (opToken) {
KtTokens.EQEQEQ -> IF_ACMPNE
KtTokens.EXCLEQEQEQ -> IF_ACMPEQ
else -> throw UnsupportedOperationException("don't know how to generate this condjump")
}
fun getObjectCompareOpcode(opToken: IElementType): Int = when (opToken) {
KtTokens.EQEQEQ -> IF_ACMPNE
KtTokens.EXCLEQEQEQ -> IF_ACMPEQ
else -> throw UnsupportedOperationException("don't know how to generate this condjump")
}
}
}
abstract class SafeCallFusedWithPrimitiveEqualityBase(
val opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue
) : BranchedValue(left, right, operandType, NumberCompare.getNumberCompareOpcode(opToken)) {
private val trueIfEqual = opToken == KtTokens.EQEQ || opToken == KtTokens.EQEQEQ
protected abstract fun cleanupOnNullReceiver(v: InstructionAdapter)
override fun patchOpcode(opcode: Int, v: InstructionAdapter): Int =
NumberCompare.patchOpcode(opcode, v, opToken, operandType)
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
val endLabel = Label()
arg1.put(operandType, v)
arg2!!.put(operandType, v)
v.visitJumpInsn(patchOpcode(if (jumpIfFalse) opcode else negatedOperations[opcode]!!, v), jumpLabel)
v.goTo(endLabel)
cleanupOnNullReceiver(v)
if (jumpIfFalse == trueIfEqual) {
v.goTo(jumpLabel)
}
v.mark(endLabel)
}
override fun putSelector(type: Type, v: InstructionAdapter) {
val falseLabel = Label()
val endLabel = Label()
arg1.put(operandType, v)
arg2!!.put(operandType, v)
v.visitJumpInsn(patchOpcode(opcode, v), falseLabel)
if (!trueIfEqual) {
val trueLabel = Label()
v.goTo(trueLabel)
cleanupOnNullReceiver(v)
v.mark(trueLabel)
}
v.iconst(1)
v.goTo(endLabel)
if (trueIfEqual) {
cleanupOnNullReceiver(v)
}
v.mark(falseLabel)
v.iconst(0)
v.mark(endLabel)
coerceTo(type, v)
}
}
class SafeCallToPrimitiveEquality(
opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue,
val safeReceiverType: Type,
val safeReceiverIsNull: Label
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
v.mark(safeReceiverIsNull)
AsmUtil.pop(v, safeReceiverType)
}
}
class PrimitiveToSafeCallEquality(
opToken: IElementType,
operandType: Type,
left: StackValue,
right: StackValue,
val safeReceiverType: Type,
val safeReceiverIsNull: Label
) : SafeCallFusedWithPrimitiveEqualityBase(opToken, operandType, left, right) {
override fun cleanupOnNullReceiver(v: InstructionAdapter) {
v.mark(safeReceiverIsNull)
AsmUtil.pop(v, safeReceiverType)
AsmUtil.pop(v, arg1.type)
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2010-2017 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.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
public class CallReceiver extends StackValue {
private final StackValue dispatchReceiver;
private final StackValue extensionReceiver;
private final Type secondReceiverType;
private CallReceiver(
@NotNull StackValue dispatchReceiver,
@NotNull StackValue extensionReceiver,
@NotNull Type type,
@Nullable Type secondReceiverType
) {
super(type, dispatchReceiver.canHaveSideEffects() || extensionReceiver.canHaveSideEffects());
this.dispatchReceiver = dispatchReceiver;
this.extensionReceiver = extensionReceiver;
this.secondReceiverType = secondReceiverType;
}
public StackValue withoutReceiverArgument() {
return new CallReceiver(dispatchReceiver, none(), type, secondReceiverType);
}
public static StackValue generateCallReceiver(
@NotNull ResolvedCall<?> resolvedCall,
@NotNull ExpressionCodegen codegen,
@Nullable Callable callableMethod,
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
@NotNull StackValue dispatchReceiver,
@Nullable ReceiverParameterDescriptor extensionReceiverParameter,
@NotNull StackValue extensionReceiver
) {
KotlinTypeMapper typeMapper = codegen.typeMapper;
GenerationState state = codegen.getState();
Type type;
Type secondReceiverType = null;
if (extensionReceiverParameter != null) {
type = calcExtensionReceiverType(resolvedCall, extensionReceiverParameter, typeMapper, callableMethod, state);
if (dispatchReceiverParameter != null) {
secondReceiverType = calcDispatchReceiverType(resolvedCall, dispatchReceiverParameter, typeMapper, callableMethod);
}
}
else if (dispatchReceiverParameter != null) {
type = calcDispatchReceiverType(resolvedCall, dispatchReceiverParameter, typeMapper, callableMethod);
}
else if (isLocalFunCall(callableMethod)) {
type = callableMethod.getGenerateCalleeType();
}
else {
type = Type.VOID_TYPE;
}
assert type != null : "Could not map receiver type for " + resolvedCall;
return new CallReceiver(dispatchReceiver, extensionReceiver, type, secondReceiverType);
}
private static Type calcDispatchReceiverType(
@NotNull ResolvedCall<?> resolvedCall,
@Nullable ReceiverParameterDescriptor dispatchReceiver,
@NotNull KotlinTypeMapper typeMapper,
@Nullable Callable callableMethod
) {
if (dispatchReceiver == null) return null;
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
return Type.VOID_TYPE;
}
if (callableMethod != null) {
return callableMethod.getDispatchReceiverType();
}
// Extract the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have
// all the needed information, for example there's no way to find out whether or not a smart cast was applied to the receiver.
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container instanceof ClassDescriptor) {
return typeMapper.mapClass((ClassDescriptor) container);
}
return typeMapper.mapType(dispatchReceiver);
}
private static Type calcExtensionReceiverType(
@NotNull ResolvedCall<?> resolvedCall,
@Nullable ReceiverParameterDescriptor extensionReceiver,
@NotNull KotlinTypeMapper typeMapper,
@Nullable Callable callableMethod,
@NotNull GenerationState state
) {
if (extensionReceiver == null) return null;
CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor();
if (descriptor instanceof PropertyDescriptor &&
// hackaround: boxing changes behaviour of T.javaClass intrinsic
state.getIntrinsics().getIntrinsic((PropertyDescriptor) descriptor) != JavaClassProperty.INSTANCE
) {
ReceiverParameterDescriptor receiverCandidate = descriptor.getExtensionReceiverParameter();
assert receiverCandidate != null;
return typeMapper.mapType(receiverCandidate.getType());
}
return callableMethod != null ? callableMethod.getExtensionReceiverType() : typeMapper.mapType(extensionReceiver.getType());
}
@Override
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
StackValue currentExtensionReceiver = extensionReceiver;
boolean hasExtensionReceiver = extensionReceiver != none();
if (extensionReceiver instanceof SafeCall) {
currentExtensionReceiver.put(currentExtensionReceiver.type, v);
currentExtensionReceiver = StackValue.onStack(currentExtensionReceiver.type);
}
Type dispatchReceiverType = secondReceiverType != null ? secondReceiverType :
hasExtensionReceiver ? dispatchReceiver.type :
type;
dispatchReceiver.put(dispatchReceiverType, v);
currentExtensionReceiver
.moveToTopOfStack(hasExtensionReceiver ? type : currentExtensionReceiver.type, v, dispatchReceiverType.getSize());
}
@Override
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type);
}
@NotNull
public StackValue getDispatchReceiver() {
return dispatchReceiver;
}
@NotNull
public StackValue getExtensionReceiver() {
return extensionReceiver;
}
}

View File

@@ -192,6 +192,6 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
@Nullable
@Override
protected ClassDescriptor classForInnerClassRecord() {
return InnerClassConsumer.Companion.classForInnerClassRecord(descriptor, false);
return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
}
}

View File

@@ -39,11 +39,12 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenForLambda;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.coroutines.ResolvedCallWithRealDescriptor;
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.kotlin.codegen.forLoop.AbstractForLoopGenerator;
import org.jetbrains.kotlin.codegen.forLoop.ForLoopGeneratorsKt;
import org.jetbrains.kotlin.codegen.inline.*;
import org.jetbrains.kotlin.codegen.intrinsics.*;
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
import org.jetbrains.kotlin.codegen.range.RangeValue;
import org.jetbrains.kotlin.codegen.range.RangeValuesKt;
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator;
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -599,7 +600,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
private void generateFor(@NotNull KtForExpression forExpression) {
generateForLoop(ForLoopGeneratorsKt.getForLoopGenerator(this, forExpression));
KtExpression range = forExpression.getLoopRange();
assert range != null : "No loop range in for expression";
RangeValue rangeValue = RangeValuesKt.createRangeValueForExpression(this, range);
generateForLoop(rangeValue.createForLoopGenerator(this, forExpression));
}
@NotNull
@@ -623,7 +627,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return context.getContextKind();
}
private void generateForLoop(AbstractForLoopGenerator generator) {
private void generateForLoop(ForLoopGenerator generator) {
Label loopExit = new Label();
Label loopEntry = new Label();
Label continueLabel = new Label();
@@ -2278,12 +2282,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// But the problem is that we should leave the receiver itself on the stack, so we store it in a temporary variable.
if (isSuspendCall && isSafeCallOrOnStack) {
boolean bothReceivers =
receiver instanceof StackValue.CallReceiver
&& ((StackValue.CallReceiver) receiver).getDispatchReceiver().type.getSort() != Type.VOID
&& ((StackValue.CallReceiver) receiver).getExtensionReceiver().type.getSort() != Type.VOID;
receiver instanceof CallReceiver
&& ((CallReceiver) receiver).getDispatchReceiver().type.getSort() != Type.VOID
&& ((CallReceiver) receiver).getExtensionReceiver().type.getSort() != Type.VOID;
Type firstReceiverType =
bothReceivers
? ((StackValue.CallReceiver) receiver).getDispatchReceiver().type
? ((CallReceiver) receiver).getDispatchReceiver().type
: receiver.type;
Type secondReceiverType = bothReceivers ? receiver.type : null;
@@ -2851,76 +2855,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private StackValue generateIn(StackValue leftValue, KtExpression rangeExpression, KtSimpleNameExpression operationReference) {
KtExpression deparenthesized = KtPsiUtil.deparenthesize(rangeExpression);
assert deparenthesized != null : "For with empty range expression";
boolean isInverted = operationReference.getReferencedNameElementType() == KtTokens.NOT_IN;
return StackValue.operation(Type.BOOLEAN_TYPE, v -> {
if (RangeCodegenUtil.isPrimitiveRangeSpecializationOfType(leftValue.type, deparenthesized, bindingContext) ||
RangeCodegenUtil.isPrimitiveRangeToExtension(operationReference, bindingContext)) {
generateInPrimitiveRange(leftValue, (KtBinaryExpression) deparenthesized, isInverted);
}
else {
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt
.getResolvedCallWithAssert(operationReference, bindingContext);
StackValue result = invokeFunction(resolvedCall.getCall(), resolvedCall, StackValue.none());
result.put(result.type, v);
if (isInverted) {
genInvertBoolean(v);
}
}
return null;
});
}
/*
* Translates x in a..b to a <= x && x <= b
* and x !in a..b to a > x || x > b for any primitive type
*/
private void generateInPrimitiveRange(StackValue argument, KtBinaryExpression rangeExpression, boolean isInverted) {
Type rangeType = argument.type;
int localVarIndex = myFrameMap.enterTemp(rangeType);
// Load left bound
gen(rangeExpression.getLeft(), rangeType);
// Load x into local variable to avoid StackValue#put side-effects
argument.put(rangeType, v);
v.store(localVarIndex, rangeType);
v.load(localVarIndex, rangeType);
// If (x < left) goto L1
Label l1 = new Label();
emitGreaterThan(rangeType, l1);
// If (x > right) goto L1
v.load(localVarIndex, rangeType);
gen(rangeExpression.getRight(), rangeType);
emitGreaterThan(rangeType, l1);
Label l2 = new Label();
v.iconst(isInverted ? 0 : 1);
v.goTo(l2);
v.mark(l1);
v.iconst(isInverted ? 1 : 0);
v.mark(l2);
myFrameMap.leaveTemp(rangeType);
}
private void emitGreaterThan(Type type, Label label) {
if (AsmUtil.isIntPrimitive(type)) {
v.ificmpgt(label);
}
else if (type == Type.LONG_TYPE) {
v.lcmp();
v.ifgt(label);
}
// '>' != 'compareTo' for NaN and +/- 0.0
else if (type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE) {
v.cmpg(type);
v.ifgt(label);
}
else {
throw new UnsupportedOperationException("Unexpected type: " + type);
}
RangeValue rangeValue = RangeValuesKt.createRangeValueForExpression(this, deparenthesized);
return rangeValue.createInExpressionGenerator(this, operationReference).generate(leftValue);
}
private StackValue generateBooleanAnd(KtBinaryExpression expression) {
@@ -2958,6 +2895,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken);
}
if (BoxedToPrimitiveEquality.isApplicable(opToken, leftType, rightType)) {
return BoxedToPrimitiveEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType,
myFrameMap);
}
if (PrimitiveToBoxedEquality.isApplicable(opToken, leftType, rightType)) {
return PrimitiveToBoxedEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType);
}
if (PrimitiveToObjectEquality.isApplicable(opToken, leftType, rightType)) {
return PrimitiveToObjectEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType);
}
if (isPrimitive(leftType) != isPrimitive(rightType)) {
leftType = boxType(leftType);
rightType = boxType(rightType);

View File

@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -64,10 +65,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
@@ -348,9 +346,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
protected void generateSyntheticParts() {
protected void generateSyntheticPartsBeforeBody() {
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
}
@Override
protected void generateSyntheticPartsAfterBody() {
generateFieldForSingleton();
generateCompanionObjectBackingFieldCopies();
@@ -835,9 +836,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Nullable KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(myClass.getCompanionObjects());
int properFieldVisibilityFlag = getVisibilityAccessFlag(companionObjectDescriptor);
boolean fieldShouldBeDeprecated =
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.DeprecatedFieldForInvisibleCompanionObject) &&
(properFieldVisibilityFlag & (ACC_PRIVATE | ACC_PROTECTED)) != 0;
// TODO generate field with proper visibility in language version 1.3
int fieldAccessFlags = ACC_PUBLIC | ACC_STATIC | ACC_FINAL;
if (fieldShouldBeDeprecated) {
fieldAccessFlags |= ACC_DEPRECATED;
}
StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject),
ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject),
fieldAccessFlags, field.name, field.type.getDescriptor(), null, null);
if (fieldShouldBeDeprecated) {
AnnotationCodegen.forField(fv, this, typeMapper).visitAnnotation("Ljava/lang/Deprecated;", true).visitEnd();
}
}
private void generateCompanionObjectBackingFieldCopies() {

View File

@@ -17,35 +17,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import java.util.*
interface InnerClassConsumer {
fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor)
companion object {
fun classForInnerClassRecord(descriptor: ClassDescriptor, defaultImpls: Boolean): ClassDescriptor? {
if (defaultImpls) {
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,
/* isExternal = */ false)
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
return classDescriptorImpl
}
else {
return if (DescriptorUtils.isTopLevelDeclaration(descriptor)) null else descriptor
}
}
}
}

View File

@@ -60,10 +60,17 @@ class InterfaceImplBodyCodegen(
override fun classForInnerClassRecord(): ClassDescriptor? {
if (!isAnythingGenerated) return null
return InnerClassConsumer.classForInnerClassRecord(descriptor, true)
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,
/* isExternal = */ false)
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
return classDescriptorImpl
}
override fun generateSyntheticParts() {
override fun generateSyntheticPartsAfterBody() {
for (memberDescriptor in descriptor.defaultType.memberScope.getContributedDescriptors()) {
if (memberDescriptor !is CallableMemberDescriptor) continue

View File

@@ -94,8 +94,7 @@ class JvmStaticInCompanionObjectGenerator(
CallableMemberDescriptor.Kind.SYNTHESIZED,
false
)
val staticFunctionDescriptor = copies[descriptor]!!
return staticFunctionDescriptor
return copies[descriptor]!!
}
}
}

View File

@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.fileClasses.FileClasses;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
@@ -49,6 +50,7 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
@@ -134,11 +136,18 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
public void generate() {
generateDeclaration();
boolean shouldGenerateSyntheticParts =
!(element instanceof KtClassOrObject) ||
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) element);
if (shouldGenerateSyntheticParts) {
generateSyntheticPartsBeforeBody();
}
generateBody();
if (!(element instanceof KtClassOrObject) ||
state.getGenerateDeclaredClassFilter().shouldGenerateClassMembers((KtClassOrObject) element)) {
generateSyntheticParts();
if (shouldGenerateSyntheticParts) {
generateSyntheticPartsAfterBody();
}
if (state.getClassBuilderMode().generateMetadata) {
@@ -150,9 +159,12 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
protected abstract void generateDeclaration();
protected void generateSyntheticPartsBeforeBody() {
}
protected abstract void generateBody();
protected void generateSyntheticParts() {
protected void generateSyntheticPartsAfterBody() {
}
protected abstract void generateKotlinMetadataAnnotation();
@@ -332,7 +344,12 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
parentCodegen.innerClasses.add(classDescriptor);
}
addParentsToInnerClassesIfNeeded(innerClasses);
for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
ClassDescriptor outerClass = codegen.classForInnerClassRecord();
if (outerClass != null) {
innerClasses.add(outerClass);
}
}
}
for (ClassDescriptor innerClass : innerClasses) {
@@ -340,18 +357,6 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
}
protected void addParentsToInnerClassesIfNeeded(@NotNull Collection<ClassDescriptor> innerClasses) {
ClassDescriptor outerClass = classForInnerClassRecord();
if (outerClass != null) {
innerClasses.add(outerClass);
}
MemberCodegen<?> parentCodegen = getParentCodegen();
if (parentCodegen != null) {
parentCodegen.addParentsToInnerClassesIfNeeded(innerClasses);
}
}
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
// See FileBasedKotlinClass.convertAnnotationVisitor
@Override

View File

@@ -189,7 +189,7 @@ class MultifileClassPartCodegen(
}
}
override fun generateSyntheticParts() {
override fun generateSyntheticPartsAfterBody() {
generateSyntheticAccessors()
}

View File

@@ -132,7 +132,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
}
@Override
protected void generateSyntheticParts() {
protected void generateSyntheticPartsAfterBody() {
generateSyntheticAccessors();
}
}

View File

@@ -1,241 +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 com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
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 java.util.Arrays;
import java.util.List;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor;
public class RangeCodegenUtil {
private static final ImmutableMap<FqName, PrimitiveType> RANGE_TO_ELEMENT_TYPE;
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_TO_ELEMENT_TYPE;
@NotNull
public static List<PrimitiveType> supportedRangeTypes() {
return Arrays.asList(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG);
}
static {
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = ImmutableMap.builder();
for (PrimitiveType primitiveType : supportedRangeTypes()) {
FqName rangeClassFqName = RANGES_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Range"));
FqName progressionClassFqName = RANGES_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
rangeBuilder.put(rangeClassFqName, primitiveType);
progressionBuilder.put(progressionClassFqName, primitiveType);
}
RANGE_TO_ELEMENT_TYPE = rangeBuilder.build();
PROGRESSION_TO_ELEMENT_TYPE = progressionBuilder.build();
}
private RangeCodegenUtil() {}
public static boolean isRange(KotlinType rangeType) {
return !rangeType.isMarkedNullable() && getPrimitiveRangeElementType(rangeType) != null;
}
public static boolean isProgression(KotlinType rangeType) {
return !rangeType.isMarkedNullable() && getPrimitiveProgressionElementType(rangeType) != null;
}
@Nullable
private static PrimitiveType getPrimitiveRangeElementType(KotlinType rangeType) {
return getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE);
}
@Nullable
private static PrimitiveType getPrimitiveProgressionElementType(KotlinType rangeType) {
return getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE);
}
@Nullable
private static PrimitiveType getPrimitiveRangeOrProgressionElementType(
@NotNull KotlinType rangeOrProgression,
@NotNull ImmutableMap<FqName, PrimitiveType> map
) {
ClassifierDescriptor declarationDescriptor = rangeOrProgression.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor == null) return null;
FqNameUnsafe fqName = DescriptorUtils.getFqName(declarationDescriptor);
if (!fqName.isSafe()) return null;
return map.get(fqName.toSafe());
}
@Nullable
public static PrimitiveType getPrimitiveRangeOrProgressionElementType(@NotNull FqName rangeOrProgressionName) {
PrimitiveType result = RANGE_TO_ELEMENT_TYPE.get(rangeOrProgressionName);
return result != null ? result : PROGRESSION_TO_ELEMENT_TYPE.get(rangeOrProgressionName);
}
public static boolean isRangeOrProgression(@NotNull FqName className) {
return getPrimitiveRangeOrProgressionElementType(className) != null;
}
public static boolean isPrimitiveNumberRangeTo(CallableDescriptor rangeTo) {
if (!"rangeTo".equals(rangeTo.getName().asString())) return false;
if (!isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) return false;
return true;
}
private static boolean isPrimitiveRangeToExtension(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.getType());
}
public static boolean isPrimitiveNumberDownTo(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
ClassifierDescriptor extensionReceiverClassifier = extensionReceiver.getType().getConstructor().getDeclarationDescriptor();
if (!isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)) return false;
return true;
}
public static boolean isPrimitiveNumberUntil(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
ClassifierDescriptor extensionReceiverClassifier = extensionReceiver.getType().getConstructor().getDeclarationDescriptor();
if (!isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)) return false;
return true;
}
public static boolean isArrayOrPrimitiveArrayIndices(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
KotlinType extensionReceiverType = extensionReceiver.getType();
if (!KotlinBuiltIns.isArray(extensionReceiverType) && !KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)) return false;
return true;
}
public static boolean isCollectionIndices(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
KotlinType extensionReceiverType = extensionReceiver.getType();
if (!KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)) return false;
return true;
}
public static boolean isCharSequenceIndices(@NotNull CallableDescriptor descriptor) {
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
if (extensionReceiver == null) return false;
KotlinType extensionReceiverType = extensionReceiver.getType();
if (!KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)) return false;
return true;
}
public static boolean isPrimitiveRangeToExtension(@NotNull KtSimpleNameExpression operationReference, @NotNull BindingContext bindingContext) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt
.getResolvedCallWithAssert(operationReference, bindingContext);
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
/*
* Range is optimizable if
* 'in' receiver is expression 'rangeTo' from stdlib package
* and its argument has same primitive type as generic range parameter.
* For non-matching primitive types (e.g. int in double range)
* dispatch receiver will be null, because extension method will be called.
*/
if (!(receiver instanceof ExpressionReceiver)) return false;
ExpressionReceiver e = (ExpressionReceiver) receiver;
ResolvedCall<? extends CallableDescriptor> resolvedReceiver =
CallUtilKt.getResolvedCall(e.getExpression(), bindingContext);
if (resolvedReceiver == null) return false;
return isPrimitiveRangeToExtension(resolvedReceiver.getResultingDescriptor());
}
/*
* Checks whether for expression 'x in a..b' a..b is primitive integral range
* with same type as x.
*/
public static boolean isPrimitiveRangeSpecializationOfType(
@NotNull Type argumentType,
@NotNull KtExpression rangeExpression,
@NotNull BindingContext bindingContext
) {
if (rangeExpression instanceof KtBinaryExpression &&
((KtBinaryExpression) rangeExpression).getOperationReference().getReferencedNameElementType() == KtTokens.RANGE) {
KotlinType kotlinType = bindingContext.getType(rangeExpression);
assert kotlinType != null;
DeclarationDescriptor descriptor = kotlinType.getConstructor().getDeclarationDescriptor();
if (descriptor != null) {
FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
if (fqName.equals(KotlinBuiltIns.FQ_NAMES.longRange)) {
return argumentType == Type.LONG_TYPE;
}
if (fqName.equals(KotlinBuiltIns.FQ_NAMES.charRange) || fqName.equals(KotlinBuiltIns.FQ_NAMES.intRange)) {
return AsmUtil.isIntPrimitive(argumentType);
}
}
}
return false;
}
private static boolean isTopLevelInPackage(@NotNull CallableDescriptor descriptor, @NotNull String name, @NotNull String packageName) {
if (!name.equals(descriptor.getName().asString())) return false;
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (!(containingDeclaration instanceof PackageFragmentDescriptor)) return false;
String packageFqName = ((PackageFragmentDescriptor) containingDeclaration).getFqName().asString();
if (!packageName.equals(packageFqName)) return false;
return true;
}
}

View File

@@ -0,0 +1,242 @@
/*
* Copyright 2010-2017 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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.RANGES_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitiveNumberClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
val supportedRangeTypes = listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG)
private val RANGE_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
supportedRangeTypes.associateBy {
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Range"))
}
private val PROGRESSION_TO_ELEMENT_TYPE: Map<FqName, PrimitiveType> =
supportedRangeTypes.associateBy {
RANGES_PACKAGE_FQ_NAME.child(Name.identifier(it.typeName.toString() + "Progression"))
}
fun isPrimitiveRange(rangeType: KotlinType) =
!rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null
fun isPrimitiveProgression(rangeType: KotlinType) =
!rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null
fun getPrimitiveRangeElementType(rangeType: KotlinType): PrimitiveType? =
getPrimitiveRangeOrProgressionElementType(rangeType, RANGE_TO_ELEMENT_TYPE)
private fun getPrimitiveProgressionElementType(rangeType: KotlinType) =
getPrimitiveRangeOrProgressionElementType(rangeType, PROGRESSION_TO_ELEMENT_TYPE)
private fun getPrimitiveRangeOrProgressionElementType(
rangeOrProgression: KotlinType,
map: Map<FqName, PrimitiveType>
): PrimitiveType? {
val declarationDescriptor = rangeOrProgression.constructor.declarationDescriptor ?: return null
val fqName = DescriptorUtils.getFqName(declarationDescriptor).takeIf { it.isSafe } ?: return null
return map[fqName.toSafe()]
}
fun getRangeOrProgressionElementType(rangeType: KotlinType): KotlinType? {
val rangeTypeDescriptor = rangeType.constructor.declarationDescriptor ?: return null
val builtIns = rangeTypeDescriptor.builtIns
return when {
isTopLevelInPackage(rangeTypeDescriptor, "CharRange", "kotlin.ranges") -> builtIns.charType
isTopLevelInPackage(rangeTypeDescriptor, "IntRange", "kotlin.ranges") -> builtIns.intType
isTopLevelInPackage(rangeTypeDescriptor, "LongRange", "kotlin.ranges") -> builtIns.longType
isTopLevelInPackage(rangeTypeDescriptor, "CharProgression", "kotlin.ranges") -> builtIns.charType
isTopLevelInPackage(rangeTypeDescriptor, "IntProgression", "kotlin.ranges") -> builtIns.intType
isTopLevelInPackage(rangeTypeDescriptor, "LongProgression", "kotlin.ranges") -> builtIns.longType
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatRange", "kotlin.ranges") -> builtIns.floatType
isTopLevelInPackage(rangeTypeDescriptor, "ClosedDoubleRange", "kotlin.ranges") -> builtIns.doubleType
isTopLevelInPackage(rangeTypeDescriptor, "ClosedRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
isTopLevelInPackage(rangeTypeDescriptor, "ClosedFloatingPointRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
isTopLevelInPackage(rangeTypeDescriptor, "ComparableRange", "kotlin.ranges") -> rangeType.arguments.singleOrNull()?.type
else -> null
}
}
fun getPrimitiveRangeOrProgressionElementType(rangeOrProgressionName: FqName): PrimitiveType? =
RANGE_TO_ELEMENT_TYPE[rangeOrProgressionName] ?:
PROGRESSION_TO_ELEMENT_TYPE[rangeOrProgressionName]
fun isRangeOrProgression(className: FqName) =
getPrimitiveRangeOrProgressionElementType(className) != null
fun isPrimitiveNumberRangeTo(rangeTo: CallableDescriptor) =
"rangeTo" == rangeTo.name.asString() && isPrimitiveNumberClassDescriptor(rangeTo.containingDeclaration) ||
isPrimitiveRangeToExtension(rangeTo)
private fun isPrimitiveRangeToExtension(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
return KotlinBuiltIns.isPrimitiveType(extensionReceiver.type)
}
fun isPrimitiveNumberDownTo(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "downTo", "kotlin.ranges")) return false
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
}
fun isPrimitiveNumberUntil(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "until", "kotlin.ranges")) return false
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
val extensionReceiverClassifier = extensionReceiver.type.constructor.declarationDescriptor
return isPrimitiveNumberClassDescriptor(extensionReceiverClassifier)
}
fun isArrayOrPrimitiveArrayIndices(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
val extensionReceiverType = extensionReceiver.type
return KotlinBuiltIns.isArray(extensionReceiverType) || KotlinBuiltIns.isPrimitiveArray(extensionReceiverType)
}
fun isCollectionIndices(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.collections")) return false
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
val extensionReceiverType = extensionReceiver.type
return KotlinBuiltIns.isCollectionOrNullableCollection(extensionReceiverType)
}
fun isCharSequenceIndices(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "indices", "kotlin.text")) return false
val extensionReceiver = descriptor.extensionReceiverParameter ?: return false
val extensionReceiverType = extensionReceiver.type
return KotlinBuiltIns.isCharSequenceOrNullableCharSequence(extensionReceiverType)
}
fun isComparableRangeTo(descriptor: CallableDescriptor): Boolean {
if (!isTopLevelInPackage(descriptor, "rangeTo", "kotlin.ranges")) return false
val extensionReceiver = descriptor.original.extensionReceiverParameter ?: return false
val extensionReceiverTypeDescriptor = extensionReceiver.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
val upperBoundType = extensionReceiverTypeDescriptor.upperBounds.singleOrNull() ?: return false
val upperBoundClassDescriptor = upperBoundType.constructor.declarationDescriptor as? ClassDescriptor ?: return false
if (!isTopLevelInPackage(upperBoundClassDescriptor, "Comparable", "kotlin")) return false
return true
}
fun isClosedRangeContains(descriptor: CallableDescriptor): Boolean {
if (descriptor.name.asString() != "contains") return false
val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
if (!isTopLevelInPackage(containingClassDescriptor, "ClosedRange", "kotlin.ranges")) return false
return true
}
fun isPrimitiveRangeContains(descriptor: CallableDescriptor): Boolean {
if (descriptor.name.asString() != "contains") return false
val dispatchReceiverType = descriptor.dispatchReceiverParameter?.type ?: return false
if (!isPrimitiveRange(dispatchReceiverType)) return false
return true
}
fun isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(descriptor: CallableDescriptor): Boolean {
if (descriptor.name.asString() != "contains") return false
val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return false
val rangeElementType = getRangeOrProgressionElementType(extensionReceiverType) ?: return false
if (!isPrimitiveNumberType(rangeElementType)) return false
val argumentType = descriptor.valueParameters.singleOrNull()?.type ?: return false
if (!isPrimitiveNumberType(argumentType)) return false
return true
}
private fun isPrimitiveNumberType(type: KotlinType) =
KotlinBuiltIns.isByte(type) ||
KotlinBuiltIns.isShort(type) ||
KotlinBuiltIns.isInt(type) ||
KotlinBuiltIns.isChar(type) ||
KotlinBuiltIns.isLong(type) ||
KotlinBuiltIns.isFloat(type) ||
KotlinBuiltIns.isDouble(type)
fun isClosedFloatingPointRangeContains(descriptor: CallableDescriptor): Boolean {
if (descriptor.name.asString() != "contains") return false
val containingClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return false
if (!isTopLevelInPackage(containingClassDescriptor, "ClosedFloatingPointRange", "kotlin.ranges")) return false
return true
}
fun getClosedFloatingPointRangeElementType(rangeType: KotlinType): KotlinType? {
val classDescriptor = rangeType.constructor.declarationDescriptor as? ClassDescriptor ?: return null
if (!isTopLevelInPackage(classDescriptor, "ClosedFloatingPointRange", "kotlin.ranges")) return null
return rangeType.arguments.singleOrNull()?.type
}
private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String, packageName: String): Boolean {
if (name != descriptor.name.asString()) return false
val containingDeclaration = descriptor.containingDeclaration as? PackageFragmentDescriptor ?: return false
val packageFqName = containingDeclaration.fqName.asString()
return packageName == packageFqName
}
fun getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCallee: CallableDescriptor): Type {
val rangeType = rangeCallee.returnType!!
getPrimitiveRangeElementType(rangeType)?.let {
return AsmTypes.valueTypeForPrimitive(it)
}
getPrimitiveProgressionElementType(rangeType)?.let {
return AsmTypes.valueTypeForPrimitive(it)
}
getClosedFloatingPointRangeElementType(rangeType)?.let {
when {
KotlinBuiltIns.isDouble(it) -> return Type.DOUBLE_TYPE
KotlinBuiltIns.isFloat(it) -> return Type.FLOAT_TYPE
else -> {}
}
}
throw AssertionError("Unexpected range type: $rangeType")
}

View File

@@ -105,10 +105,14 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
}
@Override
protected void generateSyntheticParts() {
protected void generateSyntheticPartsBeforeBody() {
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
}
@Override
protected void generateSyntheticPartsAfterBody() {
}
@Override
protected void generateKotlinMetadataAnnotation() {
generateKotlinClassMetadataAnnotation(scriptDescriptor, true);

View File

@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen;
import com.intellij.psi.tree.IElementType;
import kotlin.Unit;
import kotlin.collections.ArraysKt;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@@ -27,8 +26,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
@@ -518,9 +515,11 @@ public abstract class StackValue {
descriptor
);
StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, callExtensionReceiver, true);
Type type = CallReceiver.calcType(resolvedCall, dispatchReceiverParameter, extensionReceiverParameter, codegen.typeMapper, callableMethod, codegen.getState());
assert type != null : "Could not map receiver type for " + resolvedCall;
return new CallReceiver(dispatchReceiver, extensionReceiver, type);
return CallReceiver.generateCallReceiver(
resolvedCall, codegen, callableMethod,
dispatchReceiverParameter, dispatchReceiver,
extensionReceiverParameter, extensionReceiver
);
}
return receiver;
}
@@ -569,14 +568,13 @@ public abstract class StackValue {
}
@Contract("null -> false")
private static boolean isLocalFunCall(@Nullable Callable callableMethod) {
static boolean isLocalFunCall(@Nullable Callable callableMethod) {
return callableMethod != null && callableMethod.getGenerateCalleeType() != null;
}
public static StackValue receiverWithoutReceiverArgument(StackValue receiverWithParameter) {
if (receiverWithParameter instanceof CallReceiver) {
CallReceiver callReceiver = (CallReceiver) receiverWithParameter;
return new CallReceiver(callReceiver.dispatchReceiver, none(), callReceiver.type);
return ((CallReceiver) receiverWithParameter).withoutReceiverArgument();
}
return receiverWithParameter;
}
@@ -1517,101 +1515,6 @@ public abstract class StackValue {
}
}
public static class CallReceiver extends StackValue {
private final StackValue dispatchReceiver;
private final StackValue extensionReceiver;
public CallReceiver(
@NotNull StackValue dispatchReceiver,
@NotNull StackValue extensionReceiver,
@NotNull Type type
) {
super(type, dispatchReceiver.canHaveSideEffects() || extensionReceiver.canHaveSideEffects());
this.dispatchReceiver = dispatchReceiver;
this.extensionReceiver = extensionReceiver;
}
@Nullable
public static Type calcType(
@NotNull ResolvedCall<?> resolvedCall,
@Nullable ReceiverParameterDescriptor dispatchReceiver,
@Nullable ReceiverParameterDescriptor extensionReceiver,
@NotNull KotlinTypeMapper typeMapper,
@Nullable Callable callableMethod,
@NotNull GenerationState state
) {
if (extensionReceiver != null) {
CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor();
if (descriptor instanceof PropertyDescriptor &&
// hackaround: boxing changes behaviour of T.javaClass intrinsic
state.getIntrinsics().getIntrinsic((PropertyDescriptor) descriptor) != JavaClassProperty.INSTANCE
) {
ReceiverParameterDescriptor receiverCandidate = descriptor.getExtensionReceiverParameter();
assert receiverCandidate != null;
return typeMapper.mapType(receiverCandidate.getType());
}
return callableMethod != null ? callableMethod.getExtensionReceiverType() : typeMapper.mapType(extensionReceiver.getType());
}
else if (dispatchReceiver != null) {
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (CodegenUtilKt.isJvmStaticInObjectOrClass(descriptor)) {
return Type.VOID_TYPE;
}
if (callableMethod != null) {
return callableMethod.getDispatchReceiverType();
}
// Extract the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have
// all the needed information, for example there's no way to find out whether or not a smart cast was applied to the receiver.
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container instanceof ClassDescriptor) {
return typeMapper.mapClass((ClassDescriptor) container);
}
return typeMapper.mapType(dispatchReceiver);
}
else if (isLocalFunCall(callableMethod)) {
return callableMethod.getGenerateCalleeType();
}
return Type.VOID_TYPE;
}
@Override
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
StackValue currentExtensionReceiver = extensionReceiver;
boolean hasExtensionReceiver = extensionReceiver != none();
if (extensionReceiver instanceof StackValue.SafeCall) {
currentExtensionReceiver.put(currentExtensionReceiver.type, v);
currentExtensionReceiver = StackValue.onStack(currentExtensionReceiver.type);
}
dispatchReceiver.put(hasExtensionReceiver ? dispatchReceiver.type : type, v);
currentExtensionReceiver
.moveToTopOfStack(hasExtensionReceiver ? type : currentExtensionReceiver.type, v, dispatchReceiver.type.getSize());
}
@Override
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
AsmUtil.dup(v, extensionReceiver.type, dispatchReceiver.type);
}
@NotNull
public StackValue getDispatchReceiver() {
return dispatchReceiver;
}
@NotNull
public StackValue getExtensionReceiver() {
return extensionReceiver;
}
}
public abstract static class StackValueWithSimpleReceiver extends StackValue {
public final boolean isStaticPut;

View File

@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName
interface WrappedAnnotated : Annotated {
val originalAnnotated: Annotated
@@ -34,10 +33,6 @@ class AnnotatedWithOnlyTargetedAnnotations(original: Annotated) : Annotated {
private class UseSiteTargetedAnnotations(private val additionalAnnotations: Annotations) : Annotations {
override fun isEmpty() = true
override fun findAnnotation(fqName: FqName) = null
override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations() = getAdditionalTargetedAnnotations()
override fun getAllAnnotations() = getAdditionalTargetedAnnotations()
@@ -48,4 +43,4 @@ class AnnotatedWithOnlyTargetedAnnotations(original: Annotated) : Annotated {
}
}
class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)
class AnnotatedSimple(annotations: Annotations) : AnnotatedImpl(annotations)

View File

@@ -413,4 +413,10 @@ fun extractReificationArgument(type: KotlinType): Pair<TypeParameterDescriptor,
}
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
function.initialSignatureDescriptor ?: function
function.initialSignatureDescriptor ?: function
fun ExpressionCodegen.generateCallReceiver(rangeCall: ResolvedCall<out CallableDescriptor>): StackValue =
generateReceiverValue(rangeCall.extensionReceiver ?: rangeCall.dispatchReceiver!!, false)
fun ExpressionCodegen.generateCallSingleArgument(rangeCall: ResolvedCall<out CallableDescriptor>): StackValue =
gen(ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!)

View File

@@ -111,12 +111,11 @@ class CoroutineTransformerMethodVisitor(
methodNode.instructions.apply {
val startLabel = LabelNode()
val defaultLabel = LabelNode()
val firstToInsertBefore = actualCoroutineStart
val tableSwitchLabel = LabelNode()
val lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
// tableswitch(this.label)
insertBefore(firstToInsertBefore,
insertBefore(actualCoroutineStart,
insnListOf(
*withInstructionAdapter { loadCoroutineSuspendedMarker() }.toArray(),
tableSwitchLabel,

View File

@@ -144,7 +144,7 @@ internal fun performRefinedTypeAnalysis(methodNode: MethodNode, thisName: String
}
})
val refinedFrames = Array(basicFrames.size) {
return Array(basicFrames.size) {
insnIndex ->
val current = Frame(basicFrames[insnIndex] ?: return@Array null)
@@ -158,8 +158,6 @@ internal fun performRefinedTypeAnalysis(methodNode: MethodNode, thisName: String
current
}
return refinedFrames
}
private fun AbstractInsnNode.isIntLoad() = opcode == Opcodes.ILOAD

View File

@@ -1,99 +0,0 @@
/*
* Copyright 2010-2017 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.forLoop
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.RangeCodegenUtil
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.org.objectweb.asm.Type
fun ExpressionCodegen.getForLoopGenerator(forExpression: KtForExpression) : AbstractForLoopGenerator {
getLoopRangeResolvedCall(forExpression, bindingContext)?.let { loopRangeCall ->
createOptimizedForLoopGeneratorOrNull(forExpression, loopRangeCall)?.let {
return it
}
}
val loopRange = forExpression.loopRange!!
val loopRangeType = bindingContext.getType(loopRange)!!
val asmLoopRangeType = asmType(loopRangeType)
return when {
asmLoopRangeType.sort == Type.ARRAY ->
ForInArrayLoopGenerator(this, forExpression)
RangeCodegenUtil.isRange(loopRangeType) ->
ForInRangeInstanceLoopGenerator(this, forExpression)
RangeCodegenUtil.isProgression(loopRangeType) ->
ForInProgressionExpressionLoopGenerator(this, forExpression)
isSubtypeOfCharSequence(loopRangeType, state.module.builtIns) ->
ForInCharSequenceLoopGenerator(this, forExpression)
else ->
IteratorForLoopGenerator(this, forExpression)
}
}
private fun isSubtypeOfCharSequence(type: KotlinType, builtIns: KotlinBuiltIns) =
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
private fun ExpressionCodegen.createOptimizedForLoopGeneratorOrNull(
forExpression: KtForExpression,
loopRangeCall: ResolvedCall<out CallableDescriptor>
): AbstractForLoopGenerator? {
val loopRangeCallee = loopRangeCall.resultingDescriptor
return when {
RangeCodegenUtil.isPrimitiveNumberRangeTo(loopRangeCallee) ->
ForInRangeLiteralLoopGenerator(this, forExpression, loopRangeCall)
RangeCodegenUtil.isPrimitiveNumberDownTo(loopRangeCallee) ->
ForInDownToProgressionLoopGenerator(this, forExpression, loopRangeCall)
RangeCodegenUtil.isPrimitiveNumberUntil(loopRangeCallee) ->
ForInUntilRangeLoopGenerator(this, forExpression, loopRangeCall)
RangeCodegenUtil.isArrayOrPrimitiveArrayIndices(loopRangeCallee) ->
ForInArrayIndicesRangeLoopGenerator(this, forExpression, loopRangeCall)
RangeCodegenUtil.isCollectionIndices(loopRangeCallee) ->
ForInCollectionIndicesRangeLoopGenerator(this, forExpression, loopRangeCall)
RangeCodegenUtil.isCharSequenceIndices(loopRangeCallee) ->
ForInCharSequenceIndicesRangeLoopGenerator(this, forExpression, loopRangeCall)
else -> null
}
}
private fun getLoopRangeResolvedCall(forExpression: KtForExpression, bindingContext: BindingContext): ResolvedCall<out CallableDescriptor>? {
val loopRange = KtPsiUtil.deparenthesize(forExpression.loopRange)
when (loopRange) {
is KtQualifiedExpression -> {
val qualifiedExpression = loopRange as KtQualifiedExpression?
val selector = qualifiedExpression!!.selectorExpression
if (selector is KtCallExpression || selector is KtSimpleNameExpression) {
return selector.getResolvedCall(bindingContext)
}
}
is KtSimpleNameExpression, is KtCallExpression -> return loopRange.getResolvedCall(bindingContext)
is KtBinaryExpression -> return loopRange.operationReference.getResolvedCall(bindingContext)
}
return null
}

View File

@@ -460,7 +460,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
val classId = classId
val bytes = state.inlineCache.classBytes.getOrPut(classId) { bytecode }
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, AsmUtil.asmTypeByClassId(classId))
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classId.asString())
}
assert(callableDescriptor is DeserializedCallableMemberDescriptor) { "Not a deserialized function or proper: " + callableDescriptor }
@@ -474,7 +474,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
throw IllegalStateException("Couldn't find declaration file for " + containerId)
}
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, AsmUtil.asmTypeByClassId(containerId)) ?: return null
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, containerId.asString()) ?: return null
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks

View File

@@ -135,7 +135,7 @@ class DefaultLambda(
classReader.b,
"<init>",
descriptor,
lambdaClassType)?.node
lambdaClassType.internalName)?.node
assert(constructor != null || capturedArgs.isEmpty()) {
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
@@ -164,7 +164,7 @@ class DefaultLambda(
classReader.b,
invokeMethod.name,
invokeMethod.descriptor,
lambdaClassType)!!
lambdaClassType.internalName)!!
if (needReification) {
//nested classes could also require reification

View File

@@ -619,11 +619,11 @@ class MethodInliner(
}
private fun wrapException(originalException: Throwable, node: MethodNode, errorSuffix: String): RuntimeException {
if (originalException is InlineException) {
return InlineException("$errorPrefix: $errorSuffix", originalException)
return if (originalException is InlineException) {
InlineException("$errorPrefix: $errorSuffix", originalException)
}
else {
return InlineException("$errorPrefix: $errorSuffix\nCause: ${node.nodeText}", originalException)
InlineException("$errorPrefix: $errorSuffix\nCause: ${node.nodeText}", originalException)
}
}
@@ -679,11 +679,11 @@ class MethodInliner(
localReturns.add(LocalReturn(returnInsn, insertBeforeInsn, sourceValueFrame))
if (returnInsn.opcode != Opcodes.RETURN) {
if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) {
returnVariableSize = 2
returnVariableSize = if (returnInsn.opcode == Opcodes.LRETURN || returnInsn.opcode == Opcodes.DRETURN) {
2
}
else {
returnVariableSize = 1
1
}
}
}
@@ -716,10 +716,9 @@ class MethodInliner(
"Captured field template should start with $CAPTURED_FIELD_FOLD_PREFIX prefix"
}
val fin = FieldInsnNode(node.opcode, node.owner, node.name.substring(3), node.desc)
val field = fieldRemapper.findField(fin) ?: throw IllegalStateException(
return fieldRemapper.findField(fin) ?: throw IllegalStateException(
"Couldn't find captured field ${node.owner}.${node.name} in ${fieldRemapper.originalLambdaInternalName}"
)
return field
}
private fun analyzeMethodNodeWithoutMandatoryTransformations(node: MethodNode): Array<Frame<SourceValue>?> {

View File

@@ -98,8 +98,8 @@ open class NestedSourceMapper(
override fun mapLineNumber(lineNumber: Int): Int {
val mappedLineNumber = visitedLines.get(lineNumber)
if (mappedLineNumber > 0) {
return mappedLineNumber
return if (mappedLineNumber > 0) {
mappedLineNumber
}
else {
val rangeForMapping =
@@ -111,7 +111,7 @@ open class NestedSourceMapper(
visitedLines.put(lineNumber, newLineNumber)
}
lastVisitedRange = rangeForMapping
return newLineNumber
newLineNumber
}
}

View File

@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -95,8 +94,6 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
private var context by Delegates.notNull<CodegenContext<*>>()
private var additionalInnerClasses = mutableListOf<ClassDescriptor>()
override val lookupLocation = KotlinLookupLocation(callElement)
@@ -167,15 +164,12 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
if (isLambda)
codegen.parentCodegen.className
else
state.typeMapper.mapImplementationOwner(descriptor).internalName,
if (isLambda) emptyList() else additionalInnerClasses,
isLambda
state.typeMapper.mapImplementationOwner(descriptor).internalName
)
val strategy = when (expression) {
is KtCallableReferenceExpression -> {
val callableReferenceExpression = expression
val receiverExpression = callableReferenceExpression.receiverExpression
val receiverExpression = expression.receiverExpression
val receiverType = if (receiverExpression != null && state.bindingContext.getType(receiverExpression) != null)
state.typeMapper.mapType(state.bindingContext.getType(receiverExpression)!!)
else
@@ -192,7 +186,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
FunctionReferenceGenerationStrategy(
state,
descriptor,
callableReferenceExpression.callableReference
expression.callableReference
.getResolvedCallWithAssert(state.bindingContext),
receiverType, null,
true
@@ -228,9 +222,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
internal val delegate: MemberCodegen<*>,
declaration: KtElement,
codegenContext: FieldOwnerContext<*>,
private val className: String,
private val parentAsInnerClasses: List<ClassDescriptor>,
private val isInlineLambdaCodegen: Boolean
private val className: String
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
override fun generateDeclaration() {
@@ -254,14 +246,6 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
return className
}
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
if (isInlineLambdaCodegen) {
super.addParentsToInnerClassesIfNeeded(innerClasses)
}
else {
innerClasses.addAll(parentAsInnerClasses)
}
}
}
override fun doCreateMethodNodeFromSource(
@@ -294,9 +278,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
implementationOwner.internalName,
additionalInnerClasses,
false
implementationOwner.internalName
)
if (element !is KtNamedFunction) {
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
@@ -407,25 +389,22 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
}
override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
context = getContext(functionDescriptor, functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile, additionalInnerClasses)
context = getContext(functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile)
}
companion object {
fun getContext(
descriptor: DeclarationDescriptor, innerDescriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?, additionalInners: MutableList<ClassDescriptor>
descriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?
): CodegenContext<*> {
if (descriptor is PackageFragmentDescriptor) {
//no inners
return PackageContext(descriptor, state.rootContext, null, sourceFile)
}
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
val parent = getContext(
container,
descriptor,
state,
sourceFile,
additionalInners
sourceFile
)
return when (descriptor) {
@@ -438,14 +417,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
)
}
is ClassDescriptor -> {
val kind =
if (DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor)
OwnerKind.DEFAULT_IMPLS
else OwnerKind.IMPLEMENTATION
additionalInners.addIfNotNull(
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
)
val kind = if (DescriptorUtils.isInterface(descriptor)) OwnerKind.DEFAULT_IMPLS else OwnerKind.IMPLEMENTATION
parent.intoClass(descriptor, kind, state)
}
is FunctionDescriptor -> {

View File

@@ -89,13 +89,12 @@ private const val INLINE_MARKER_FINALLY_START = "finallyStart"
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
private val INTRINSIC_ARRAY_CONSTRUCTOR_TYPE = AsmUtil.asmTypeByClassId(classId)
internal fun getMethodNode(
classData: ByteArray,
methodName: String,
methodDescriptor: String,
classType: Type
classInternalName: String
): SMAPAndMethodNode? {
val cr = ClassReader(classData)
var node: MethodNode? = null
@@ -137,12 +136,12 @@ internal fun getMethodNode(
return null
}
if (INTRINSIC_ARRAY_CONSTRUCTOR_TYPE == classType) {
if (classId.asString() == classInternalName) {
// Don't load source map for intrinsic array constructors
debugInfo[0] = null
}
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, lines[0], lines[1])
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classInternalName, lines[0], lines[1])
return SMAPAndMethodNode(node!!, smap)
}
@@ -287,9 +286,8 @@ internal fun getMarkedReturnLabelOrNull(returnInsn: AbstractInsnNode): String? {
}
val previous = returnInsn.previous
if (previous is MethodInsnNode) {
val marker = previous
if (NON_LOCAL_RETURN == marker.owner) {
return marker.name
if (NON_LOCAL_RETURN == previous.owner) {
return previous.name
}
}
return null
@@ -458,13 +456,12 @@ private fun isInlineMarker(insn: AbstractInsnNode, name: String?): Boolean {
return false
}
val methodInsnNode = insn
return insn.getOpcode() == Opcodes.INVOKESTATIC &&
methodInsnNode.owner == INLINE_MARKER_CLASS_NAME &&
insn.owner == INLINE_MARKER_CLASS_NAME &&
if (name != null)
methodInsnNode.name == name
insn.name == name
else
methodInsnNode.name == INLINE_MARKER_BEFORE_METHOD_NAME || methodInsnNode.name == INLINE_MARKER_AFTER_METHOD_NAME
insn.name == INLINE_MARKER_BEFORE_METHOD_NAME || insn.name == INLINE_MARKER_AFTER_METHOD_NAME
}
internal fun isBeforeInlineMarker(insn: AbstractInsnNode): Boolean {

View File

@@ -40,7 +40,7 @@ private inline fun <reified T> arrayOf(vararg elements: T): Array<T> = elements
private inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
val result = arrayOfNulls<T>(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result as Array<T>
@@ -48,7 +48,7 @@ private inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
val result = DoubleArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -56,7 +56,7 @@ private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
val result = FloatArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -64,7 +64,7 @@ private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
val result = LongArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -72,7 +72,7 @@ private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
val result = IntArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -80,7 +80,7 @@ private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
val result = CharArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -88,7 +88,7 @@ private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
val result = ShortArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -96,7 +96,7 @@ private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
val result = ByteArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result
@@ -104,7 +104,7 @@ private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
private inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
val result = BooleanArray(size)
for (i in 0..size - 1) {
for (i in result.indices) {
result[i] = init(i)
}
return result

View File

@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.codegen.CallableMethod
class StringPlus : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable =
createIntrinsicCallable(method) {
it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus",
it.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "stringPlus",
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;", false)
}
}

View File

@@ -232,17 +232,15 @@ class CapturedVarsOptimizationMethodTransformer : MethodTransformer() {
}
private fun findCleanInstructions(refValue: CapturedVarDescriptor, oldVarIndex: Int, instructions: InsnList): List<VarInsnNode> {
val cleanInstructions =
InsnSequence(instructions).filterIsInstance<VarInsnNode>().filter {
it.opcode == Opcodes.ASTORE && it.`var` == oldVarIndex
}.filter {
it.previous?.opcode == Opcodes.ACONST_NULL
}.filter {
val operationIndex = instructions.indexOf(it)
val localVariableNode = refValue.localVar!!
instructions.indexOf(localVariableNode.start) < operationIndex && operationIndex < instructions.indexOf(localVariableNode.end)
}.toList()
return cleanInstructions
return InsnSequence(instructions).filterIsInstance<VarInsnNode>().filter {
it.opcode == Opcodes.ASTORE && it.`var` == oldVarIndex
}.filter {
it.previous?.opcode == Opcodes.ACONST_NULL
}.filter {
val operationIndex = instructions.indexOf(it)
val localVariableNode = refValue.localVar!!
instructions.indexOf(localVariableNode.start) < operationIndex && operationIndex < instructions.indexOf(localVariableNode.end)
}.toList()
}
private fun rewrite() {

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2017 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.optimization
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicVerifier
class MethodVerifier(private val checkPoint: String) : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
try {
analyze(internalClassName, methodNode, BasicVerifier())
}
catch (e: Throwable) {
throw AssertionError("$checkPoint: incorrect bytecode", e)
}
}
}

View File

@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.codegen.optimization
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.boxing.FastPopBackwardPropagationTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.StackPeepholeOptimizationsTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantBoxingMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.boxing.PopBackwardPropagationTransformer
import org.jetbrains.kotlin.codegen.optimization.common.prepareForEmitting
@@ -47,7 +47,10 @@ class OptimizationMethodVisitor(
companion object {
private val MEMORY_LIMIT_BY_METHOD_MB = 50
private val MANDATORY_METHOD_TRANSFORMER = FixStackWithLabelNormalizationMethodTransformer()
private val MANDATORY_METHOD_TRANSFORMER = CompositeMethodTransformer(
FixStackWithLabelNormalizationMethodTransformer(),
MethodVerifier("AFTER mandatory stack transformations")
)
private val OPTIMIZATION_TRANSFORMER = CompositeMethodTransformer(
CapturedVarsOptimizationMethodTransformer(),
@@ -55,11 +58,12 @@ class OptimizationMethodVisitor(
RedundantCheckCastEliminationMethodTransformer(),
ConstantConditionEliminationMethodTransformer(),
RedundantBoxingMethodTransformer(),
FastPopBackwardPropagationTransformer(),
StackPeepholeOptimizationsTransformer(),
PopBackwardPropagationTransformer(),
DeadCodeEliminationMethodTransformer(),
RedundantGotoMethodTransformer(),
RedundantNopsCleanupMethodTransformer()
RedundantNopsCleanupMethodTransformer(),
MethodVerifier("AFTER optimizations")
)
fun canBeOptimized(node: MethodNode): Boolean {

View File

@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
import com.google.common.collect.ImmutableSet
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.RangeCodegenUtil
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.isRangeOrProgression
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
import org.jetbrains.kotlin.name.FqName
@@ -213,7 +213,7 @@ fun AbstractInsnNode.isIteratorMethodCallOfProgression(values: List<BasicValue>)
}
fun isProgressionClass(type: Type) =
RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(type.internalName))
isRangeOrProgression(buildFqNameByInternal(type.internalName))
fun AbstractInsnNode.isAreEqualIntrinsicForSameTypedBoxedValues(values: List<BasicValue>) =
isAreEqualIntrinsic() && areSameTypedBoxedValues(values)

View File

@@ -1,88 +0,0 @@
/*
* Copyright 2010-2017 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.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class FastPopBackwardPropagationTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
while (transformOnce(methodNode)) {
}
}
private fun transformOnce(methodNode: MethodNode): Boolean {
val toRemove = ArrayList<AbstractInsnNode>()
val toReplaceWithNop = ArrayList<AbstractInsnNode>()
val insns = methodNode.instructions.toArray()
for (i in 1 until insns.size) {
val insn = insns[i]
val prev = insns[i - 1]
when (insn.opcode) {
Opcodes.POP -> {
if (prev.isEliminatedByPop()) {
toReplaceWithNop.add(insn)
toRemove.add(prev)
}
}
Opcodes.POP2 -> {
if (prev.isEliminatedByPop2()) {
toReplaceWithNop.add(insn)
toRemove.add(prev)
}
else if (i > 1) {
val prev2 = insns[i - 2]
if (prev.isEliminatedByPop() && prev2.isEliminatedByPop()) {
toReplaceWithNop.add(insn)
toRemove.add(prev)
toRemove.add(prev2)
}
}
}
}
}
toReplaceWithNop.forEach { methodNode.instructions.set(it, InsnNode(Opcodes.NOP)) }
toRemove.forEach { methodNode.instructions.remove(it) }
return toReplaceWithNop.isNotEmpty() &&
toRemove.isNotEmpty()
}
private fun AbstractInsnNode.isEliminatedByPop() =
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
opcode == Opcodes.FLOAD ||
opcode == Opcodes.ALOAD ||
isUnitInstance() ||
opcode == Opcodes.DUP
private fun AbstractInsnNode.isEliminatedByPop2() =
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1 ||
opcode == Opcodes.LLOAD ||
opcode == Opcodes.DLOAD ||
opcode == Opcodes.DUP2
}

View File

@@ -17,8 +17,10 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.debugText
import org.jetbrains.kotlin.codegen.optimization.common.isLoadOperation
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.fixStack.peekWords
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.removeNodeGetNext
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
@@ -74,46 +76,84 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
postprocessNops()
}
private fun analyzeMethodBody(): Array<out Frame<SourceValue>?> =
Analyzer<SourceValue>(object : SourceInterpreter() {
override fun naryOperation(insn: AbstractInsnNode, values: MutableList<out SourceValue>): SourceValue {
for (value in values) {
value.insns.markAsDontTouch()
}
return super.naryOperation(insn, values)
}
private fun analyzeMethodBody(): Array<out Frame<SourceValue>?> {
val frames = Analyzer<SourceValue>(HazardsTrackingInterpreter()).analyze("fake", methodNode)
override fun copyOperation(insn: AbstractInsnNode, value: SourceValue): SourceValue {
value.insns.markAsDontTouch()
return super.copyOperation(insn, value)
}
postprocessDupNxM(frames)
override fun unaryOperation(insn: AbstractInsnNode, value: SourceValue): SourceValue {
if (insn.opcode != Opcodes.CHECKCAST && !insn.isPrimitiveTypeConversion()) {
value.insns.markAsDontTouch()
}
return super.unaryOperation(insn, value)
}
return frames
}
override fun binaryOperation(insn: AbstractInsnNode, value1: SourceValue, value2: SourceValue): SourceValue {
value1.insns.markAsDontTouch()
value2.insns.markAsDontTouch()
return super.binaryOperation(insn, value1, value2)
}
private fun postprocessDupNxM(frames: Array<out Frame<SourceValue>?>) {
val insns = methodNode.instructions.toArray()
for (i in frames.indices) {
val frame = frames[i] ?: continue
val insn = insns[i]
override fun ternaryOperation(insn: AbstractInsnNode, value1: SourceValue, value2: SourceValue, value3: SourceValue): SourceValue {
value1.insns.markAsDontTouch()
value2.insns.markAsDontTouch()
value3.insns.markAsDontTouch()
return super.ternaryOperation(insn, value1, value2, value3)
when (insn.opcode) {
Opcodes.DUP_X1 -> {
val top2 = frame.peekWords(1, 1) ?: throwIncorrectBytecode(insn, frame)
top2.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP2_X1 -> {
val top3 = frame.peekWords(2, 1) ?: throwIncorrectBytecode(insn, frame)
top3.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP_X2 -> {
val top3 = frame.peekWords(1, 2) ?: throwIncorrectBytecode(insn, frame)
top3.forEach { it.insns.markAsDontTouch() }
}
Opcodes.DUP2_X2 -> {
val top4 = frame.peekWords(2, 2) ?: throwIncorrectBytecode(insn, frame)
top4.forEach { it.insns.markAsDontTouch() }
}
}
}
}
private fun Collection<AbstractInsnNode>.markAsDontTouch() {
forEach {
dontTouchInsnIndices[insnList.indexOf(it)] = true
}
}
}).analyze("fake", methodNode)
private fun throwIncorrectBytecode(insn: AbstractInsnNode?, frame: Frame<SourceValue>): Nothing {
throw AssertionError("Incorrect bytecode at ${methodNode.instructions.indexOf(insn)}: ${insn.debugText} $frame")
}
private inner class HazardsTrackingInterpreter : SourceInterpreter() {
override fun naryOperation(insn: AbstractInsnNode, values: MutableList<out SourceValue>): SourceValue {
for (value in values) {
value.insns.markAsDontTouch()
}
return super.naryOperation(insn, values)
}
override fun copyOperation(insn: AbstractInsnNode, value: SourceValue): SourceValue {
value.insns.markAsDontTouch()
return super.copyOperation(insn, value)
}
override fun unaryOperation(insn: AbstractInsnNode, value: SourceValue): SourceValue {
if (insn.opcode != Opcodes.CHECKCAST && !insn.isPrimitiveTypeConversion()) {
value.insns.markAsDontTouch()
}
return super.unaryOperation(insn, value)
}
override fun binaryOperation(insn: AbstractInsnNode, value1: SourceValue, value2: SourceValue): SourceValue {
value1.insns.markAsDontTouch()
value2.insns.markAsDontTouch()
return super.binaryOperation(insn, value1, value2)
}
override fun ternaryOperation(insn: AbstractInsnNode, value1: SourceValue, value2: SourceValue, value3: SourceValue): SourceValue {
value1.insns.markAsDontTouch()
value2.insns.markAsDontTouch()
value3.insns.markAsDontTouch()
return super.ternaryOperation(insn, value1, value2, value3)
}
}
private fun Collection<AbstractInsnNode>.markAsDontTouch() {
forEach {
dontTouchInsnIndices[insnList.indexOf(it)] = true
}
}
private fun computeTransformations() {

View File

@@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.codegen.RangeCodegenUtil;
import org.jetbrains.kotlin.codegen.RangeCodegenUtilKt;
import org.jetbrains.kotlin.codegen.intrinsics.IteratorNext;
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue;
import org.jetbrains.kotlin.name.FqName;
@@ -32,7 +32,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
private final static ImmutableMap<String, Type> VALUES_TYPENAME_TO_TYPE;
static {
ImmutableMap.Builder<String, Type> builder = ImmutableMap.builder();
for (PrimitiveType primitiveType : RangeCodegenUtil.supportedRangeTypes()) {
for (PrimitiveType primitiveType : RangeCodegenUtilKt.getSupportedRangeTypes()) {
builder.put(primitiveType.getTypeName().asString(), Type.getType(JvmPrimitiveType.get(primitiveType).getDesc()));
}
VALUES_TYPENAME_TO_TYPE = builder.build();
@@ -41,7 +41,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
private static final ImmutableMap<PrimitiveType, ProgressionIteratorBasicValue> ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE;
static {
ImmutableMap.Builder<PrimitiveType, ProgressionIteratorBasicValue> builder = ImmutableMap.builder();
for (PrimitiveType elementType : RangeCodegenUtil.supportedRangeTypes()) {
for (PrimitiveType elementType : RangeCodegenUtilKt.getSupportedRangeTypes()) {
builder.put(elementType, new ProgressionIteratorBasicValue(elementType.getTypeName().asString()));
}
ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE = builder.build();
@@ -67,7 +67,7 @@ public class ProgressionIteratorBasicValue extends StrictBasicValue {
@Nullable
public static ProgressionIteratorBasicValue byProgressionClassType(@NotNull Type progressionClassType) {
FqName classFqName = new FqName(progressionClassType.getClassName());
PrimitiveType elementType = RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(classFqName);
PrimitiveType elementType = RangeCodegenUtilKt.getPrimitiveRangeOrProgressionElementType(classFqName);
return ITERATOR_VALUE_BY_ELEMENT_PRIMITIVE_TYPE.get(elementType);
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2010-2017 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.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.InsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class StackPeepholeOptimizationsTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
while (transformOnce(methodNode)) {
}
}
private fun transformOnce(methodNode: MethodNode): Boolean {
val actions = ArrayList<(InsnList) -> Unit>()
val insns = methodNode.instructions.toArray()
forInsn@ for (i in 1 until insns.size) {
val insn = insns[i]
val prev = insn.previous
val prevNonNop = insn.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue@forInsn
when (insn.opcode) {
Opcodes.POP -> {
when {
prevNonNop.isEliminatedByPop() -> actions.add {
it.set(insn, InsnNode(Opcodes.NOP))
it.remove(prevNonNop)
}
prevNonNop.opcode == Opcodes.DUP_X1 -> actions.add {
it.remove(insn)
it.set(prevNonNop, InsnNode(Opcodes.SWAP))
}
}
}
Opcodes.SWAP -> {
val prevNonNop2 = prevNonNop.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue@forInsn
if (prevNonNop.isPurePushOfSize1() && prevNonNop2.isPurePushOfSize1()) {
actions.add {
it.remove(insn)
it.set(prevNonNop, prevNonNop2.clone(emptyMap()))
it.set(prevNonNop2, prevNonNop.clone(emptyMap()))
}
}
}
Opcodes.I2L -> {
when (prevNonNop.opcode) {
Opcodes.ICONST_0 -> actions.add {
it.remove(insn)
it.set(prevNonNop, InsnNode(Opcodes.LCONST_0))
}
Opcodes.ICONST_1 -> actions.add {
it.remove(insn)
it.set(prevNonNop, InsnNode(Opcodes.LCONST_1))
}
}
}
Opcodes.POP2 -> {
if (prevNonNop.isEliminatedByPop2()) {
actions.add {
it.set(insn, InsnNode(Opcodes.NOP))
it.remove(prevNonNop)
}
}
else if (i > 1) {
val prevNonNop2 = prevNonNop.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue@forInsn
if (prevNonNop.isEliminatedByPop() && prevNonNop2.isEliminatedByPop()) {
actions.add {
it.set(insn, InsnNode(Opcodes.NOP))
it.remove(prevNonNop)
it.remove(prevNonNop2)
}
}
}
}
Opcodes.NOP ->
if (prev.opcode == Opcodes.NOP) {
actions.add {
it.remove(prev)
}
}
}
}
actions.forEach { it(methodNode.instructions) }
return actions.isNotEmpty()
}
private fun AbstractInsnNode.isEliminatedByPop() =
isPurePushOfSize1() ||
opcode == Opcodes.DUP
private fun AbstractInsnNode.isPurePushOfSize1(): Boolean =
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
opcode == Opcodes.FLOAD ||
opcode == Opcodes.ALOAD ||
isUnitInstance()
private fun AbstractInsnNode.isEliminatedByPop2() =
isPurePushOfSize2() ||
opcode == Opcodes.DUP2
private fun AbstractInsnNode.isPurePushOfSize2(): Boolean =
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1 ||
opcode == Opcodes.LLOAD ||
opcode == Opcodes.DLOAD
}

View File

@@ -142,20 +142,20 @@ internal class FixStackAnalyzer(
}
override fun pop(): BasicValue {
if (extraStack.isNotEmpty()) {
return extraStack.pop()
return if (extraStack.isNotEmpty()) {
extraStack.pop()
}
else {
return super.pop()
super.pop()
}
}
override fun getStack(i: Int): BasicValue {
if (i < super.getMaxStackSize()) {
return super.getStack(i)
return if (i < super.getMaxStackSize()) {
super.getStack(i)
}
else {
return extraStack[i - maxStackSize]
extraStack[i - maxStackSize]
}
}
}

View File

@@ -28,6 +28,31 @@ fun <V : Value> Frame<V>.top(): V? =
fun <V : Value> Frame<V>.peek(offset: Int): V? =
if (stackSize > offset) getStack(stackSize - offset - 1) else null
private fun <V : Value> Frame<V>.peekWordsTo(dest: MutableList<V>, size: Int, offset0: Int = 0): Int {
var offset = offset0
var totalSize = 0
while (totalSize < size) {
val value = peek(offset++) ?: return -1
dest.add(value)
totalSize += value.size
}
if (totalSize > size) return -1
return offset
}
fun <V : Value> Frame<V>.peekWords(size: Int): List<V>? {
val result = ArrayList<V>(size)
return if (peekWordsTo(result, size) < 0) null else result
}
fun <V : Value> Frame<V>.peekWords(size1: Int, size2: Int): List<V>? {
val result = ArrayList<V>(size1 + size2)
val offset = peekWordsTo(result, size1)
if (offset < 0) return null
if (peekWordsTo(result, size2, offset) < 0) return null
return result
}
class SavedStackDescriptor(
val savedValues: List<BasicValue>,
val firstLocalVarIndex: Int

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
abstract class AbstractBoundedValue(
protected val codegen: ExpressionCodegen,
protected val rangeCall: ResolvedCall<out CallableDescriptor>,
override val isLowInclusive: Boolean = true,
override val isHighInclusive: Boolean = true
) : BoundedValue {
override val instanceType: Type = codegen.asmType(rangeCall.resultingDescriptor.returnType!!)
override fun putInstance(v: InstructionAdapter, type: Type) {
codegen.invokeFunction(rangeCall.call, rangeCall, StackValue.none()).put(type, v)
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.range.forLoop.ForInArrayIndicesRangeLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
override fun getBoundedValue(codegen: ExpressionCodegen) =
object : AbstractBoundedValue(codegen, rangeCall, isHighInclusive = false) {
override fun putHighLow(v: InstructionAdapter, type: Type) {
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.arraylength()
StackValue.coerce(Type.INT_TYPE, type, v)
StackValue.constant(0, asmElementType).put(type, v)
}
}
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInArrayLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class ArrayRangeValue : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInArrayLoopGenerator(codegen, forExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue {
protected abstract fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>): Boolean
protected abstract fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression, resolvedCall: ResolvedCall<out CallableDescriptor>): InExpressionGenerator
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator {
val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
return if (isIntrinsicInCall(resolvedCall))
createIntrinsicInExpressionGenerator(codegen, operatorReference, resolvedCall)
else
CallBasedInExpressionGenerator(codegen, operatorReference)
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCharSequenceIndicesRangeLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
override fun getBoundedValue(codegen: ExpressionCodegen) =
object : AbstractBoundedValue(codegen, rangeCall, isHighInclusive = false) {
override fun putHighLow(v: InstructionAdapter, type: Type) {
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.invokeinterface("java/lang/CharSequence", "length", "()I")
StackValue.coerce(Type.INT_TYPE, type, v)
StackValue.constant(0, asmElementType).put(type, v)
}
}
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCharSequenceLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class CharSequenceRangeValue : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCharSequenceLoopGenerator(codegen, forExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.range.forLoop.ForInCollectionIndicesRangeLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
override fun getBoundedValue(codegen: ExpressionCodegen) =
object : AbstractBoundedValue(codegen, rangeCall, isHighInclusive = false) {
override fun putHighLow(v: InstructionAdapter, type: Type) {
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.invokeinterface("java/util/Collection", "size", "()I")
StackValue.coerce(Type.INT_TYPE, type, v)
StackValue.constant(0, asmElementType).put(type, v)
}
}
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall)
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.isClosedRangeContains
import org.jetbrains.kotlin.codegen.range.forLoop.IteratorForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeOfComparableExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class ComparableRangeLiteralRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
) : CallIntrinsicRangeValue(rangeCall) {
private val boundedValue = SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
IteratorForLoopGenerator(codegen, forExpression)
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
override fun createIntrinsicInExpressionGenerator(
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
) = InContinuousRangeOfComparableExpressionGenerator(operatorReference, boundedValue)
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDownToProgressionLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = codegen.generateCallSingleArgument(rangeCall),
highBound = codegen.generateCallReceiver(rangeCall)
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDownToProgressionLoopGenerator(codegen, forExpression, rangeCall)
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.IteratorForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class IterableRangeValue : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
IteratorForLoopGenerator(codegen, forExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InPrimitiveContinuousRangeExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): CallIntrinsicRangeValue(rangeCall) {
protected val asmElementType = getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCall.resultingDescriptor)
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
resolvedCallForIn.resultingDescriptor.let {
isPrimitiveRangeContains(it) ||
isClosedFloatingPointRangeContains(it) ||
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
}
override fun createIntrinsicInExpressionGenerator(
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
): InExpressionGenerator {
val comparisonGenerator = getComparisonGeneratorForRangeContainsCall(codegen, resolvedCall)
return if (comparisonGenerator != null)
InPrimitiveContinuousRangeExpressionGenerator(operatorReference, getBoundedValue(codegen), comparisonGenerator)
else
CallBasedInExpressionGenerator(codegen, operatorReference)
}
protected abstract fun getBoundedValue(codegen: ExpressionCodegen): BoundedValue
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeLiteralLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class PrimitiveNumberRangeLiteralRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall)
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInUntilRangeLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInUntilRangeLoopGenerator(codegen, forExpression, rangeCall)
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInProgressionExpressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class PrimitiveProgressionRangeValue : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInProgressionExpressionLoopGenerator(codegen, forExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeInstanceLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class PrimitiveRangeRangeValue : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeInstanceLoopGenerator(codegen, forExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
interface RangeValue {
fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator
fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator
}
interface BoundedValue {
val instanceType: Type
fun putInstance(v: InstructionAdapter, type: Type)
// It is necessary to maintain the proper evaluation order as of Kotlin 1.0 and 1.1
// to evaluate range bounds left to right and put them on stack as 'high; low'.
fun putHighLow(v: InstructionAdapter, type: Type)
val isLowInclusive: Boolean
val isHighInclusive: Boolean
}
fun BoundedValue.asStackValue(): StackValue =
object : StackValue(instanceType) {
override fun putSelector(type: Type, v: InstructionAdapter) {
putInstance(v, type)
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.org.objectweb.asm.Type
fun ExpressionCodegen.createRangeValueForExpression(rangeExpression: KtExpression): RangeValue {
// NB when you implement a new intrinsic RangeValue,
// also look into org.jetbrains.kotlin.generators.tests and update related testData generators
// (e.g., GenerateInRangeExpressionTestData).
getResolvedCallForRangeExpression(bindingContext, rangeExpression)?.let {
createIntrinsifiedRangeValueOrNull(it)?.let {
return it
}
}
val rangeType = bindingContext.getType(rangeExpression)!!
val asmRangeType = asmType(rangeType)
return when {
asmRangeType.sort == Type.ARRAY ->
ArrayRangeValue()
isPrimitiveRange(rangeType) ->
PrimitiveRangeRangeValue()
isPrimitiveProgression(rangeType) ->
PrimitiveProgressionRangeValue()
isSubtypeOfCharSequence(rangeType, state.module.builtIns) ->
CharSequenceRangeValue()
else ->
IterableRangeValue()
}
}
private fun isSubtypeOfCharSequence(type: KotlinType, builtIns: KotlinBuiltIns) =
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
private fun getResolvedCallForRangeExpression(
bindingContext: BindingContext,
rangeExpression: KtExpression
): ResolvedCall<out CallableDescriptor>? {
val expression = KtPsiUtil.deparenthesize(rangeExpression) ?: return null
return when (expression) {
is KtQualifiedExpression ->
expression.selectorExpression.let { selector ->
if (selector is KtCallExpression || selector is KtSimpleNameExpression)
selector.getResolvedCall(bindingContext)
else
null
}
is KtSimpleNameExpression, is KtCallExpression ->
expression.getResolvedCall(bindingContext)
is KtBinaryExpression ->
expression.operationReference.getResolvedCall(bindingContext)
else ->
null
}
}
private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue? {
val rangeCallee = rangeCall.resultingDescriptor
return when {
isPrimitiveNumberRangeTo(rangeCallee) ->
PrimitiveNumberRangeLiteralRangeValue(rangeCall)
isPrimitiveNumberDownTo(rangeCallee) ->
DownToProgressionRangeValue(rangeCall)
isPrimitiveNumberUntil(rangeCallee) ->
PrimitiveNumberUntilRangeValue(rangeCall)
isArrayOrPrimitiveArrayIndices(rangeCallee) ->
ArrayIndicesRangeValue(rangeCall)
isCollectionIndices(rangeCallee) ->
CollectionIndicesRangeValue(rangeCall)
isCharSequenceIndices(rangeCallee) ->
CharSequenceIndicesRangeValue(rangeCall)
isComparableRangeTo(rangeCallee) ->
ComparableRangeLiteralRangeValue(this, rangeCall)
else ->
null
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2010-2017 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.range
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class SimpleBoundedValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
private val lowBound: StackValue,
isLowInclusive: Boolean,
private val highBound: StackValue,
isHighInclusive: Boolean
): AbstractBoundedValue(codegen, rangeCall, isLowInclusive, isHighInclusive) {
constructor(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
isLowInclusive: Boolean = true,
isHighInclusive: Boolean = true
) : this(
codegen,
rangeCall,
codegen.generateCallReceiver(rangeCall),
isLowInclusive,
codegen.generateCallSingleArgument(rangeCall),
isHighInclusive
)
constructor(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
lowBound: StackValue,
highBound: StackValue
) : this(codegen, rangeCall, lowBound, true, highBound, true)
override fun putHighLow(v: InstructionAdapter, type: Type) {
if (!lowBound.canHaveSideEffects() || !highBound.canHaveSideEffects()) {
highBound.put(type, v)
lowBound.put(type, v)
}
else {
lowBound.put(type, v)
highBound.put(type, v)
AsmUtil.swap(v, type, type)
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2010-2017 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.range.comparison
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.getRangeOrProgressionElementType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
interface ComparisonGenerator {
val comparedType: Type
fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label)
fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label)
fun jumpIfGreater(v: InstructionAdapter, label: Label)
fun jumpIfLess(v: InstructionAdapter, label: Label)
}
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
when {
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
type == Type.LONG_TYPE -> LongComparisonGenerator
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
}
fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call: ResolvedCall<out CallableDescriptor>): ComparisonGenerator? {
val descriptor = call.resultingDescriptor
val receiverType = descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type ?: return null
val elementType = getRangeOrProgressionElementType(receiverType) ?: return null
val valueParameterType = descriptor.valueParameters.singleOrNull()?.type ?: return null
val asmElementType = codegen.asmType(elementType)
val asmValueParameterType = codegen.asmType(valueParameterType)
return when {
asmElementType == asmValueParameterType ->
getComparisonGeneratorForPrimitiveType(asmElementType)
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType.isRepresentedAsPrimitiveInt() ->
IntComparisonGenerator
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType == Type.LONG_TYPE ||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
LongComparisonGenerator
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
asmElementType == Type.DOUBLE_TYPE && asmValueParameterType == Type.FLOAT_TYPE ->
DoubleComparisonGenerator
else -> null
}
}
private fun Type.isRepresentedAsPrimitiveInt() =
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2010-2017 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.range.comparison
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
sealed class FloatingPointComparisonGenerator(override val comparedType: Type): ComparisonGenerator {
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.cmpl(comparedType)
v.ifge(label)
}
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
v.cmpg(comparedType)
v.ifle(label)
}
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
v.cmpl(comparedType)
v.ifgt(label)
}
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
v.cmpg(comparedType)
v.iflt(label)
}
}
object FloatComparisonGenerator : FloatingPointComparisonGenerator(Type.FLOAT_TYPE)
object DoubleComparisonGenerator : FloatingPointComparisonGenerator(Type.DOUBLE_TYPE)

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2010-2017 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.range.comparison
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
object IntComparisonGenerator : ComparisonGenerator {
override val comparedType: Type = Type.INT_TYPE
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.ificmpge(label)
}
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
v.ificmple(label)
}
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
v.ificmpgt(label)
}
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
v.ificmplt(label)
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2010-2017 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.range.comparison
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
object LongComparisonGenerator : ComparisonGenerator {
override val comparedType: Type = Type.LONG_TYPE
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.lcmp()
v.ifge(label)
}
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
v.lcmp()
v.ifle(label)
}
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
v.lcmp()
v.ifgt(label)
}
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
v.lcmp()
v.iflt(label)
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2010-2017 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.range.comparison
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
object ObjectComparisonGenerator : ComparisonGenerator {
override val comparedType: Type = Type.getObjectType("java/lang/Comparable")
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
invokeCompare(v)
v.ifge(label)
}
override fun jumpIfLessOrEqual(v: InstructionAdapter, label: Label) {
invokeCompare(v)
v.ifle(label)
}
override fun jumpIfGreater(v: InstructionAdapter, label: Label) {
invokeCompare(v)
v.ifgt(label)
}
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
invokeCompare(v)
v.iflt(label)
}
private fun invokeCompare(v: InstructionAdapter) {
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I")
}
}

View File

@@ -14,10 +14,9 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
@@ -25,15 +24,7 @@ import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForInExclusiveRangeLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
) : AbstractForInRangeLoopGenerator(codegen, forExpression) {
protected abstract fun generateFrom(): StackValue
protected abstract fun generateTo(): StackValue
override fun storeRangeStartAndEnd() {
loopParameter().store(generateFrom(), v)
StackValue.local(endVar, asmElementType).store(generateTo(), v)
}
) : AbstractForInRangeWithGivenBoundsLoopGenerator(codegen, forExpression) {
override fun checkEmptyLoop(loopExit: Label) {}
override fun checkPreCondition(loopExit: Label) {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
@@ -24,38 +24,36 @@ import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
class ForInProgressionExpressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression)
{
private var incrementVar: Int = 0
private var incrementType: Type? = null
protected var incrementVar: Int = -1
protected val asmLoopRangeType: Type
protected val incrementType: Type
init {
val loopRangeType = bindingContext.getType(forExpression.loopRange!!)!!
asmLoopRangeType = codegen.asmType(loopRangeType)
val incrementProp = loopRangeType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND)
assert(incrementProp.size == 1) { loopRangeType.toString() + " " + incrementProp.size }
incrementType = codegen.asmType(incrementProp.iterator().next().type)
}
override fun beforeLoop() {
super.beforeLoop()
incrementVar = createLoopTempVariable(asmElementType)
val loopRangeType = bindingContext.getType(forExpression.loopRange!!)!!
val asmLoopRangeType = codegen.asmType(loopRangeType)
val incrementProp = loopRangeType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND)
assert(incrementProp.size == 1) { loopRangeType.toString() + " " + incrementProp.size }
incrementType = codegen.asmType(incrementProp.iterator().next().type)
codegen.gen(forExpression.loopRange, asmLoopRangeType)
v.dup()
v.dup()
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType,
loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType!!, incrementType!!, incrementVar)
storeProgressionParametersToLocalVars()
}
protected abstract fun storeProgressionParametersToLocalVars()
override fun checkEmptyLoop(loopExit: Label) {
loopParameter().put(asmElementType, v)
v.load(endVar, asmElementType)
v.load(incrementVar, incrementType!!)
v.load(incrementVar, incrementType)
val negativeIncrement = Label()
val afterIf = Label()
@@ -106,4 +104,4 @@ class ForInProgressionExpressionLoopGenerator(codegen: ExpressionCodegen, forExp
loopParameter.store(StackValue.onStack(asmElementType), v)
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
@@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForLoopGenerator(codegen, forExpression)
{
protected var endVar: Int = 0
protected var endVar: Int = -1
private var loopParameter: StackValue? = null

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2010-2017 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.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.KtForExpression
abstract class AbstractForInRangeWithGivenBoundsLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
step: Int = 1
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
protected abstract fun generateFrom(): StackValue
protected abstract fun generateTo(): StackValue
override fun storeRangeStartAndEnd() {
loopParameter().store(generateFrom(), v)
StackValue.local(endVar, asmElementType).store(generateTo(), v)
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
@@ -30,8 +30,8 @@ import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForLoopGenerator(
protected val codegen: ExpressionCodegen,
val forExpression: KtForExpression
) {
override val forExpression: KtForExpression
) : ForLoopGenerator {
protected val bindingContext = codegen.bindingContext
protected val v = codegen.v!!
@@ -42,7 +42,7 @@ abstract class AbstractForLoopGenerator(
protected val elementType: KotlinType = bindingContext.getElementType(forExpression)
protected val asmElementType: Type = codegen.asmType(elementType)
protected var loopParameterVar: Int = 0
protected var loopParameterVar: Int = -1
protected lateinit var loopParameterType: Type
private fun BindingContext.getElementType(forExpression: KtForExpression): KotlinType {
@@ -52,7 +52,7 @@ abstract class AbstractForLoopGenerator(
return nextCall.resultingDescriptor.returnType!!
}
open fun beforeLoop() {
override fun beforeLoop() {
val loopParameter = forExpression.loopParameter ?: return
val multiParameter = loopParameter.destructuringDeclaration
if (multiParameter != null) {
@@ -75,11 +75,7 @@ abstract class AbstractForLoopGenerator(
}
}
abstract fun checkEmptyLoop(loopExit: Label)
abstract fun checkPreCondition(loopExit: Label)
fun beforeBody() {
override fun beforeBody() {
assignToLoopParameter()
v.mark(loopParameterStartLabel)
@@ -118,7 +114,7 @@ abstract class AbstractForLoopGenerator(
protected abstract fun checkPostConditionAndIncrement(loopExit: Label)
fun body() {
override fun body() {
codegen.generateLoopBody(forExpression.body)
}
@@ -132,7 +128,7 @@ abstract class AbstractForLoopGenerator(
return varIndex
}
fun afterBody(loopExit: Label) {
override fun afterBody(loopExit: Label) {
codegen.markStartLineNumber(forExpression)
checkPostConditionAndIncrement(loopExit)
@@ -140,7 +136,7 @@ abstract class AbstractForLoopGenerator(
v.mark(bodyEnd)
}
fun afterLoop() {
override fun afterLoop() {
for (task in leaveVariableTasks.asReversed()) {
task.run()
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtForExpression

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.psi.KtForExpression

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtForExpression

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtForExpression

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
@@ -27,12 +27,11 @@ class ForInDownToProgressionLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
loopRangeCall: ResolvedCall<*>
) : AbstractForInRangeLoopGenerator(codegen, forExpression, -1) {
) : AbstractForInRangeWithGivenBoundsLoopGenerator(codegen, forExpression, -1) {
private val from: ReceiverValue = loopRangeCall.extensionReceiver!!
private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(loopRangeCall)!!
override fun storeRangeStartAndEnd() {
loopParameter().store(codegen.generateReceiverValue(from, false), v)
StackValue.local(endVar, asmElementType).store(codegen.gen(to), v)
}
override fun generateFrom(): StackValue = codegen.generateReceiverValue(from, false)
override fun generateTo(): StackValue = codegen.gen(to)
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2010-2017 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.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtForExpression
class ForInProgressionExpressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForInProgressionLoopGenerator(codegen, forExpression)
{
override fun storeProgressionParametersToLocalVars() {
codegen.gen(forExpression.loopRange, asmLoopRangeType)
v.dup()
v.dup()
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar)
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.psi.KtForExpression
@@ -31,8 +31,7 @@ class ForInRangeInstanceLoopGenerator(
v.dup()
// ranges inherit first and last from corresponding progressions
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType,
loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
@@ -27,12 +27,16 @@ class ForInRangeLiteralLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
loopRangeCall: ResolvedCall<*>
) : AbstractForInRangeLoopGenerator(codegen, forExpression) {
) : AbstractForInRangeWithGivenBoundsLoopGenerator(codegen, forExpression) {
private val from: ReceiverValue = loopRangeCall.dispatchReceiver!!
private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(loopRangeCall)!!
override fun generateFrom(): StackValue = codegen.generateReceiverValue(from, false)
override fun generateTo(): StackValue = codegen.gen(to)
override fun storeRangeStartAndEnd() {
loopParameter().store(codegen.generateReceiverValue(from, false), codegen.v)
StackValue.local(endVar, asmElementType).store(codegen.gen(to), codegen.v)
loopParameter().store(generateFrom(), v)
StackValue.local(endVar, asmElementType).store(generateTo(), v)
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue

View File

@@ -14,18 +14,18 @@
* limitations under the License.
*/
package kotlin.script.experimental.dependencies
package org.jetbrains.kotlin.codegen.range.forLoop
import java.io.File
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
data class ScriptDependencies(
val javaHome: File? = null,
val classpath: List<File> = emptyList(),
val imports: List<String> = emptyList(),
val sources: List<File> = emptyList(),
val scripts: List<File> = emptyList()
) {
companion object {
val Empty = ScriptDependencies()
}
interface ForLoopGenerator {
val forExpression: KtForExpression
fun beforeLoop()
fun checkEmptyLoop(loopExit: Label)
fun checkPreCondition(loopExit: Label)
fun beforeBody()
fun body()
fun afterBody(loopExit: Label)
fun afterLoop()
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen.forLoop
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2010-2017 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.range.inExpression
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class CallBasedInExpressionGenerator(
val codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression
) : InExpressionGenerator {
private val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
private val isInverted = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isInverted) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, argument.type, Opcodes.IFEQ) {
override fun putSelector(type: Type, v: InstructionAdapter) {
invokeFunction(v)
}
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
invokeFunction(v)
v.visitJumpInsn(if (jumpIfFalse) Opcodes.IFEQ else Opcodes.IFNE, jumpLabel)
}
private fun invokeFunction(v: InstructionAdapter) {
val result = codegen.invokeFunction(resolvedCall.call, resolvedCall, none())
result.put(result.type, v)
}
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2010-2017 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.range.inExpression
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.BranchedValue
import org.jetbrains.kotlin.codegen.Invert
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.BoundedValue
import org.jetbrains.kotlin.codegen.range.comparison.ObjectComparisonGenerator
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class InContinuousRangeOfComparableExpressionGenerator(
operatorReference: KtSimpleNameExpression,
private val boundedValue: BoundedValue
) : InExpressionGenerator {
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
private val comparisonGenerator = ObjectComparisonGenerator
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isNotIn) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
}
else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
val exitLabel1 = Label()
val exitLabel2 = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
AsmUtil.dupx(v, operandType)
// On stack: high arg low arg
// if (low bound is NOT satisfied) goto exitLabel1
if (boundedValue.isLowInclusive) {
// arg < low
v.swap()
comparisonGenerator.jumpIfLess(v, exitLabel1)
}
else {
// arg <= low
v.swap()
comparisonGenerator.jumpIfLessOrEqual(v, exitLabel1)
}
// On stack: high arg
// if (high bound is satisfied) goto jumpLabel
if (boundedValue.isHighInclusive) {
// arg <= high
v.swap()
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
}
else {
// arg < high
v.swap()
comparisonGenerator.jumpIfLess(v, jumpLabel)
}
v.goTo(exitLabel2)
v.mark(exitLabel1)
AsmUtil.pop2(v, operandType)
v.mark(exitLabel2)
}
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
val cmpHighLabel = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
AsmUtil.dupx(v, operandType)
// On stack: high arg low arg
// if ([low bound is satisfied]) goto cmpHighLabel
if (boundedValue.isLowInclusive) {
// arg >= low
v.swap()
comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel)
}
else {
// arg > low
v.swap()
comparisonGenerator.jumpIfGreater(v, cmpHighLabel)
}
// Low bound is NOT satisfied, clear stack and goto jumpLabel
AsmUtil.pop2(v, operandType)
v.goTo(jumpLabel)
v.mark(cmpHighLabel)
// On stack: high arg
// if ([high bound is NOT satisfied]) goto jumpLabel
if (boundedValue.isHighInclusive) {
// arg > high
v.swap()
comparisonGenerator.jumpIfGreater(v, jumpLabel)
}
else {
// arg >= high
v.swap()
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
}
}
}
}

View File

@@ -14,10 +14,11 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.utils
package org.jetbrains.kotlin.codegen.range.inExpression
import java.util.*
import org.jetbrains.kotlin.codegen.BranchedValue
import org.jetbrains.kotlin.codegen.StackValue
// Based on org.jetbrains.kotlin.com.intellij.openapi.util.SystemInfoRt from Intellij platform
internal val isWindows: Boolean =
System.getProperty("os.name")?.toLowerCase(Locale.US)?.startsWith("windows") ?: false
interface InExpressionGenerator {
fun generate(argument: StackValue): BranchedValue
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright 2010-2017 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.range.inExpression
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.BranchedValue
import org.jetbrains.kotlin.codegen.Invert
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.BoundedValue
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class InPrimitiveContinuousRangeExpressionGenerator(
operatorReference: KtSimpleNameExpression,
private val boundedValue: BoundedValue,
private val comparisonGenerator: ComparisonGenerator
) : InExpressionGenerator {
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isNotIn) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
}
else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
val exitLabel1 = Label()
val exitLabel2 = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
AsmUtil.dupx(v, operandType)
// On stack: high arg low arg
// if (low bound is NOT satisfied) goto exitLabel1
if (boundedValue.isLowInclusive) {
// low > arg
comparisonGenerator.jumpIfGreater(v, exitLabel1)
}
else {
// low >= arg
comparisonGenerator.jumpIfGreaterOrEqual(v, exitLabel1)
}
// On stack: high arg
// if (high bound is satisfied) goto jumpLabel
if (boundedValue.isHighInclusive) {
// high >= arg
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
}
else {
// high > arg
comparisonGenerator.jumpIfGreater(v, jumpLabel)
}
v.goTo(exitLabel2)
v.mark(exitLabel1)
AsmUtil.pop2(v, operandType)
v.mark(exitLabel2)
}
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
val cmpHighLabel = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
AsmUtil.dupx(v, operandType)
// On stack: high arg low arg
// if ([low bound is satisfied]) goto cmpHighLabel
if (boundedValue.isLowInclusive) {
// low <= arg
comparisonGenerator.jumpIfLessOrEqual(v, cmpHighLabel)
}
else {
// low < arg
comparisonGenerator.jumpIfLess(v, cmpHighLabel)
}
// Low bound is NOT satisfied, clear stack and goto jumpLabel
AsmUtil.pop2(v, operandType)
v.goTo(jumpLabel)
v.mark(cmpHighLabel)
// On stack: high arg
// if ([high bound is NOT satisfied]) goto jumpLabel
if (boundedValue.isHighInclusive) {
// high < arg
comparisonGenerator.jumpIfLess(v, jumpLabel)
}
else {
// high <= arg
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
}
}
}
}

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
enum class FieldAccessorKind(val suffix: String) {
NORMAL("p"),
@@ -26,15 +27,18 @@ enum class FieldAccessorKind(val suffix: String) {
override fun toString() = suffix
}
private fun CallableMemberDescriptor.getJvmName() =
DescriptorUtils.getJvmName(this) ?: name.asString()
fun getAccessorNameSuffix(descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?,
accessorKind: FieldAccessorKind): String {
val suffix = when (descriptor) {
is ConstructorDescriptor ->
return "will be ignored"
is SimpleFunctionDescriptor ->
descriptor.name.asString()
descriptor.getJvmName()
is PropertyDescriptor ->
descriptor.name.asString() + "$" + accessorKind
descriptor.getJvmName() + "$" + accessorKind
else ->
throw UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor)
}

View File

@@ -16,13 +16,6 @@
package org.jetbrains.kotlin.cli.common.arguments;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.config.AnalysisFlag;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("WeakerAccess")
public abstract class CommonCompilerArguments extends CommonToolArguments {
public static final long serialVersionUID = 0L;
@@ -96,14 +89,6 @@ public abstract class CommonCompilerArguments extends CommonToolArguments {
public static final String ERROR = "error";
public static final String ENABLE = "enable";
@NotNull
public Map<AnalysisFlag<?>, Object> configureAnalysisFlags() {
Map<AnalysisFlag<?>, Object> result = new HashMap<>();
result.put(AnalysisFlag.getSkipMetadataVersionCheck(), skipMetadataVersionCheck);
result.put(AnalysisFlag.getMultiPlatformDoNotCheckImpl(), noCheckImpl);
return result;
}
// Used only for serialize and deserialize settings. Don't use in other places!
public static final class DummyImpl extends CommonCompilerArguments {}
}

View File

@@ -16,14 +16,8 @@
package org.jetbrains.kotlin.cli.common.arguments;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.config.AnalysisFlag;
import org.jetbrains.kotlin.config.Jsr305State;
import org.jetbrains.kotlin.config.JvmTarget;
import java.util.Map;
@SuppressWarnings("WeakerAccess")
public class K2JVMCompilerArguments extends CommonCompilerArguments {
public static final long serialVersionUID = 0L;
@@ -163,26 +157,9 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
description = "Java compiler arguments")
public String[] javacArguments;
@Argument(
value = "-Xjsr305-annotations",
valueDescription = "{ignore|enable}",
description = "Specify global behavior for JSR-305 nullability annotations: ignore, or treat as other supported nullability annotations"
)
public String jsr305GlobalReportLevel = Jsr305State.DEFAULT.getDescription();
@Argument(value = "-Xload-jsr305-annotations", description = "Load JSR-305 nullability annotations")
public boolean loadJsr305annotations;
// Paths to output directories for friend modules.
public String[] friendPaths;
@Override
@NotNull
public Map<AnalysisFlag<?>, Object> configureAnalysisFlags() {
Map<AnalysisFlag<?>, Object> result = super.configureAnalysisFlags();
for (Jsr305State state : Jsr305State.values()) {
if (state.getDescription().equals(jsr305GlobalReportLevel)) {
result.put(AnalysisFlag.getLoadJsr305Annotations(), state);
break;
}
}
return result;
}
}

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.common.arguments
import com.intellij.util.SmartList
import java.lang.reflect.Field
import java.util.*
annotation class Argument(
val value: String,
@@ -53,7 +54,7 @@ data class ArgumentParseErrors(
)
// Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors].
fun <A : CommonToolArguments> parseCommandLineArguments(args: List<String>, result: A) {
fun <A : CommonToolArguments> parseCommandLineArguments(args: Array<out String>, result: A) {
data class ArgumentField(val field: Field, val argument: Argument)
val fields = result::class.java.fields.mapNotNull { field ->

View File

@@ -59,14 +59,13 @@ abstract class KotlinJsr223JvmScriptEngineBase(protected val myFactory: ScriptEn
val codeLine = nextCodeLine(context, script)
val state = getCurrentState(context)
val result = replEvaluator.compileAndEval(state, codeLine, scriptArgs = overrideScriptArgs(context))
val ret = when (result) {
return when (result) {
is ReplEvalResult.ValueResult -> result.value
is ReplEvalResult.UnitResult -> null
is ReplEvalResult.Error -> throw ScriptException(result.message)
is ReplEvalResult.Incomplete -> throw ScriptException("error: incomplete code")
is ReplEvalResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${result.lineNo}")
}
return ret
}
open fun compile(script: String, context: ScriptContext): CompiledScript {
@@ -91,14 +90,13 @@ abstract class KotlinJsr223JvmScriptEngineBase(protected val myFactory: ScriptEn
throw ScriptException(e)
}
val ret = when (result) {
return when (result) {
is ReplEvalResult.ValueResult -> result.value
is ReplEvalResult.UnitResult -> null
is ReplEvalResult.Error -> throw ScriptException(result.message)
is ReplEvalResult.Incomplete -> throw ScriptException("error: incomplete code")
is ReplEvalResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${result.lineNo}")
}
return ret
}
class CompiledKotlinScript(val engine: KotlinJsr223JvmScriptEngineBase, val codeLine: ReplCodeLine, val compiledData: ReplCompileResult.CompiledClasses) : CompiledScript() {

View File

@@ -189,12 +189,15 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> extends CLI
extraLanguageFeatures.put(LanguageFeature.Coroutines, coroutinesState);
}
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new LanguageVersionSettingsImpl(
languageVersion,
ApiVersion.createByLanguageVersion(apiVersion),
arguments.configureAnalysisFlags(),
extraLanguageFeatures
));
LanguageVersionSettingsImpl settings =
new LanguageVersionSettingsImpl(languageVersion, ApiVersion.createByLanguageVersion(apiVersion), extraLanguageFeatures);
settings.switchFlag(AnalysisFlags.getSkipMetadataVersionCheck(), arguments.skipMetadataVersionCheck);
settings.switchFlag(AnalysisFlags.getMultiPlatformDoNotCheckImpl(), arguments.noCheckImpl);
configureAnalysisFlags(settings, arguments);
CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, settings);
}
protected void configureAnalysisFlags(@NotNull LanguageVersionSettingsImpl settings, @NotNull A arguments) {
}
@Nullable

View File

@@ -45,7 +45,7 @@ abstract class CLITool<A : CommonToolArguments> {
K2JVMCompiler.resetInitStartTime()
val arguments = createArguments()
parseCommandLineArguments(args.asList(), arguments)
parseCommandLineArguments(args, arguments)
val collector = PrintingMessageCollector(errStream, messageRenderer, arguments.verbose)
try {
@@ -99,7 +99,7 @@ abstract class CLITool<A : CommonToolArguments> {
// Used in kotlin-maven-plugin (KotlinCompileMojoBase) and in kotlin-gradle-plugin (KotlinJvmOptionsImpl, KotlinJsOptionsImpl)
fun parseArguments(args: Array<out String>, arguments: A) {
parseCommandLineArguments(args.asList(), arguments)
parseCommandLineArguments(args, arguments)
val message = validateArguments(arguments.errors)
if (message != null) {
throw IllegalArgumentException(message)

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