Skip to content

WIP Avoid ObjectRef overhead for effectively final case vars #66

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
wants to merge 1 commit into from

Conversation

retronym
Copy link
Owner

@retronym retronym commented Aug 27, 2019

Given

class C {
    lazy val s: reflect.internal.SymbolTable = ???
    import s._
    def test(t: Tree) = {
        t match {
            case ap @ Apply(sel @ Select(_, _), _) if (ap, sel).hashCode > 0 =>
                1
            case ap @ Apply(sel @ Select(_, _), _) if (ap, sel).hashCode == 0 =>
                () => ap
        }
    }
}
$ scalac  -Xprint:jvm sandbox/test.scala  2>&1 | tee /tmp/old && qscalac  -Xprint:jvm sandbox/test.scala  2>&1 | tee /tmp/new && diff -U1000 /tmp/{old,new}
--- /tmp/old    2019-08-27 10:47:15.000000000 +1000
+++ /tmp/new    2019-08-27 10:47:18.000000000 +1000
@@ -1,80 +1,80 @@
 [[syntax trees at end of                       jvm]] // test.scala
 package <empty> {
   class C extends Object {
     final <synthetic> lazy private[this] var s: scala.reflect.internal.SymbolTable = _;
     @volatile private[this] var bitmap$0: Boolean = _;
     private def s$lzycompute(): scala.reflect.internal.SymbolTable = {
       C.this.synchronized(if (C.this.bitmap$0.unary_!())
         {
           C.this.s = (scala.Predef.???(): scala.reflect.internal.SymbolTable);
           C.this.bitmap$0 = true
         });
       C.this.s
     };
-    <stable> <accessor> lazy def s(): scala.reflect.internal.SymbolTable = (if (C.this.bitmap$0.unary_!())
+    <stable> <accessor> lazy def s(): scala.reflect.internal.SymbolTable = if (C.this.bitmap$0.unary_!())
       C.this.s$lzycompute()
     else
-      C.this.s: scala.reflect.internal.SymbolTable);
+      C.this.s;
     def test(t: reflect.internal.Trees$Tree): Object = {
       <synthetic> var rc13: Boolean = false;
-      <synthetic> var x2: runtime.ObjectRef = scala.runtime.ObjectRef.create((null: reflect.internal.Trees$Apply));
+      <synthetic> <stable> var x2: reflect.internal.Trees$Apply = (null: reflect.internal.Trees$Apply);
       {
         case <synthetic> val x1: reflect.internal.Trees$Tree = t;
         case15(){
           if (x1.$isInstanceOf[reflect.internal.Trees$Apply]())
             {
               rc13 = true;
-              x2.elem = (x1.$asInstanceOf[reflect.internal.Trees$Apply](): reflect.internal.Trees$Apply);
+              x2 = (x1.$asInstanceOf[reflect.internal.Trees$Apply](): reflect.internal.Trees$Apply);
               {
-                val sel: reflect.internal.Trees$Tree = x2.elem.$asInstanceOf[reflect.internal.Trees$Apply]().fun();
+                val sel: reflect.internal.Trees$Tree = x2.fun();
                 if (sel.$isInstanceOf[reflect.internal.Trees$Select]())
                   {
                     <synthetic> val x4: reflect.internal.Trees$Select = (sel.$asInstanceOf[reflect.internal.Trees$Select](): reflect.internal.Trees$Select);
-                    if (new Tuple2(x2.elem.$asInstanceOf[reflect.internal.Trees$Apply](), x4).hashCode().>(0))
+                    if (new Tuple2(x2, x4).hashCode().>(0))
                       matchEnd14(scala.Int.box(1))
                     else
                       case16()
                   }
                 else
                   case16()
               }
             }
           else
             case16()
         };
         case16(){
           if (rc13)
             {
-              val sel: reflect.internal.Trees$Tree = x2.elem.$asInstanceOf[reflect.internal.Trees$Apply]().fun();
+              val sel: reflect.internal.Trees$Tree = x2.fun();
               if (sel.$isInstanceOf[reflect.internal.Trees$Select]())
                 {
                   <synthetic> val x9: reflect.internal.Trees$Select = (sel.$asInstanceOf[reflect.internal.Trees$Select](): reflect.internal.Trees$Select);
-                  if (new Tuple2(x2.elem.$asInstanceOf[reflect.internal.Trees$Apply](), x9).hashCode().==(0))
+                  if (new Tuple2(x2, x9).hashCode().==(0))
                     matchEnd14({
                       $anonfun(x2)
                     })
                   else
                     case17()
                 }
               else
                 case17()
             }
           else
             case17()
         };
         case17(){
           matchEnd14(throw new MatchError(x1))
         };
         matchEnd14(x: Object){
           x
         }
       }
     };
-    final <static> <artifact> def $anonfun$test$1(x2$1: runtime.ObjectRef): reflect.internal.Trees$Apply = x2$1.elem.$asInstanceOf[reflect.internal.Trees$Apply]();
+    final <static> <artifact> def $anonfun$test$1(x2$1: reflect.internal.Trees$Apply): reflect.internal.Trees$Apply = x2$1;
     def <init>(): C = {
       C.super.<init>();
       ()
     }
   }
 }

@retronym retronym force-pushed the faster/case-var-no-capture branch 3 times, most recently from 4f9506b to cf2937b Compare August 27, 2019 00:48
@retronym retronym force-pushed the faster/case-var-no-capture branch from cf2937b to 744a984 Compare August 27, 2019 01:17
Given

```scala
class C {
    lazy val s: reflect.internal.SymbolTable = ???
    import s._
    def test(t: Tree) = {
        t match {
            case ap @ Apply(sel @ Select(_, _), _) if (ap, sel).hashCode > 0 =>
                1
            case ap @ Apply(sel @ Select(_, _), _) if (ap, sel).hashCode == 0 =>
                () => ap
        }
    }
}
```

```
$ scalac  -Xprint:jvm sandbox/test.scala  2>&1 | tee /tmp/old && qscalac  -Xprint:jvm sandbox/test.scala  2>&1 | tee /tmp/new && diff -U1000 /tmp/{old,new}
```

```diff
--- /tmp/old    2019-08-27 10:47:15.000000000 +1000
+++ /tmp/new    2019-08-27 10:47:18.000000000 +1000
@@ -1,80 +1,80 @@
 [[syntax trees at end of                       jvm]] // test.scala
 package <empty> {
   class C extends Object {
     final <synthetic> lazy private[this] var s: scala.reflect.internal.SymbolTable = _;
     @volatile private[this] var bitmap$0: Boolean = _;
     private def s$lzycompute(): scala.reflect.internal.SymbolTable = {
       C.this.synchronized(if (C.this.bitmap$0.unary_!())
         {
           C.this.s = (scala.Predef.???(): scala.reflect.internal.SymbolTable);
           C.this.bitmap$0 = true
         });
       C.this.s
     };
-    <stable> <accessor> lazy def s(): scala.reflect.internal.SymbolTable = (if (C.this.bitmap$0.unary_!())
+    <stable> <accessor> lazy def s(): scala.reflect.internal.SymbolTable = if (C.this.bitmap$0.unary_!())
       C.this.s$lzycompute()
     else
-      C.this.s: scala.reflect.internal.SymbolTable);
+      C.this.s;
     def test(t: reflect.internal.Trees$Tree): Object = {
       <synthetic> var rc13: Boolean = false;
-      <synthetic> var x2: runtime.ObjectRef = scala.runtime.ObjectRef.create((null: reflect.internal.Trees$Apply));
+      <synthetic> <stable> var x2: reflect.internal.Trees$Apply = (null: reflect.internal.Trees$Apply);
       {
         case <synthetic> val x1: reflect.internal.Trees$Tree = t;
         case15(){
           if (x1.$isInstanceOf[reflect.internal.Trees$Apply]())
             {
               rc13 = true;
-              x2.elem = (x1.$asInstanceOf[reflect.internal.Trees$Apply](): reflect.internal.Trees$Apply);
+              x2 = (x1.$asInstanceOf[reflect.internal.Trees$Apply](): reflect.internal.Trees$Apply);
               {
-                val sel: reflect.internal.Trees$Tree = x2.elem.$asInstanceOf[reflect.internal.Trees$Apply]().fun();
+                val sel: reflect.internal.Trees$Tree = x2.fun();
                 if (sel.$isInstanceOf[reflect.internal.Trees$Select]())
                   {
                     <synthetic> val x4: reflect.internal.Trees$Select = (sel.$asInstanceOf[reflect.internal.Trees$Select](): reflect.internal.Trees$Select);
-                    if (new Tuple2(x2.elem.$asInstanceOf[reflect.internal.Trees$Apply](), x4).hashCode().>(0))
+                    if (new Tuple2(x2, x4).hashCode().>(0))
                       matchEnd14(scala.Int.box(1))
                     else
                       case16()
                   }
                 else
                   case16()
               }
             }
           else
             case16()
         };
         case16(){
           if (rc13)
             {
-              val sel: reflect.internal.Trees$Tree = x2.elem.$asInstanceOf[reflect.internal.Trees$Apply]().fun();
+              val sel: reflect.internal.Trees$Tree = x2.fun();
               if (sel.$isInstanceOf[reflect.internal.Trees$Select]())
                 {
                   <synthetic> val x9: reflect.internal.Trees$Select = (sel.$asInstanceOf[reflect.internal.Trees$Select](): reflect.internal.Trees$Select);
-                  if (new Tuple2(x2.elem.$asInstanceOf[reflect.internal.Trees$Apply](), x9).hashCode().==(0))
+                  if (new Tuple2(x2, x9).hashCode().==(0))
                     matchEnd14({
                       $anonfun(x2)
                     })
                   else
                     case17()
                 }
               else
                 case17()
             }
           else
             case17()
         };
         case17(){
           matchEnd14(throw new MatchError(x1))
         };
         matchEnd14(x: Object){
           x
         }
       }
     };
-    final <static> <artifact> def $anonfun$test$1(x2$1: runtime.ObjectRef): reflect.internal.Trees$Apply = x2$1.elem.$asInstanceOf[reflect.internal.Trees$Apply]();
+    final <static> <artifact> def $anonfun$test$1(x2$1: reflect.internal.Trees$Apply): reflect.internal.Trees$Apply = x2$1;
     def <init>(): C = {
       C.super.<init>();
       ()
     }
   }
 }

```
@retronym retronym force-pushed the faster/case-var-no-capture branch from 744a984 to c69a52b Compare August 27, 2019 01:20
@retronym retronym closed this Aug 27, 2019
@retronym
Copy link
Owner Author

Upstream: scala#8375

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.

1 participant