Skip to content

Dotty backend fails to emit code in CSE'd if predicate #1442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jvican opened this issue Aug 4, 2016 · 1 comment
Closed

Dotty backend fails to emit code in CSE'd if predicate #1442

jvican opened this issue Aug 4, 2016 · 1 comment

Comments

@jvican
Copy link
Member

jvican commented Aug 4, 2016

Code snippet:

final def sum[B](implicit num: Numeric[B]): B = {
           // arithmetic series formula  can be used for regular addition
       var cse: scala.math.Numeric.type = null.asInstanceOf[scala.math.Numeric.type]   
       if ({cse = scala.math.Numeric; num eq cse.IntIsIntegral}||
               (num eq cse.BigIntIsIntegral)||
               (num eq cse.ShortIsIntegral)||
               (num eq cse.ByteIsIntegral)||
               (num eq cse.CharIsIntegral)||
               (num eq cse.LongIsIntegral)||
               (num eq cse.FloatAsIfIntegral)||
               (num eq cse.BigDecimalIsFractional)||
               (num eq cse.DoubleAsIfIntegral)) {     
        null.asInstanceOf[B]
      } else null.asInstanceOf[B]
} 

REPL fails with:

error: Error while emitting line35$object$$iw$$iw$
1

The Linker (in the branch cse-rebase, that implements Common Subexpression Elimination) fails with a more concise error:

java.lang.ArrayIndexOutOfBoundsException: 1
    at scala.tools.asm.Frame.merge(Frame.java:1397)
    at scala.tools.asm.Frame.merge(Frame.java:1352)
    at scala.tools.asm.MethodWriter.visitMaxs(MethodWriter.java:1483)
    at scala.tools.asm.tree.MethodNode.accept(MethodNode.java:834)
    at scala.tools.asm.tree.MethodNode.accept(MethodNode.java:726)
    at scala.tools.asm.tree.ClassNode.accept(ClassNode.java:412)
    at dotty.tools.backend.jvm.GenBCodePipeline$Worker2.getByteArray$1(GenBCode.scala:272)
    at dotty.tools.backend.jvm.GenBCodePipeline$Worker2.addToQ3(GenBCode.scala:279)
    at dotty.tools.backend.jvm.GenBCodePipeline$Worker2.run(GenBCode.scala:258)
    at dotty.tools.backend.jvm.GenBCodePipeline.buildAndSendToDisk(GenBCode.scala:361)
    at dotty.tools.backend.jvm.GenBCodePipeline.run(GenBCode.scala:324)
    at dotty.tools.backend.jvm.GenBCode.run(GenBCode.scala:56)
    at dotty.tools.dotc.core.Phases$Phase$$anonfun$runOn$1.apply(Phases.scala:279)
    at dotty.tools.dotc.core.Phases$Phase$$anonfun$runOn$1.apply(Phases.scala:277)
    at scala.collection.immutable.List.map(List.scala:273)
    at dotty.tools.dotc.core.Phases$Phase$class.runOn(Phases.scala:277)
    at dotty.tools.backend.jvm.GenBCode.runOn(GenBCode.scala:40)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1$$anonfun$apply$mcV$sp$1.apply(Run.scala:62)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1$$anonfun$apply$mcV$sp$1.apply(Run.scala:59)
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
    at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1.apply$mcV$sp(Run.scala:59)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1.apply(Run.scala:54)
    at dotty.tools.dotc.Run$$anonfun$compileUnits$1.apply(Run.scala:54)
    at dotty.tools.dotc.util.Stats$.monitorHeartBeat(Stats.scala:69)
    at dotty.tools.dotc.Run.compileUnits(Run.scala:54)
    at dotty.tools.dotc.Run.compileSources(Run.scala:51)
    at dotty.tools.dotc.Run.compile(Run.scala:35)
    at dotty.tools.dotc.Driver.doCompile(Driver.scala:26)
    at dotty.tools.dotc.Driver.process(Driver.scala:124)
    at dotty.tools.dotc.Driver.process(Driver.scala:93)
    at dotty.tools.dotc.Driver.process(Driver.scala:105)
    at test.CompilerTest.compileArgs(CompilerTest.scala:237)
    at test.CompilerTest.compileFile(CompilerTest.scala:106)
    at dotc.tests.dotty(tests.scala:151)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runners.Suite.runChild(Suite.java:127)
    at org.junit.runners.Suite.runChild(Suite.java:26)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:138)
    at com.novocode.junit.JUnitRunner$1.execute(JUnitRunner.java:132)
    at sbt.ForkMain$Run$2.call(ForkMain.java:296)
    at sbt.ForkMain$Run$2.call(ForkMain.java:286)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
error: Error while emitting scala/collection/immutable/NumericRange
1

It seems to me that this code should compile. Therefore, I consider this a bug. The original source code is located in the Numeric class of the Scala standard library.

@DarkDimius
Copy link
Contributor

For future reference. I've introduced an undocumented environment variable printBCODE, that specifies which methods to print.
In this example:

printBCODE=sum dotc bfail.scala
Bytecode for method sum
   L0
    LINENUMBER 2 L0
   L1
    LINENUMBER 4 L1
    ACONST_NULL
    CHECKCAST scala/math/Numeric$
   L2
    ASTORE 2
   L3
    LINENUMBER 5 L3
    GETSTATIC scala/math/Numeric$.MODULE$ : Lscala/math/Numeric$;
    ASTORE 2
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$IntIsIntegral$.MODULE$ : Lscala/math/Numeric$IntIsIntegral$;
    IF_ACMPEQ L4
    GOTO L5
   L4
    ICONST_1
    GOTO L6
   L5
    ICONST_0
   L6
    IFNE L7
    GOTO L8
   L8
    LINENUMBER 6 L8
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$BigIntIsIntegral$.MODULE$ : Lscala/math/Numeric$BigIntIsIntegral$;
    IF_ACMPEQ L7
    GOTO L9
   L9
    LINENUMBER 7 L9
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$ShortIsIntegral$.MODULE$ : Lscala/math/Numeric$ShortIsIntegral$;
    IF_ACMPEQ L7
    GOTO L10
   L10
    LINENUMBER 8 L10
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$ByteIsIntegral$.MODULE$ : Lscala/math/Numeric$ByteIsIntegral$;
    IF_ACMPEQ L7
    GOTO L11
   L11
    LINENUMBER 9 L11
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$CharIsIntegral$.MODULE$ : Lscala/math/Numeric$CharIsIntegral$;
    IF_ACMPEQ L7
    GOTO L12
   L12
    LINENUMBER 10 L12
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$LongIsIntegral$.MODULE$ : Lscala/math/Numeric$LongIsIntegral$;
    IF_ACMPEQ L7
    GOTO L13
   L13
    LINENUMBER 11 L13
    ALOAD 1
    ALOAD 2 
    // HERE IS THE BUG.
    GETSTATIC scala/math/Numeric$FloatAsIfIntegral$.MODULE$ : Lscala/math/Numeric$FloatAsIfIntegral$;
    IF_ACMPEQ L7
    GOTO L14
   L14
    LINENUMBER 12 L14
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$BigDecimalIsFractional$.MODULE$ : Lscala/math/Numeric$BigDecimalIsFractional$;
    IF_ACMPEQ L7
    GOTO L15
   L15
    LINENUMBER 13 L15
    ALOAD 1
    ALOAD 2
    GETSTATIC scala/math/Numeric$DoubleAsIfIntegral$.MODULE$ : Lscala/math/Numeric$DoubleAsIfIntegral$;
    IF_ACMPEQ L7
    GOTO L16
   L7
    LINENUMBER 14 L7
    ACONST_NULL
    POP
    ACONST_NULL
    GOTO L17
   L16
    LINENUMBER 15 L16
    ACONST_NULL
    POP
    ACONST_NULL
   L17
    ARETURN
   L18
    LOCALVARIABLE cse Lscala/math/Numeric$; L2 L17 2
    LOCALVARIABLE this LTest$; L1 L18 0
    LOCALVARIABLE num Lscala/math/Numeric; L1 L18 1
    MAXSTACK = 0
    MAXLOCALS = 0

@DarkDimius DarkDimius self-assigned this Aug 9, 2016
DarkDimius added a commit to dotty-staging/dotty that referenced this issue Aug 9, 2016
DarkDimius added a commit that referenced this issue Aug 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants