Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

retronym
Copy link
Member

Although the same the code would be later optimized by -Yconst-opt,
we can offer the same lean byte code to those compiling without that
option by being more discerning when translating ==.

This helps people using bytecode based code coverage tools
such as jacoco that would emit "branch not covered" warnings
for the impossible null check.

Before:

scala> class C { (null: Any) match { case Nil => case "" => case _ => } }
defined class C

scala> :javap C

public C();
  Code:
   Stack=2, Locals=5, Args_size=1
   0:   aload_0
   1:   invokespecial   #9; //Method java/lang/Object."<init>":()V
   4:   aconst_null
   5:   astore_1
   6:   getstatic   #15; //Field scala/collection/immutable/Nil$.MODULE$:Lscala/collection/immutable/Nil$;
   9:   aload_1
   10:  astore_2
   11:  dup
   12:  ifnonnull   23
   15:  pop
   16:  aload_2
   17:  ifnull  30
   20:  goto    37
   23:  aload_2
   24:  invokevirtual   #19; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
   27:  ifeq    37
   30:  getstatic   #25; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   33:  astore_3
   34:  goto    74
   37:  ldc #27; //String
   39:  aload_1
   40:  astore  4
   42:  dup
   43:  ifnonnull   55
   46:  pop
   47:  aload   4
   49:  ifnull  63
   52:  goto    70
   55:  aload   4
   57:  invokevirtual   #19; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
   60:  ifeq    70
   63:  getstatic   #25; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   66:  astore_3
   67:  goto    74
   70:  getstatic   #25; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   73:  astore_3
   74:  return
  LocalVariableTable:
   Start  Length  Slot  Name   Signature

After:

public C();
  Code:
   Stack=2, Locals=3, Args_size=1
   0:   aload_0
   1:   invokespecial   #9; //Method java/lang/Object."<init>":()V
   4:   aconst_null
   5:   astore_1
   6:   getstatic   #15; //Field scala/collection/immutable/Nil$.MODULE$:Lscala/collection/immutable/Nil$;
   9:   aload_1
   10:  invokevirtual   #19; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
   13:  ifeq    23
   16:  getstatic   #25; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   19:  astore_2
   20:  goto    43
   23:  ldc #27; //String
   25:  aload_1
   26:  invokevirtual   #19; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
   29:  ifeq    39
   32:  getstatic   #25; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   35:  astore_2
   36:  goto    43
   39:  getstatic   #25; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   42:  astore_2
   43:  return

Review by @gkossakowski or @JamesIry, /cc @dragos

Will be somewhat leaner after the next commit.
Although the same the code would be later optimized by -Yconst-opt,
we can offer the same lean byte code to those compiling without that
option by being more discerning when translating ==.

This helps people using bytecode based code coverage tools
such as jacoco that would emit "branch not covered" warnings
for the impossible null check.
For which we can also elide the null check, and will in the
next commit.
@retronym
Copy link
Member Author

I'm happy to rework the tests a little, it will be a bit less brittle if we assert the absence of null check instructions.

@gkossakowski
Copy link
Contributor

@retronym: rewriting those tests to test the specific property we care about would be very welcome.

Also, please reopen once test failures are addressed.

For the same reasons outlined in the previous commits.
 - Directly count null checks, rather than diffing the textual
   bytecode of the entire method
 - Add a test to show that the LHS needs to be a direct module
   reference, not just a tree with a module type, to elide the
   null check.
@retronym retronym reopened this Sep 18, 2013
@retronym
Copy link
Member Author

@gkossakowski The latest push does both of those things :) I left the bytcode-diffing tests in the history as they might be easier to review, the the last commit switches to counting null check instructions.

@ghost ghost assigned gkossakowski Sep 18, 2013
@dragos
Copy link
Contributor

dragos commented Sep 20, 2013

LGTM! I like the tests.

@gkossakowski
Copy link
Contributor

LGTM as well!

I'll hold the merge until build bot comes back and can verify this branch.

retronym added a commit that referenced this pull request Sep 23, 2013
Avoid null checks when emitting "".== and SomeModule.==
@retronym retronym merged commit 469d303 into scala:master Sep 23, 2013
lrytz added a commit to lrytz/scala that referenced this pull request May 7, 2014
Avoid null checks for "someLiteral".== and SomeModule.==. This has
been implemented in GenICode in scala#2954.

Introduces a trait to share code between GenICode and GenBCode. This
is just a start, more such refactorings will come quite certainly.
lrytz added a commit to lrytz/scala that referenced this pull request May 7, 2014
Avoid null checks for "someLiteral".== and SomeModule.==. This has
been implemented in GenICode in scala#2954.

Introduces a trait to share code between GenICode and GenBCode. This
is just a start, more such refactorings will come quite certainly.
@lrytz lrytz mentioned this pull request May 7, 2014
@lrytz
Copy link
Member

lrytz commented Feb 12, 2016

The optimization is not correct for modules, https://issues.scala-lang.org/browse/SI-9655

@sjrd
Copy link
Member

sjrd commented Feb 12, 2016

The optimization is not correct for modules, https://issues.scala-lang.org/browse/SI-9655

Do we care? I mean, code where a module load returns null is already broken, right?

FTR Scala.js considers this UB.

@lrytz
Copy link
Member

lrytz commented Feb 12, 2016

well, define broken :) the example prints null, and behaves as specified

class C {
  println(O)
}
object O extends C

i'd love to make the assumption that module loads are always non-null. maybe we can, but it definitely changes program semantics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants