| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
The ConstantOptimization phase uses abstract interpretation
to track what is known about values, and then to use this information
to optimize away tests with a statically known result.
Constant propagation was added under -optimize in Scala 2.11.0-M3, in
PR #2214.
For example, we might know that a variable must hold one of a set
of values (`Possible`). Or, we could track that it must *not*
be of of a set of value (`Impossible`).
The test case in the bug report was enough to create comparison:
v1 == v2 // where V1 = Possible(Set(true, false))
// V2 = Possible(Set(true, false))
This test was considered to be always true, due to a bug in
`Possible#mightNotEqual`. The only time we can be sure that
`Possible(p1) mightNotEquals Possible(p2)` is if
`p1` and `p2` are the same singleton set. This commit changes
this method to implement this logic.
The starting assumption for all values is currently
`Impossible(Set())`, although it would also be reasonable to represent
an unknown boolean variable as `Possible(Set(true, false))`, given
the finite and small domain.
I tried to change the starting assumption for boolean locals in
exactly this manner, and that brings the bug into sharp focus.
Under this patch:
https://github.com/retronym/scala/commit/e564fe522d
This code:
def test(a: Boolean, b: Boolean) = a == b
Compiles to:
public boolean test(boolean, boolean);
Code:
0: iconst_1
1: ireturn
Note: the enclosed test case does not list `-optimize` in a `.flags`
file, I'm relying on that being passed in by the validation build.
I've tested locally with that option, though.
|
|\ \ \
| | | |
| | | | |
SI-9365 Don't null out dependencies of transient lazy vals
|
| |/ /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
As per Iulian's analysis:
> When lazy vals are transient, the optimization in SI-720 is invalid,
> leading to NPEs.
These NPEs appear when recomputing the lazy val when deserializaing
the object.
This commit disables the field nulling if the lazy val is marked
transient.
The post-mixin tree in the enclosed test changes as follows:
```
--- sandbox/old.log 2015-07-27 15:48:03.000000000 +1000
+++ sandbox/new.log 2015-07-27 15:47:56.000000000 +1000
@@ -1,61 +1,54 @@
[[syntax trees at end of mixin]] // t9365.scala
package <empty> {
class Test extends Object with Serializable {
@transient @volatile private[this] var bitmap$trans$0: Boolean = false;
private def foo$lzycompute(): Object = {
{
Test.this.synchronized({
if (Test.this.bitmap$trans$0.unary_!())
{
Test.this.foo = Test.this.x.apply();
Test.this.bitmap$trans$0 = true;
()
};
scala.runtime.BoxedUnit.UNIT
});
- Test.this.x = null
+ ()
};
Test.this.foo
};
```
In addition to the test from the ticket, I've added a reflection
based test that directly tests the nulling. This complements the
test added in 449f2a7473, the fix for SI-720, which passes by
virtue of not exhausting the heap.
|
|\ \ \
| | | |
| | | | |
SI-9403 fix ICodeReader for negative BIPUSH / SIPUSH values
|
| |/ /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
The byte value of a BIPUSH instruction and the (byte1 << 8) | byte2
value of a SIPUSH instruction are signed, see [1] and [2].
Similar for the increment value of IINC [3].
[1] https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.bipush
[2] https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.sipush
[3] https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iinc
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
As with regular `Apply`-s, we should compute the generated type
based on the function's type, rather than the expected type.
In the test case, the expected type was void. Now, we correctly
use the generated type of `scala/Function1`, which is enough
to generate a subsequent POP instruction.
The tree shape involved was:
```
arg0 = {
{
$anonfun()
};
scala.runtime.BoxedUnit.UNIT
}
```
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| | |
Add support in scalap to parse new constant pool entries
- MethodHandle
- MethodType
- InvokeDynamic
Spec: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
|
|\ \
| | |
| | | |
SI-8502 create PackageClass instead of Class symbol stubs for pkgs
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
https://github.com/scala/scala/pull/4111 creates a stub type symbol
for missing packages, deferring (or avoiding) a crash if a package
is missing.
The symbol created was a ClassSymbol, which could lead to an assertion
failure in flattten:
case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) =>
assert(args.isEmpty && sym.enclosingTopLevelClass != NoSymbol, sym.ownerChain)
`pre` is the stub ClassSymbol, so `isFlattenablePrefix` is true (but
it should be false). The assertion then fails because the enclosing
class of a top-level class defined in a missing package is NoSymbol.
This failed only with GenBCode, which traverses more of the symbol
graph while building ClassBTypes: it looks collects the nested classes
of `Outer` into a `NestedInfo`.
|
|\ \
| | |
| | | |
Fix 23 typos (t-v)
|
| |/ |
|
|/ |
|
| |
|
|\
| |
| | |
Fix 27 typos (p-r)
|
| | |
|
|\ \
| |/
|/| |
SI-9206 REPL custom bits
|
| |
| |
| |
| |
| | |
The welcome message defaults to a sober header followed by
one line of instructions.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Everyone knows that a `help` command will result in `more information`.
This commit moves the version string to the second line and adds some
verve to the welcome.
If anyone can't live without the old banner, they are now able to
configure it explicitly, so there is still no blood on our hands.
```
$ scala
Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :quit
$ skala
Welcome to Scala!
version 2.11.7-20150623-155244-eab44dd092 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
Type in expressions for evaluation. Or try :help.
scala> :quit
```
REPL tests now lop off the actual length of the welcome header; or, if
necessary, remove the version number from a header embedded in output.
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Anyone who doesn't understand why result printing was turned
off after they entered `:silent` mode will start the REPL
with `-Dscala.repl.debug` and be enlightened.
For infotainment purposes, the verbose message is also emitted
under info mode.
|
|\ \
| | |
| | | |
GenBCode: fix incrementatal compilation by mimicing GenASM
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
The incremental compiler in SBT uses an implementation detail
of the compiler backend to enumerate the classes that are actually
written to disk.
This commit mimics this in GenBCode by populating `Run#icode` with
an `IClass` for each `ClassDef` processed.
We should revisit this by creating a dedicated API for this purpose
and migrating SBT to use that. We should also revisit this code
as we implement closure elimination in the GenBCode; this commit
assumes that all `ClassDef`s that enter the backend will generate
classfile products.
The enclosed test is extracted from the incrementatl compiler.
I've also manually integration tested this with SBT:
https://gist.github.com/retronym/fabf6f92787ea9c1ce67
|
|\ \ \
| | | |
| | | | |
Improve method names (m-o)
|
| |/ / |
|
|/ / |
|
|\ \
| |/
|/| |
Fix 25 typos (g-i)
|
| | |
|
|\ \
| | |
| | | |
SI-9206 Fix REPL code indentation
|
| | |
| | |
| | |
| | | |
But sans test.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
To make code in error messages line up with the original line of
code, templated code is indented by the width of the prompt.
Use the raw prompt (without ANSI escapes or newlines) to determine
the indentation.
Also, indent only once per line.
|
|\ \ \
| |_|/
|/| | |
SI-9359 Fix InnerClass entry flags for nested Java enums
|
| | | |
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The access flags in InnerClass entries for nested Java enums were
basically completely off.
A first step is to use the recently introduced backend method
`javaClassfileFlags`, which is now moved to BCodeAsmCommon.
See its doc for an explanation.
Then the flags of the enum class symbol were off. An enum is
- final if none of its values has a class body
- abstract if it has an abstract method
(https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9)
When using the ClassfileParser:
- ENUM was never added. I guess that's just an oversight.
- ABSTRACT (together with SEALED) was always added. This is to
enable exhaustiveness checking, see 3f7b8b5. This is a hack and we
have to go through the class members in the backend to find out if
the enum actually has the `ACC_ABSTRACT` flag or not.
When using the JavaParser:
- FINAL was never added.
- ABSTRACT was never added.
This commit fixes all of the above and tests cases (Java enum read
from the classfile and from source).
|
|/ |
|
|\
| |
| | |
Fix some typos (a-c)
|
| | |
|
|\ \
| |/
|/| |
Fix illegal inlining of instructions accessing protected members
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
There were two issues in the new inliner that would cause a
VerifyError and an IllegalAccessError.
First, an access to a public member of package protected class C can
only be inlined if the destination class can access C. This is tested
by t7582b.
Second, an access to a protected member requires the receiver object
to be a subtype of the class where the instruction is located. So
when inlining such an access, we need to know the type of the receiver
object - which we don't have. Therefore we don't inline in this case
for now. This can be fixed once we have a type propagation analyis.
https://github.com/scala-opt/scala/issues/13.
This case is tested by t2106.
Force kmpSliceSearch test to delambdafy:inline
See discussion on https://github.com/scala/scala/pull/4505. The issue
will go away when moving to indy-lambda.
|
|\ \
| | |
| | | |
SI-9348 Fix missing last element in exclusive floating point ranges
|
| | |
| | |
| | |
| | |
| | | |
Fix exclusive floating point ranges to contain also the last element
when the end-start difference is not an integer multiple of step.
|
|\ \ \
| |/ /
|/| | |
Fix toolbox with varargs constructors
|
| | |
| | |
| | |
| | | |
It was already working for methods, but not for constructors.
|
|\ \ \
| |/ /
|/| | |
SI-7747 Make REPL wrappers serialization friendly.
|
| | | |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
We only need to introduce the temporary val in the imports
wrapper when we are importing a val or module defined in the REPL.
The test case from the previous commit still passes, but
we are generating slightly simpler code.
Compared to 2.11.6, these two commits result in the following
diff:
https://gist.github.com/retronym/aa4bd3aeef1ab1b85fe9
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Spark has been shipping a forked version of our REPL for
sometime. We have been trying to fold the patches back into
the mainline so they can defork. This is the last outstanding
issue.
Consider this REPL session:
```
scala> val x = StdIn.readInt
scala> class A(a: Int)
scala> serializedAndExecuteRemotely {
() => new A(x)
}
```
As shown by the enclosed test, the REPL, even with the
Spark friendly option `-Yrepl-class-based`, will re-initialize
`x` on the remote system.
This test simulates this by running a REPL session, and then
deserializing the resulting closure into a fresh classloader
based on the class files generated by that session. Before this
patch, it printed "evaluating x" twice.
This is based on the Spark change described:
https://github.com/mesos/spark/pull/535#discussion_r3541925
A followup commit will avoid the `val lineN$read = ` part if we
import classes or type aliases only.
[Original commit from Prashant Sharma, test case from Jason Zaugg]
|
| |/
|/|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- private-inline, t8601-closure-elim, inline-in-constructors
- test closure inlining / elimination, which is not yet implemented
in GenBCode. noted in https://github.com/scala-opt/scala/issues/14.
- constant-optimization, t7006
- no constant folding in GenBCode yet.
noted in https://github.com/scala-opt/scala/issues/29.
- patmat_opt_ignore_underscore, patmat_opt_no_nullcheck, patmat_opt_primitive_typetest
- not all optimizations in GenBCode yet.
noted in https://github.com/scala-opt/scala/issues/30.
- t3234
- tests a warning of trait inlining - trait inlining works in
GenBCode
- synchronized
- ignore inliner warnings (they changed a bit)
- t6102
- account for the changed outputo of -Ydebug has under GenBCode
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
We add a static field to each class that defines lambdas that
will hold a `ju.Map[String, MethodHandle]` to cache references to
the constructors of the classes originally created by
`LambdaMetafactory`.
The cache is initially null, and created on the first deserialization.
In case of a race between two threads deserializing the first
lambda hosted by a class, the last one to finish will clobber
the one-element cache of the first.
This lack of strong guarantees mirrors the current policy in
`LambdaDeserializer`.
We should consider whether to strengthen the combinaed guarantee here.
A useful benchmark would be those of the invokedynamic instruction,
which allows multiple threads to call the boostrap method in parallel,
but guarantees that if that happens, the results of all but one will
be discarded:
> If several threads simultaneously execute the bootstrap method for
> the same dynamic call site, the Java Virtual Machine must choose
> one returned call site object and install it visibly to all threads.
We could meet this guarantee easily, albeit excessively, by
synchronizing `$deserializeLambda$`. But a more fine grained
approach is possible and desirable.
A test is included that shows we are able to garbage collect
classloaders of classes that have hosted lambda deserialization.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
To support serialization, we use the alternative lambda metafactory
that lets us specify that our anonymous functions should extend the
marker interface `scala.Serializable`. They will also have a
`writeObject` method added that implements the serialization proxy
pattern using `j.l.invoke.SerializedLamba`.
To support deserialization, we synthesize a `$deserializeLamba$`
method in each class with lambdas. This will be called reflectively by
`SerializedLambda#readResolve`. This method in turn delegates to
`LambdaDeserializer`, currently defined [1] in `scala-java8-compat`,
that uses `LambdaMetafactory` to spin up the anonymous class and
instantiate it with the deserialized environment.
Note: `LambdaDeserializer` can reuses the anonymous class on subsequent
deserializations of a given lambda, in the same spirit as an
invokedynamic call site only spins up the class on the first time
it is run. But first we'll need to host a cache in a static field
of each lambda hosting class. This is noted as a TODO and a failing
test, and will be updated in the next commit.
`LambdaDeserializer` will be moved into our standard library in
the 2.12.x branch, where we can introduce dependencies on the
Java 8 standard library.
The enclosed test cases must be manually run with indylambda enabled.
Once we enable indylambda by default on 2.12.x, the test will
actually test the new feature.
```
% echo $INDYLAMBDA
-Ydelambdafy:method -Ybackend:GenBCode -target:jvm-1.8 -classpath .:scala-java8-compat_2.11-0.5.0-SNAPSHOT.jar
% qscala $INDYLAMBDA -e "println((() => 42).getClass)"
class Main$$anon$1$$Lambda$1/1183231938
% qscala $INDYLAMBDA -e "assert(classOf[scala.Serializable].isInstance(() => 42))"
% qscalac $INDYLAMBDA test/files/run/lambda-serialization.scala && qscala $INDYLAMBDA Test
```
This commit contains a few minor refactorings to the code that
generates the invokedynamic instruction to use more meaningful
names and to reuse Java signature generation code in ASM rather
than the DIY approach.
[1] https://github.com/scala/scala-java8-compat/pull/37
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`LambdaMetafactory` generates code to perform a limited number
of type adaptations when delegating from its implementation of
the functional interface method to the lambda target method.
These adaptations are: numeric widening, casting, boxing and unboxing.
However, the semantics of unboxing numerics in Java differs to Scala:
they treat `UNBOX(null)` as cause to raise a `NullPointerException`,
Scala (in `BoxesRuntime.unboxTo{Byte,Short,...}`) reinterprets the
null as zero.
Furthermore, Java has no idea how to adapt between a value class and
its wrapped type, nor from a void return to `BoxedUnit`.
This commit detects when the lambda target method would require
such adaptation. If it does, an extra method, `$anonfun$1$adapted` is
created to perform the adaptation, and this is used as the target
of the lambda.
This obviates the use of `JProcedureN` for `Unit` returning
lambdas, we know use `JFunctionN` as the functional interface
and bind this to an `$adapted` method that summons the instance
of `BoxedUnit` after calling the `void` returning lambda target.
The enclosed test cases fail without boxing changes. They don't
execute with indylambda enabled under regular partest runs yet,
you need to add scala-java8-compat to scala-library and pass
the SCALAC_OPTS to partest manually to try this out, as described
in https://github.com/scala/scala/pull/4463. Once we enable indylambda
by default, however, this test will exercise the code in this patch
all the time.
It is also possible to run the tests with:
```
% curl https://oss.sonatype.org/content/repositories/releases/org/scala-lang/modules/scala-java8-compat_2.11/0.4.0/scala-java8-compat_2.11-0.4.0.jar > scala-java8-compat_2.11-0.4.0.jar
% export INDYLAMBDA="-Ydelambdafy:method -Ybackend:GenBCode -target:jvm-1.8 -classpath .:scala-java8-compat_2.11-0.4.0.jar"
qscalac $INDYLAMBDA test/files/run/indylambda-boxing/*.scala && qscala $INDYLAMBDA Test
```
|
|
|
|
|
|
|
|
|
|
| |
Previously, the flag caused any elidable to be elided.
This commit simply sets -Xelide-below to ASSERTION + 1.
The flag is useful because there's no mnemonic for specifying
the magic constant as an option argument. `-Xelide-below ASSERTION`
means asserts are enabled.
|