| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
| |
In 8020cd6, the inliner was changed to make sure trait methods bodies
are not duplicated into the static super accessors, and from there into
mixin forwarders.
The check for mixin forwarders was too wide. In `def t = super.m`, where
`m` is a trait method annotated `@inline`, we want to inline `m`. Note
that `super.m` is translated to an `invokestatic T.m$`. The current
check incorrectly identifies `t` as a mixin forwarder, and skip
inlining.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some changes to the trait encoding came late in the 2.12 cycle, and the
inliner was not adapted to support it in the best possible way.
In 2.12.0 concrete trait methods are encoded as
interface T {
default int m() { return 1 }
static int m$(T $this) { <invokespecial $this.m()> }
}
class C implements T {
public int m() { return T.m$(this) }
}
If a trait method is selected for inlining, the 2.12.0 inliner would
copy its body into the static super accessor `T.m$`, and from there into
the mixin forwarder `C.m`.
This commit special-cases the inliner:
- We don't inline into static super accessors and mixin forwarders.
- Insted, when inlining an invocation of a mixin forwarder, the
inliner also follows through the two forwarders and inlines the
trait method body.
There was a difficulty implementing this: inlining the static static
super accessor would copy an `invokespecial` instruction into a
different classfile, which is not legal / may change semantics. That
`invokespecial` is supposed to disappear when inlining the actual
default method body. However, this last step may fail, for example
because the trait method body itself contains instructions that are not
legal in a different classfile.
It is very difficult to perform all necessary checks ahead of time. So
instead, this commit implements the ability to speculatively inline a
callsite and roll back if necessary.
The commit also cleans up the implementation of inliner warnings a
little. The previous code would always emit a warning when a method
annotated `@inline` was not picked by the heuristics - this was a
problem when the callsite in the static super accessor was no longer
chosen.
|
|
|
|
|
|
| |
just in time for Halloween. "boostrap" is definitely the most
adorable typo evah -- and one of the most common, too. but we don't
want to scare anybody.
|
|
|
|
|
|
|
|
|
|
| |
Also eliminates the warning when a mixin forwarder cannot be implemented
because the target method is a java-defined default method in an
interface that is not a direct parent of the class.
The test t5148 is moved to neg, as expected: It was moved to pos when
disabling mixin forwarders in 33e7106. Same for the changed error
message in t4749.
|
| |
|
|
|
|
|
|
|
|
|
| |
The motivation is to use the new fine-grained lock scoping that
local lazies have since #5294.
Fixes scala/scala-dev#235
Co-Authored-By: Jason Zaugg <jzaugg@gmail.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
GenBCode, the new backend in Scala 2.12, subtly changed
the way that synchronized blocks are emitted.
It used `java/lang/Throwable` as an explicitly named exception
type, rather than implying the same by omitting this in bytecode.
This appears to confuse HotSpot JIT, which reports a error
parsing the bytecode into its IR which leaves the enclosing method
stuck in interpreted mode.
This commit passes a `null` descriptor to restore the old pattern
(the same one used by javac.) I've checked that the JIT warnings
are gone and that the method can be compiled again.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The monitors and module instantation were inliuned into the module accessor
method in b2e0911. However, this seems to have had a detrimental impact on
performance. This might be because the module accessors are now above the
"always inline" HotSpot threshold of 35 bytes, or perhaps because they
contain monitor-entry/exit and exception handlers.
This commit returns to the the 2.11.8 appraoch of factoring
the the second check of the doublecheck locking into a method.
I've done this by declaring a nested method within the accessor;
this will be lifted out to the class level by lambdalift.
This represents a slight deviation from the implementation strategy used
for lazy accessors, which create a symbol for the slowpath method in
the info transform and generate the corresponding DefDef as a class
member. I don't believe this deviation is particular worrisome, though.
I have bootstrapped the compiler through this commit and found that
the drastic regression in compiling the shapeless test suite is solved.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Essentially, we fuse mixin and lazyvals into the fields phase.
With fields mixing in trait members into subclasses, we
have all info needed to compute bitmaps, and thus we can
synthesize the synchronisation logic as well.
By doing this before erasure we get better signatures,
and before specialized means specialized lazy vals work now.
Mixins is now almost reduced to its essence: implementing
super accessors and forwarders. It still synthesizes
accessors for param accessors and early init trait vals.
Concretely, trait lazy vals are mixed into subclasses
with the needed synchronization logic in place, as do
lazy vals in classes and methods. Similarly, modules
are initialized using double checked locking.
Since the code to initialize a module is short,
we do not emit compute methods for modules (anymore).
For simplicity, local lazy vals do not get a compute method either.
The strange corner case of constant-typed final lazy vals
is resolved in favor of laziness, by no longer assigning
a constant type to a lazy val (see widenIfNecessary in namers).
If you explicitly ask for something lazy, you get laziness;
with the constant-typedness implicit, it yields to the
conflicting `lazy` modifier because it is explicit.
Co-Authored-By: Lukas Rytz <lukas@lightbend.com>
Fixes scala/scala-dev#133
Inspired by dotc, desugar a local `lazy val x = rhs` into
```
val x$lzy = new scala.runtime.LazyInt()
def x(): Int = {
x$lzy.synchronized {
if (!x$lzy.initialized) {
x$lzy.initialized = true
x$lzy.value = rhs
}
x$lzy.value
}
}
```
Note that the 2.11 decoding (into a local variable and a bitmap) also
creates boxes for local lazy vals, in fact two for each lazy val:
```
def f = {
lazy val x = 0
x
}
```
desugars to
```
public int f() {
IntRef x$lzy = IntRef.zero();
VolatileByteRef bitmap$0 = VolatileByteRef.create((byte)0);
return this.x$1(x$lzy, bitmap$0);
}
private final int x$lzycompute$1(IntRef x$lzy$1, VolatileByteRef bitmap$0$1) {
C c = this;
synchronized (c) {
if ((byte)(bitmap$0$1.elem & 1) == 0) {
x$lzy$1.elem = 0;
bitmap$0$1.elem = (byte)(bitmap$0$1.elem | 1);
}
return x$lzy$1.elem;
}
}
private final int x$1(IntRef x$lzy$1, VolatileByteRef bitmap$0$1) {
return (byte)(bitmap$0$1.elem & 1) == 0 ?
this.x$lzycompute$1(x$lzy$1, bitmap$0$1) : x$lzy$1.elem;
}
```
An additional problem with the above encoding is that the `lzycompute`
method synchronizes on `this`. In connection with the new lambda
encoding that no longer generates anonymous classes, captured lazy vals
no longer synchronize on the lambda object.
The new encoding solves this problem (scala/scala-dev#133)
by synchronizing on the lazy holder.
Currently, we don't exploit the fact that the initialized field
is `@volatile`, because it's not clear the performance is needed
for local lazy vals (as they are not contended, and as soon as
the VM warms up, biased locking should deal with that)
Note, be very very careful when moving to double-checked locking,
as this needs a different variation than the one we use for
class-member lazy vals. A read of a volatile field of a class
does not necessarily impart any knowledge about a "subsequent" read
of another non-volatile field of the same object. A pair of
volatile reads and write can be used to implement a lock, but it's
not clear if the complexity is worth an unproven performance gain.
(Once the performance gain is proven, let's change the encoding.)
- don't explicitly init bitmap in bytecode
- must apply method to () explicitly after uncurry
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
They remain ValDefs until then.
- remove lazy accessor logic
now that we have a single ValDef for lazy vals,
with the underlying machinery being hidden until the fields phase
leave a `@deprecated def lazyAccessor` for scala-refactoring
- don't skolemize in purely synthetic getters,
but *do* skolemize in lazy accessor during typers
Lazy accessors have arbitrary user code, so have to skolemize.
We exempt the purely synthetic accessors (`isSyntheticAccessor`)
for strict vals, and lazy accessors emitted by the fields phase
to avoid spurious type mismatches due to issues with existentials
(That bug is tracked as https://github.com/scala/scala-dev/issues/165)
When we're past typer, lazy accessors are synthetic,
but before they are user-defined to make this hack less hacky,
we could rework our flag usage to allow for
requiring both the ACCESSOR and the SYNTHETIC bits
to identify synthetic accessors and trigger the exemption.
see also https://github.com/scala/scala-dev/issues/165
ok 7 - pos/existentials-harmful.scala
ok 8 - pos/t2435.scala
ok 9 - pos/existentials.scala
previous attempt: skolemize type of val inside the private[this] val
because its type is only observed from inside the
accessor methods (inside the method scope its existentials are skolemized)
- bean accessors have regular method types, not nullary method types
- must re-infer type for param accessor
some weirdness with scoping of param accessor vals and defs?
- tailcalls detect lazy vals, which are defdefs after fields
- can inline constant lazy val from trait
- don't mix in fields etc for an overridden lazy val
- need try-lift in lazy vals: the assign is not seen in uncurry
because fields does the transform (see run/t2333.scala)
- ensure field members end up final in bytecode
- implicit class companion method: annot filter in completer
- update check: previous error message was tangled up with unrelated
field definitions (`var s` and `val s_scope`),
now it behaves consistently whether those are val/vars or defs
- analyzer plugin check update seems benign, but no way to know...
- error message gen: there is no underlying symbol for a deferred var
look for missing getter/setter instead
- avoid retypechecking valdefs while duplicating for specialize
see pos/spec-private
- Scaladoc uniformly looks to field/accessor symbol
- test updates to innerClassAttribute by Lukas
|
|
|
|
|
|
| |
Rather than putting the code of a trait method body into a static method,
leave it in the default method. The static method (needed as the target
of the super calls) now uses `invokespecial` to exactly call that method.
|
|\
| |
| |
| |
| | |
SD-20 Inlcude static methods in the InlineInfo in mixed compilation
Fixes scala/scala-dev#20
|
| |
| |
| |
| |
| |
| |
| |
| | |
In mixed compilation, the InlineInfo for a Java-defined class is created
using the class symbol (vs in separate compilation, where the info is
created by looking at the classfile and its methods). The scala compiler
puts static java methods into the companion symbol, and we forgot to
include them in the list of methods in the InlineInfo.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
No longer making trait methods not-protected.
(The backend only does public/private because of the poor
mapping between visibility from Scala to the JVM).
Note that protected trait members will not receive static forwarders
in module classes (when mixed into objects).
Historic note: we used to `makeNotPrivate` during explicitouter,
now we do it later, which means more private methods must be excluded
(e.g., lambdaLIFTED ones).
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Remove some old, obsolete & untested hacks from ExplicitOuter.
Added a test for one of them to show this is now fine.
There are a lot of `makeNotPrivate` invocations sprinkled around
the codebase. Lets see if we can centralize the ones dealing
with trait methods that need implementations in the phase that emits them.
For example Fields (accessors for fields/modules) or SuperAccessors.
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
For now, keep the info transform in refchecks.
Ultimately, refchecks should only check, not transform trees/infos.
Fixes https://github.com/scala/scala-dev/issues/126:
the accessor for a module in a trait is correctly marked non-final
(it's deferred).
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
One step towards teasing apart the mixin phase, making
each phase that adds members to traits responsible for
mixing in those members into subclasses of said traits.
Another design tenet is to not emit symbols or trees
only to later remove them. Therefore, we model a
val in a trait as its accessor. The underlying field
is an implementation detail. It must be mixed into
subclasses, but has no business in a trait (an interface).
Also trying to reduce tree creation by changing less in subtrees
during tree transforms.
A lot of nice fixes fall out from this rework:
- Correct bridges and more precise generic signatures for
mixed in accessors, since they are now created before erasure.
- Correct enclosing method attribute for classes nested in trait fields.
Trait fields are now created as MethodSymbol (no longer TermSymbol).
This symbol shows up in the `originalOwner` chain of a class declared
within the field initializer. This promoted the field getter to
being the enclosing method of the nested class, which it is not
(the EnclosingMethod attribute is a source-level property).
- Signature inference is now more similar between vals and defs
- No more field for constant-typed vals, or mixed in accessors
for subclasses. A constant val can be fully implemented in a trait.
TODO:
- give same treatment to trait lazy vals (only accessors, no fields)
- remove support for presuper vals in traits
(they don't have the right init semantics in traits anyway)
- lambdalift should emit accessors for captured vals in traits,
not a field
Assorted notes from the full git history before squashing below.
Unit-typed vals: don't suppress field
it affects the memory model -- even a write of unit to a field is relevant...
unit-typed lazy vals should never receive a field
this need was unmasked by test/files/run/t7843-jsr223-service.scala,
which no longer printed the output expected from the `0 to 10 foreach`
Use getter.referenced to track traitsetter
reify's toolbox compiler changes the name of the trait
that owns the accessor between fields and constructors (`$` suffix),
so that the trait setter cannot be found when doing mkAssign in constructors
this could be solved by creating the mkAssign tree immediately during fields
anyway, first experiment: use `referenced` now that fields runs closer
to the constructors phase (I tried this before and something broke)
Infer result type for `val`s, like we do for `def`s
The lack of result type inference caused pos/t6780 to fail
in the new field encoding for traits, as there is no separate accessor,
and method synthesis computes the type signature based on the ValDef tree.
This caused a cyclic error in implicit search, because now the
implicit val's result type was not inferred from the super member,
and inferring it from the RHS would cause implicit search to consider
the member in question, so that a cycle is detected and type checking fails...
Regardless of the new encoding, we should consistently infer result types
for `def`s and `val`s.
Removed test/files/run/t4287inferredMethodTypes.scala and test/files/presentation/t4287c,
since they were relying on inferring argument types from "overridden" constructors
in a test for range positions of default arguments. Constructors don't override,
so that was a mis-feature of -Yinfer-argument-types.
Had to slightly refactor test/files/presentation/doc, as it was relying
on scalac inferring a big intersection type to approximate the anonymous
class that's instantiated for `override lazy val analyzer`.
Now that we infer `Global` as the expected type based on the overridden val,
we make `getComment` private in navigating between good old Skylla and Charybdis.
I'm not sure why we need this restriction for anonymous classes though;
only structural calls are restricted in the way that we're trying to avoid.
The old behavior is maintained nder -Xsource:2.11.
Tests:
- test/files/{pos,neg}/val_infer.scala
- test/files/neg/val_sig_infer_match.scala
- test/files/neg/val_sig_infer_struct.scala
need NMT when inferring sig for accessor
Q: why are we calling valDefSig and not methodSig?
A: traits use defs for vals, but still use valDefSig...
keep accessor and field info in synch
|
|\ \
| | |
| | | |
SD-48 limit the lenght of inlined local variable names
|
| |/
| |
| |
| |
| |
| | |
When inlining local variables, the names are prefixed with the callee
method name. In long chains of inlining, these names can grow
indefinitely. This commits introduces a limit.
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Concrete, non private methods in traits are translated into a static
method with an explicit `$this` parameter. After this translation,
the references to `$this` (subistuted for `this` in user written code)
where being positioned at the position of the method, which makes
debugging unpleasant.
This commit leaves the `Ident($this)` trees unpositioned. This is
analagous to what we do in the body of extension methods, which
is the other user of `ThisSubstitutor`.
It would be more correct to copy the position of each `This`
tree over to the substituted tree. That would let us set a breakpoint
on a line that _only_ contained `this`. But in 99% of cases users
won't be able to spot the difference, so I've opted for the tried
and tested approach here.
|
|
|
|
|
|
|
|
|
|
| |
Also logged in as SD-162
The optimizer had conservative checks in place to perform closure
elimination only for Scala Function types. We can eliminate IndyLambda
instructions for any functional interface. LambdaMetaFactory only
constructs lambda objects for interface types, which don't have any
side-effects on construction - they don't have a constructor.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
And use this as the target of the default methods or
statically resolved super or $init calls.
The call-site change is predicated on `-Yuse-trait-statics`
as a stepping stone for experimentation / bootstrapping.
I have performed this transformation in the backend,
rather than trying to reflect this in the view from
Scala symbols + ASTs.
We also need to add an restriction related to invokespecial to Java
parents: to support a super call to one of these to implement a
super accessor, the interface must be listed as a direct parent
of the class.
The static method names has a trailing $ added to avoid duplicate
name and signature errors in classfiles.
|
|
|
|
|
|
|
|
| |
So far, line numbers were kept only when inlining from the same class.
We can also keep them when inlining from a different class defined in
the same compilation unit.
Longer-term we should support JSR-45, see SI-7518 and scala-dev#3.
|
| |
|
|
|
|
|
|
| |
this change is a bit scary because it changes code that's not been
changed in 11 years
https://github.com/scala/scala/commit/7fa7c93#diff-d5789e5ae5061197d782d08324b260dbL214
|
|
|
|
|
|
|
| |
For classes being compiled (vs. being loaded from classfiles), keep the
source file path in the bytecode repo. This will allow to keep line
numbers when inlining from one class into another in case the two are
defined in the same compilation unit.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This avoids unnecessary memory retention, and allows lambdas
that call the local methods to be serializable, regardless of
whether or not the enclosing class is serializable.
The second point is especially pressing, given that the enclosing
class for local methods defined in a used to be the (serializable)
anonymous function class, but as of Scala 2.12 will be the enclosing
class of the lambda.
This change is similar in spirit to SI-9408 / 93bee55e.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The body of lambdas is compiled into a synthetic method
in the enclosing class. Previously, this method was a public
virtual method named `fully$qualified$Class$$anonfun$n`.
For lambdas that didn't capture a `this` reference, a static
method was used.
This commit changes two aspects.
Firstly, all lambda impl methods are now emitted static.
An extra parameter is added to those that require a this
reference.
This is an improvement as it:
- allows, shorter, more readable names for the lambda impl method
- avoids pollution of the vtable of the class. Note that javac uses
private instance methods, rather than public static methods. If
we followed its lead, we would be unable to support important use
cases in our inliner
Secondly, the name of the enclosing method has been included in
the name of the lambda impl method to improve debuggability and
to improve serialization compatibility. The serialization improvement
comes from the way that fresh names for the impl methods are
allocated: adding or removing lambdas in methods not named "foo" won't
change the numbering of the `anonfun$foo$n` impl methods from methods
named "foo". This is in line with user expectations about anonymous
class and lambda serialization stability. Brian Goetz has described
this tricky area well in:
http://cr.openjdk.java.net/~briangoetz/eg-attachments/lambda-serialization.html
This commit doesn't go as far a Javac, we don't use the hash of the
lambda type info, param names, etc to map to a lambda impl method name.
As such, we are more prone to the type-1 and -2 failures described there.
However, our Scala 2.11.8 has similar characteristics, so we aren't going
backwards.
Special case in the naming: Use "new" rather than "<init>" for constructor enclosed
lambdas, as javac does.
I have also changed the way that "delambdafy target" methods are identifed.
Rather than relying on the naming convention, I have switched to using a
symbol attachment. The assumption is that we only need to identify them
from within the same compilation unit.
This means we can distinguish impl metbods for expanded functions
(ones called from an `apply` method of an ahead-of-time expanded
anonfun class), from those that truly end up as targets for lambda
metafactory. Only the latter are translated to static methods in
this patch.
|
|\
| |
| | |
Debug flag to print a summary of the inliner's work
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Example output below. Note that inlining List.map fails because the
trait forwarder uses `INVOKESPECIAL` for now, will change with pr 5177.
$ cat Test.scala
class C {
def foo = Map(1 -> 'a', 2 -> 'b')
def bar(l: List[Int]) = l.map(_ + 1)
}
$ qsc -Yopt-log-inline _ -Yopt:l:classpath Test.scala
Inlining into C.foo (initially 36 instructions, ultimately 72):
- Inlined scala/Predef$ArrowAssoc$.$minus$greater$extension (8 instructions) 2 times: the callee is annotated `@inline`
Inlining into C.bar (initially 12 instructions, ultimately 12):
- Failed to inline scala/collection/immutable/List.map (the callee is a higher-order method, the argument for parameter (bf: Function1) is a function literal): The callee scala/collection/immutable/List::map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object; contains the instruction INVOKESPECIAL scala/collection/TraversableLike.map (Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;
that would cause an IllegalAccessError when inlined into class C.
|
|/
|
|
| |
Keep -Yopt-inline-heuristics and -Yopt-trace unchanged
|
|
|
|
|
| |
Also adds a mising phase travel in the backend. A comment already
points out why it's necessary, but it was actually forgotten.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Many JUnit tests share a compiler instance between all
test cases in a class to reduce overhead.
This commit refactors the mechanism to reduce the boilerplate.
In the new scheme:
- Using the `@ClassRule` hook in JUnit, we create a per-class
map for each test class.
- Per-class values are registered from the test class itself
by calling `cached("someKey", () => mkExpensiveThing)`
- At the end of the test, the entries in this map are `close()`-ed
(if they implement `Closable`), and are released for
garbage collection.)
|
|
|
|
|
| |
When inheriting multiple default methods, select the correct one to
inline. Implements method resolution according to the JVM spec.
|
|
|
|
|
|
|
|
|
| |
Implicit conversions are now in package convert as ImplicitConversions,
ImplicitConversionsToScala and ImplicitConversionsToJava.
Deprecated WrapAsJava, WrapAsScala and the values in package object.
Improve documentation.
|
|
|
|
|
| |
For some reason this was not the case, leading to spurious inliner
warnings (no inline info found for method O$lzycompute).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The code was patched many times in the history and became a bit
scattered.
When emitting a virtual call, the receiver in the bytecode cannot just
be the method's owner (the class in which it is declared), because that
class may not be accessible at the callsite. Instead we use the type
of the receiver. This was basically done to fix
- aladdin bug 455 (9954eaf)
- SI-1430 (0bea2ab) - basically the same bug, slightly different
- SI-4283 (8707c9e) - the same for field reads
In this patch we extend the fix to field writes, and clean up the code.
This patch basically reverts 6eb55d4b, the fix for SI-4560, which was
rather a workaround than a fix. The underlying problem was that in some
cases, in a method invocation `foo.bar()`, the method `bar` was not
actually a member of `foo.tpe`, causing a NoSuchMethodErrors. The
issue was related to trait implementation classes. The idea of the fix
was to check, at code-gen time, `foo.tpe.member("bar")`, and if that
returns `NoSymbol`, use `barSym.owner`. With the new trait encoding
the underlying problem seems to be fixed - all tests still pass
(run/t4560.scala and run/t4560b.scala).
|
|
|
|
|
|
|
|
| |
In most cases when a class inherits a concrete method from a trait we
don't need to generate a forwarder to the default method in the class.
t5148 is moved to pos as it compiles without error now. the error
message ("missing or invalid dependency") is still tested by t6440b.
|
| |
|
| |
|
| |
|
|\
| |
| | |
Unify treatment of built-in functions and SAMs
|