summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala
Commit message (Collapse)AuthorAgeFilesLines
* re-enable two tests (starr is up to date now)Lukas Rytz2016-09-301-4/+2
|
* Rename -Yopt to -opt, -Yopt-warnings to -opt-warningsLukas Rytz2016-05-251-1/+1
| | | | Keep -Yopt-inline-heuristics and -Yopt-trace unchanged
* All JUnit tests pass without bootstrap (when run in intellij, sbt)Lukas Rytz2016-05-201-2/+4
|
* Better abstraction for bytecode tests. Also organize some imports.Lukas Rytz2016-05-201-18/+10
|
* Rename nsc.backend.jvm.CodeGenTools to testing.BytecodeTestingLukas Rytz2016-05-201-1/+1
|
* SI-9684 Deprecate JavaConversionsSom Snytt2016-04-221-1/+1
| | | | | | | | | Implicit conversions are now in package convert as ImplicitConversions, ImplicitConversionsToScala and ImplicitConversionsToJava. Deprecated WrapAsJava, WrapAsScala and the values in package object. Improve documentation.
* Ensure ClassBTypes constructed from symbol and classfile are identicalLukas Rytz2016-04-201-13/+1
| | | | | | | | | | | | | | | | | | A super call (invokespecial) to a default method T.m is only allowed if the interface T is a direct parent of the class. Super calls are introduced for example in Mixin when generating forwarder methods: trait T { override def clone(): Object = "hi" } trait U extends T class C extends U The class C gets a forwarder that invokes T.clone(). During code generation the interface T is added as direct parent to class C. Note that T is not a (direct) parent in the frontend type of class C. This commit stores interfaces that are added to a class during code generation in the InlineInfo classfile attribute. This allows filtering the interface list when constructing a ClassBType from a classfile.
* Inline super calls, as they are statically resolvedLukas Rytz2016-03-231-2/+5
| | | | | | | Ensures that mixin methods of `@inline` annotated concrete trait methods inline the trait method. Fixes https://github.com/scala/scala-dev/issues/86
* New trait encoding: use default methods, jettison impl classesJason Zaugg2016-03-181-1/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Until now, concrete methods in traits were encoded with "trait implementation classes". - Such a trait would compile to two class files - the trait interface, a Java interface, and - the implementation class, containing "trait implementation methods" - trait implementation methods are static methods has an explicit self parameter. - some methods don't require addition of an interface method, such as private methods. Calls to these directly call the implementation method - classes that mixin a trait install "trait forwarders", which implement the abstract method in the interface by forwarding to the trait implementation method. The new encoding: - no longer emits trait implementation classes or trait implementation methods. - instead, concrete methods are simply retained in the interface, as JVM 8 default interface methods (the JVM spec changes in [JSR-335](http://download.oracle.com/otndocs/jcp/lambda-0_9_3-fr-eval-spec/index.html) pave the way) - use `invokespecial` to call private or particular super implementations of a method (rather `invokestatic`) - in cases when we `invokespecial` to a method in an indirect ancestor, we add that ancestor redundantly as a direct parent. We are investigating alternatives approaches here. - we still emit trait fowrarders, although we are [investigating](https://github.com/scala/scala-dev/issues/98) ways to only do this when the JVM would be unable to resolve the correct method using its rules for default method resolution. Here's an example: ``` trait T { println("T") def m1 = m2 private def m2 = "m2" } trait U extends T { println("T") override def m1 = super[T].m1 } class C extends U { println("C") def test = m1 } ``` The old and new encodings are displayed and diffed here: https://gist.github.com/retronym/f174d23f859f0e053580 Some notes in the implementation: - No need to filter members from class decls at all in AddInterfaces (although we do have to trigger side effecting info transformers) - We can now emit an EnclosingMethod attribute for classes nested in private trait methods - Created a factory method for an AST shape that is used in a number of places to symbolically bind to a particular super method without needed to specify the qualifier of the `Super` tree (which is too limiting, as it only allows you to refer to direct parents.) - I also found a similar tree shape created in Delambdafy, that is better expressed with an existing tree creation factory method, mkSuperInit.
* Remove -Y settings that are no longer used in 2.12Lukas Rytz2016-02-161-1/+1
| | | | | | Added a deprecation warning for `-optimize`. Later we'll also graduate `-Yopt` to `-opt`, probably for 2.12.0-M5.
* Issue inliner warnings for callsites that cannot be inlinedLukas Rytz2015-03-111-3/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Issue precise warnings when the inliner fails to inline or analyze a callsite. Inline failures may have various causes, for example because some class cannot be found on the classpath when building the call graph. So we need to store problems that happen early in the optimizer (when building the necessary data structures, call graph, ClassBTypes) to be able to report them later in case the inliner accesses the related data. We use Either to store these warning messages. The commit introduces an implicit class `RightBiasedEither` to make Either easier to use for error propagation. This would be subsumed by a biased either in the standard library (or could use a Validation). The `info` of each ClassBType is now an Either. There are two cases where the info is not available: - The type info should be parsed from a classfile, but the class cannot be found on the classpath - SI-9111, the type of a Java source originating class symbol cannot be completed This means that the operations on ClassBType that query the info now return an Either, too. Each Callsite in the call graph now stores the source position of the call instruction. Since the call graph is built after code generation, we build a map from invocation nodes to positions during code gen and query it when building the call graph. The new inliner can report a large number of precise warnings when a callsite cannot be inlined, or if the inlining metadata cannot be computed precisely, for example due to a missing classfile. The new -Yopt-warnings multi-choice option allows configuring inliner warnings. By default (no option provided), a one-line summary is issued in case there were callsites annotated @inline that could not be inlined.
* Inline final methods defined in traitsLukas Rytz2015-03-111-9/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In order to inline a final trait method, callsites of such methods are first re-written from interface calls to static calls of the trait's implementation class. Then inlining proceeds as ususal. One problem that came up during development was that mixin methods are added to class symbols only for classes being compiled, but not for others. In order to inline a mixin method, we need the InlineInfo, which so far was built using the class (and method) symbols. So we had a problem with separate compilation. Looking up the symbol from a given classfile name was already known to be brittle (it's also one of the weak points of the current inliner), so we changed the strategy. Now the InlineInfo for every class is encoded in a new classfile attribute. This classfile attribute is relatively small, because all strings it references (class internal names, method names, method descriptors) would exist anyway in the constant pool, so it just adds a few references. When building the InlineInfo for a class symbol, we only look at the symbol properties for symbols being compiled in the current run. For unpickled symbols, we build the InlineInfo by reading the classfile attribute. This change also adds delambdafy:method classes to currentRun.symSource. Otherwise, currentRun.compiles(lambdaClass) is false.
* Don't crash the inliner in mixed compilationLukas Rytz2015-03-111-1/+1
| | | | | | | | | | | | In mixed compilation, the bytecode of Java classes is not availalbe: the Scala compiler does not produce any, and there are no classfiles yet. When inlining a (Scala defined) method that contains an invocation to a Java method, we need the Java method's bytecode in order to check whether that invocation can be transplanted to the new location without causing an IllegalAccessError. If the bytecode cannot be found, inlining won't be allowed.
* Build a call graph for inlining decisionsLukas Rytz2015-03-111-0/+9
| | | | | | | | | | Inlining decisions will be taken by analyzing the ASM bytecode. This commit adds tools to build a call graph representation that can be used for these decisions. The call graph is currently built by considering method descriptors of callsite instructions. It will become more precise by using data flow analyses.
* Reuse the same compiler instance for all tests in a JUnit classLukas Rytz2015-03-111-1/+3
| | | | | | | | | | Note that JUnit creates a new instance of the test class for running each test method. So the compiler instance is added to the companion. However, the JVM would quickly run out of memory when running multiple tests, as the compilers cannot be GCd. So we make it a `var`, and set it to null when a class is done. For that we use JUnit's `@AfterClass` which is required to be on a static method. Therefore we add a Java class with such a static method that we can extend from Scala.
* Construct ClassBTypes from parsed classfilesLukas Rytz2015-01-161-0/+95
This infrastructure is required for the inliner: when inlining code from a classfile, the corresponding ClassBType is needed for various things (eg access checks, InnerClass attribute). The test creates two ClassBTypes for the same class: once using the (unpickled) Symbol, once using the parsed ASM ClassNode, and verifies that the two are the same. There's a cleanup to the InnerClass attribute: object T { class Member; def foo = { class Local } } class T For Java compatibility the InnerClass entry for Member says the class is nested in T (not in the module class T$). We now make sure to add that entry only to T, not to T$ (unless Member is actually referenced in the classfile T$, in that case it will be added, as required).