summaryrefslogtreecommitdiff
path: root/src/compiler
Commit message (Collapse)AuthorAgeFilesLines
* Run DCE before the closure optimizer (fixes a crash)Lukas Rytz2016-01-203-111/+135
| | | | | | | | | | | | | | | Before identifying function callsites within the same method as a closure allocation, run DCE. The ProdCons analysis used to identify these function calls may crash if there is unreachable code, as observed in the community build with scala-js. The crash was rare because inlining, which is performed before closure optimizations, already runs DCE. However, inlining may render more code unreachable (e.g. when inlining a method that throws). Also make sure that DCE is always performed on the callee before inlining: move the DCE invocation into the inlineCallsite method, which is also invoked by the closure optimizer.
* Move copy propagation implementation to a separate fileLukas Rytz2015-12-162-622/+650
|
* Harden push-pop elimination when eliminating constantsLukas Rytz2015-12-151-4/+8
| | | | | | | | | Ensure that LDC instructions are only eliminated when the loaded value is a numeric or string constant. Removing other literals may remove a potential failure. [1] lists the kind of values that can be loaded by a LDC [1] https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.ldc
* Apply local optimization based on nullness informationLukas Rytz2015-12-153-12/+128
| | | | | | | | | Optimize IFNULL branches to GOTO when (non-)nullness of the tested value is known statically. This enables unreachable code to be removed, which in turn enables boxes to be eliminated. Changed a test flag from `-Ynooptimise` to `-Yopt:l:classpath` - I still have to do this systematically, this will follow later.
* Ensure that `-Yopt:l:none` takes precedence, tidy optimizer settingsLukas Rytz2015-12-151-17/+28
|
* Eliminate unnecessary castsLukas Rytz2015-12-154-34/+97
| | | | | | Eliminate casts that are statically known to succeed. This enables boxes to be eliminated and simplifies the implementation of closure allocation elimination.
* Eliminate non-escaping boxes, tuples and refsLukas Rytz2015-12-154-74/+1184
| | | | | | | | | Eliminate boxes, tuples and refs that are created and used within a single method without escaping. For details on the implementation see the doc comment in class BoxUnbox. This commit also cleans up the logic of inter-dependent method-level optimizations that run until reaching a fixpoint.
* Minor cleanups in eliminateStaleStoresLukas Rytz2015-12-131-6/+7
|
* Fix push-pop elimination for values pushed by DUPLukas Rytz2015-12-133-37/+49
| | | | | | If a DUP is consumed by two POPs, ensure that the DUP and its producer are eliminated. Before, only the DUP was eliminated, leaving an unused value on the stack.
* Don't run closure optimizer on methods too large for prod-consLukas Rytz2015-12-131-7/+9
| | | | | | | | For methods that are too large to run a producers-consumers analysis, don't run the closure optimizer. This is an oversight, all data flow analyses in the backend are guarded by a method size check.
* Fix in "consumersOfOutputsFrom" query in prod-cons analysisLukas Rytz2015-11-231-10/+21
| | | | | | | | | Fix the "consumersOfOutputsFrom" in the prod-cons analysis to support dummy instructions: - UninitializedLocalProducer - ParameterProducer - ExceptionProducer
* Support specialized functions in closure optimizerLukas Rytz2015-11-134-47/+179
| | | | | | | | | | Fixes https://github.com/scala/scala-dev/issues/52. An IndyLambda may create a specialized function type, where the SAM is the corresponding specialized variant of apply. If this closure is invoked through the generic apply method, the closure optimizer would previously not re-write the invocation to the $anonfun method. This is now done, including the necessary box / unbox operations.
* Fix specialized function class names in closure optimizerLukas Rytz2015-11-101-2/+4
|
* Clean up optimizer settings.Lukas Rytz2015-11-103-23/+19
|
* Copy propagation, remove unused values (closures!) and local variablesLukas Rytz2015-11-104-58/+920
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Copy propagation uses an AliasingAnalyzer: it replaces a `LOAD n` instruction by `LOAD m` where m is the smallest alias of n. This leads to stale STORE instructions. Stale STOREs are identified using a ProdCons analyzer and replaced by POPs. Values that are pushed on the stack by a side-effect free instruction and consumed by a POP are then removed by `eliminatePushPop`. This includes elimination of unused closure allocations and unused boxes and tuple allocations (*). A final cleanup eliminates `STORE x; LOADx` pairs where the stored value is not otherwise used. Fixes - https://github.com/scala/scala-dev/issues/25 - https://github.com/scala/scala-dev/issues/7 - https://github.com/scala/scala-dev/issues/14 - https://github.com/scala/scala-dev/issues/12 (*) We don't yet rewrite reads of boxes and tuples yet. For example, `val x = (1, 2); x._1` remains a method invocation and the tuple cannot be eliminated (https://github.com/scala/scala-dev/issues/11). Inspired in many ways by Miguel's work!
* Fix merging of AliasingFramesLukas Rytz2015-11-101-13/+22
| | | | | | | | | | | | | By convention (for performance), `aliasingFrame.aliases(slot) == null` means that the value at `slot` has no aliases, so this is isomorphic to having a singleton `AliasSet(slot)`. When merging an AliasingFrame `other` into `this`, at every value slot we have to keep the intersection of the two alias sets. In other words we have to remove from `this.aliases(slot)` those values that are not in `other.aliases(slot)`. This was wrong for the cases where `other.aliases == null` - we did not treat this case as a singleton set.
* Clean up DCE: remove eliminated callsites from call graph earlierLukas Rytz2015-11-102-34/+32
| | | | | When running DCE, directly remove eliminated callsites from the call graph (instead delegating this task to the callees).
* Remove InstructionResultSize (subsumed by InstructionStackEffect)Lukas Rytz2015-11-102-237/+2
|
* Fix VarInstruction extractor to include IINCLukas Rytz2015-11-103-12/+17
| | | | | | | | | Previously the VarInstruction extractor did not include IINCs. Also give rename the isVarInstruction predicate to isLoadStoreOrRet, as it doesn't include IINC. Also fixes a bug in removeJumpAndAdjustStack, it checked the wrong opcode range before.
* [trivial] import Opcodes._ in two files, move a utility methodLukas Rytz2015-10-292-53/+51
|
* Track aliases of primitive values in AliasingFrameLukas Rytz2015-10-291-18/+21
| | | | | This allows using an AliasingAnalyzer for copy propagation (subsequent commit).
* Merge pull request #4808 from retronym/ticket/9527Seth Tisue2015-10-271-2/+3
|\ | | | | SI-9527 Fix NPE in ambiguous implicit error generation
| * SI-9527 Fix NPE in ambiguous implicit error generationJason Zaugg2015-10-211-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In #4673, an annotation was added to allow customization of the compiler error for ambigous implicits. This change had incorrect assumptions about the shape of trees that would be generated during implicit search, and failed to account for the results of eta expanded methods when searching for a function type. This commit: - Uses the symbol from `ImpilcitInfo`, rather than calling `Tree#symbol` which is fraught with the danger of returning a null symbol for something other than an application. - Adds a test for customized messages for a polymorphic, eta expanded method, and generalizes `treeTypeArgs` to handle the implicit tree of shape `{ (x: X) => f[A](x)}`.
* | Use a single Int for the prod / cons values of InstructionStackEffectLukas Rytz2015-10-274-44/+33
| | | | | | | | | | | | The maximal number of produced values of any instruction is 6, so we can safely encode the number of consumed and produced values into a single Int as (prod << 3) + cons.
* | Support JSR / RET in computeMaxLocalsMaxStackLukas Rytz2015-10-272-9/+20
| | | | | | | | | | | | | | | | Even though the two bytecodes are not allowed in classfiles of version 51+ (see [1]), we could encounter them when inlining from a JAR file containing classfiles of older version. [1] https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.9.1
* | More efficient way to compute maxLocals / maxStackLukas Rytz2015-10-276-209/+386
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In order to run an asm Analyzer, the maxLocals / maxStack values of the method need to be computed. Asm doesn't provide an efficient built-in for this purpose, but it computes these values while serializing a class. Previously, we used to serialize the method just to compute the max's, which is inefficient. This commit implements a separate, efficient traversal. The computed values are also smaller, allowing to save space when running an Analyzer: asm Analyzers only allocate a single stack slot for long/double values, while the JVM allocates two. The maxStack computed previously would always use two slots, which is not necessary. The new calculation was verified to be correct in the following way: as a test, i left the old computation in place, ran the new one in addition (in a special mode where the long/double values take two slots) and asserted equality. Bootstrapping and test suite passed.
* | Merge pull request #4820 from lrytz/t9535Lukas Rytz2015-10-274-15/+32
|\ \ | | | | | | SI-9535 correct bytecode and generic signatures for @throws[TypeParam]
| * | SI-9535 correct bytecode and generic signatures for @throws[TypeParam]Lukas Rytz2015-10-264-15/+32
| | | | | | | | | | | | | | | | | | | | | For @throws[E] where E is not a class type, GenASM incorrectly writes the non-class type to the classfile. GenBCode used to crash before this commit. Now GenBCode correctly emits the erased type (like javac) and adds a generic signature.
* | | Clean up CoreBTypes, consistent names, remove unused entriesLukas Rytz2015-10-2010-190/+136
| | |
* | | Simplify and correctify calculation of the InnerClass attributeLukas Rytz2015-10-209-149/+230
|/ / | | | | | | | | | | | | | | | | | | | | | | | | The InnerClass attribute needs to contain an entry for every nested class that is defined or referenced in a class. Details are in a doc comment in BTypes.scala. Instead of collecting ClassBTypes of nested classes into a hash map during code generation, traverse the class before writing it out to disk. The previous approach was incorrect as soon as the generated bytecode was modified by the optimzier (DCE, inlining). Fixes https://github.com/scala/scala-dev/issues/21.
* | Allow @inline/noinline at callsites (in addition to def-site)Lukas Rytz2015-10-207-25/+52
| | | | | | | | | | | | | | Allow annotating individual callsites @inline / @noinline using an annotation ascription c.foo(): @inline
* | Correctly handle post-inline requests of non-existing callsitesLukas Rytz2015-10-202-31/+85
| | | | | | | | | | | | A post-inline request is allowed to refer to a callsite that does not exist anymore because it was alredy inlined while handling some other inline request, or because it was DCE'd.
* | Simplify post inlining requestsLukas Rytz2015-10-203-22/+34
| | | | | | | | Clean up inliner test
* | Rename filter to withFilter in RightBiasedEitherLukas Rytz2015-10-201-3/+3
| |
* | Don't create inline requests for callsites that cannot be inlinedLukas Rytz2015-10-202-51/+103
|/ | | | | | | | | | | | | | | | | | | | When traversing the call graph and collecting inline reqeusts, rule out callsites that we already know cannot be inlined. Note that we cannot perform all necessary checks already at this stage: checks that depend on the callee body (the inlined code) are deferred until the callsite is actually inlined. The reason is that the code may change. Example: @inline final def f = try 1 catch { case _: Throwable => 2 } @inline final def g = f def t = println(g) When collecting inline requests, the body of g invokes the public method f, so g could be inlined into t. However, once f is inlined into g, the body of g contains a try-catch block. Now we cannot inline g into t anymore, because the call stack at the g callsite is non-empty (the stack is cleared when entering a handler).
* Merge commit 'bb3ded3' into merge-2.11-to-2.12-oct-5Lukas Rytz2015-10-059-40/+73
|\
| * Merge pull request #4770 from SethTisue/windows-testing-fixesLukas Rytz2015-10-052-2/+5
| |\ | | | | | | get test suite passing on Windows
| | * add missing newline at eof in Scala sourceSeth Tisue2015-09-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | this was causing a mysterious compilation failure on Windows. (it may not have been a sufficient cause in itself -- which is why I say "mysterious" -- but in any case, adding the newline made the failure go away. and besides, the newline should be there. so here it is.) (it's tempting to make a big commit that fixes this in every source file. resisting for now)
| | * fix bug where -Xprint-icode leaked an InputStream and a file handleSeth Tisue2015-09-251-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | usually it hardly matters, but it's still a bug, and on Windows we can't delete an open file, so this can cause trouble for someone writing a test that relies on being able to generate icode files and then clean them up afterwards. (and in fact, two IcodeComparison-based tests were failing.)
| * | Improve implicits wildcard imports in the IDEJason Zaugg2015-09-301-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In 451cab967a, I changed handling of selection of members from package objects so as to correctly use `somePackage.package.type` as the prefix, rather than `somePackage`. This fixed generic substitution for members inherited from superclasses of the package object. However, this has subtly changed the scope from which we collect implicits given a wildcard import. It seems that the IDE gets into a situation after a scaladoc lookup, which temporarily typechecks the sources of a package object of a third party library, in which the members of package object differ from the members of the enclosing package. The upshot of this was spurious type errors due to implicit search discarding an candidate implicit whose symbol is not matched by typechecking an identifier with the symbol's name at the implicit usage site (this is how we discard shadowed implicits.) I'd like to ge to the bottom of this, but in the meantime, I've found that we can fix the regression by looking up the implicit member symbols in the package, even while correctly using the package object as the prefix.
| * | Merge pull request #4720 from retronym/ticket/9029Jason Zaugg2015-09-293-31/+44
| |\ \ | | | | | | | | SI-9029 Fix regression in extractor patterns
| | * | SI-9029 Remove unused methodJason Zaugg2015-09-221-5/+0
| | | |
| | * | SI-8127 Remove dead code in UncurryJason Zaugg2015-09-211-7/+0
| | | | | | | | | | | | | | | | | | | | It remains from the days of yore, when patterns survived this long in the compiler.
| | * | SI-8989 Better error message for invalid extractor patternJason Zaugg2015-09-211-3/+8
| | | |
| | * | SI-9029 Fix regression in extractor patternsJason Zaugg2015-09-212-16/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The unified treatment of classical and named-based pattern matching does not correctly handle the generalization of "tuple capture". By "tuple capture", I mean: ``` scala> object Extractor { def unapply(a: Any): Option[(Int, String)] = Some((1, "2")) } defined object Extractor scala> "" match { case Extractor(x: Int, y: String) => } scala> "" match { case Extractor(xy : (Int, String)) => } warning: there was one deprecation warning; re-run with -deprecation for details scala> :warnings <console>:9: warning: object Extractor expects 2 patterns to hold (Int, String) but crushing into 2-tuple to fit single pattern (SI-6675) "" match { case Extractor(xy : (Int, String)) => } ^ ``` Name based pattern matching, new in Scala 2.11, allows one to deconstruct the elements that structurally resembles `ProductN`: ``` scala> class P2(val _1: Int, val _2: String) defined class P2 scala> object Extractor { def unapply(a: Any): Option[P2] = Some(new P2(1, "2")) } defined object Extractor scala> "" match { case Extractor(x: Int, y: String) => } ``` However, attempting to extract the `P2` in its entirety leads to an internal error: ``` scala> "" match { case Extractor(p2: P2) => } <console>:10: warning: fruitless type test: a value of type (Int, String) cannot also be a P2 "" match { case Extractor(p2: P2) => } ^ <console>:10: error: error during expansion of this match (this is a scalac bug). The underlying error was: type mismatch; found : P2 required: (Int, String) "" match { case Extractor(p2: P2) => } ^ ``` Note that this match was legal and warning free in 2.10. This commit avoids the hard-coded assumption that the "tuple capture" results in a `TupleN`, and instead keeps track of the product-ish type from which we extracted the element types. I have also opted not to limit the deprecation warning to `TupleN` extractors.
| * | | Merge pull request #4674 from kirillkh/2.11.xSeth Tisue2015-09-251-4/+9
| |\ \ \ | | |_|/ | |/| | add support for MSys2 to bin/scala shell script
| | * | tool-unix: support environments with TERM=cygwinkirillkh2015-08-091-1/+1
| | | |
| | * | add support for MSys2 to bin/scala shell scriptKirill Khazan2015-07-311-3/+8
| | | |
| * | | Improve presentation compilation of annotationsJason Zaugg2015-09-242-2/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A trio of problems were hampering autocompletion of annotations. First, given that that annotation is written before the annotated member, it is very common to end parse incomplete code that has a floating annotation without an anotatee. The parser was discarding the annotations (ie, the modifiers) and emitting an `EmptyTree`. Second, the presetation compiler was only looking for annotations in the Modifiers of a member def, but after typechecking annotations are moved into the symbol. Third, if an annotation failed to typecheck, it was being discarded in place of `ErroneousAnnotation`. This commit: - modifies the parser to uses a dummy class- or type-def tree, instead of EmptyTree, which can carry the annotations. - updates the locator to look in the symbol annotations of the modifiers contains no annotations. - uses a separate instance of `ErroneousAnnotation` for each erroneous annotation, and stores the original tree in its `original` tree.
| * | | Merge pull request #4757 from lrytz/t9375-2.11Lukas Rytz2015-09-222-2/+15
| |\ \ \ | | | | | | | | | | [backport] SI-9375 add synthetic readResolve only for static modules