Skip to content
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

Fix #5054: Remove the dead code generated by the Labeled-based pattern matcher #5056

Merged
merged 3 commits into from
Sep 3, 2018

Conversation

sjrd
Copy link
Member

@sjrd sjrd commented Aug 28, 2018

After this PR, the tree after patmat is

    def test(s: String): Int =
      matchResult1[Int]:
        {
          case val x1: String = s
          if "Hello".==(x1) then return[matchResult1] 1 else ()
          return[matchResult1] 2
        }

and the bytecode is

  public int test(java.lang.String);
    Code:
       0: aload_1
       1: astore_2
       2: ldc           #15                 // String Hello
       4: aload_2
       5: invokevirtual #19                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
       8: ifeq          15
      11: iconst_1
      12: goto          19
      15: iconst_2
      16: goto          19
      19: ireturn

The only difference wrt. the previous implementation is now the useless goto 19 at offset 16. But that should be trivial for a peephole optimizer to get rid of.

@sjrd sjrd requested review from odersky and allanrenucci August 28, 2018 19:01
Copy link
Member

@dottybot dottybot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, and thank you for opening this PR! 🎉

All contributors have signed the CLA, thank you! ❤️

Commit Messages

We want to keep history, but for that to actually be useful we have
some rules on how to format our commit messages (relevant xkcd).

Please stick to these guidelines for commit messages:

  1. Separate subject from body with a blank line
  2. When fixing an issue, start your commit message with Fix #<ISSUE-NBR>:
  3. Limit the subject line to 72 characters
  4. Capitalize the subject line
  5. Do not end the subject line with a period
  6. Use the imperative mood in the subject line ("Add" instead of "Added")
  7. Wrap the body at 80 characters
  8. Use the body to explain what and why vs. how

adapted from https://chris.beams.io/posts/git-commit

Have an awesome day! ☀️

@allanrenucci
Copy link
Contributor

After this PR, the tree after patmat is

    def test(s: String): Int =
      matchResult1[Int]:
        {
          case val x1: String = s
          if "Hello".==(x1) then return[matchResult1] 1 else ()
          return[matchResult1] 2
        }

I see that you added a special case in the backend to not generate code if the else part if the Unit constant. Can you not generate the else branch of the if in the first place?

Also I think it would be good to add a bytecode test, that make sure that no athrow instruction is generated:

  @Test def labeledBlock = {
    val source =
      """class Test {
        |  def test(s: String) = s match {
        |    case "Hello" => 1
        |    case _       => 2
        |  }
        |}
      """.stripMargin

    checkBCode(source) { dir =>
      val clsIn = dir.lookupName("Test.class", directory = false)
      val clsNode = loadClassNode(clsIn.input)
      val method = getMethod(clsNode, "test")
      val throwMatchError = instructionsFromMethod(method).exists {
        case Op(Opcodes.ATHROW) => true
        case _ => false
      }
      assertFalse(throwMatchError)
    }
  }

@sjrd
Copy link
Member Author

sjrd commented Aug 30, 2018

Can you not generate the else branch of the if in the first place?

I'm afraid not. dotty internals do not like that. In dotty a tpd.If must have an elsep, and it cannot be EmptyTree (I tried, things blow up everywhere).

@sjrd
Copy link
Member Author

sjrd commented Aug 30, 2018

Also I think it would be good to add a bytecode test, that make sure that no athrow instruction is generated:

I have added the test, thanks! As well as a few other tests for switches.

Copy link
Contributor

@allanrenucci allanrenucci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Although, this would benefit from some documentation.

You should push your backend changes to sharing-backend and update the submodule to track the new HEAD

@@ -597,6 +603,16 @@ object PatternMatcher {
plan
}
}
override def apply(plan: SeqPlan): Plan = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should update the doc comment of def inlineVars saying that it drops unreachable branch as well

sjrd added 3 commits September 3, 2018 13:40
If the head of a `SeqPlan` cannot fall through, the tail is
unreachable and can be removed.
…hes.

This removes the last nop's generating by the `Labeled`-based
pattern matcher.
* Switch with alternatives
* Switch with guards
* No `throw` in a match with `case _ =>`
@sjrd sjrd force-pushed the opt-patmat-labeled branch from 7baec35 to 6e08649 Compare September 3, 2018 11:41
@sjrd
Copy link
Member Author

sjrd commented Sep 3, 2018

Updated. Rebased on master and addressed @allanrenucci's comments.

@allanrenucci allanrenucci merged commit e2eadf9 into scala:master Sep 3, 2018
@allanrenucci allanrenucci deleted the opt-patmat-labeled branch September 3, 2018 12:37
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.

3 participants