rorygraves / scalac_perf

The Scala programming language
http://www.scala-lang.org/
16 stars 3 forks source link

bytecode for += and field access #20

Open mkeskells opened 7 years ago

mkeskells commented 7 years ago

accessing vars generate inefficient bytecode, and non idiomatic code WRT java equiv

Not sure if this is inefficient machine code though, but at least it is increating the classfile size

comparing with java -

mkeskells commented 6 years ago
object Foo {
  private[this] var data1 = 7
  private var data2 = 7
  final var data3 = 7

  data1 += 1
  data2 += 1
  data3 += 1

  def foo: Unit = {
    var data1 = 7
    data1 += 1
    this.data1 += 1
    this.data2 += 1
  }
}

generated bytecode (abbriviated) of

public final class scala/tools/nsc/classpath/Foo$ {

... private I data1 private I data2 private I data3

private data2()I ... private data2$eq(I)V ... public final data3()I ... public final data3$eq(I)V ... public foo()V L0 LINENUMBER 14 L0 BIPUSH 7 L1 ISTORE 1 L2 LINENUMBER 15 L2 ILOAD 1 ICONST_1 IADD ISTORE 1 L3 LINENUMBER 16 L3 ALOAD 0 ALOAD 0 GETFIELD scala/tools/nsc/classpath/Foo$.data1 : I ICONST_1 IADD PUTFIELD scala/tools/nsc/classpath/Foo$.data1 : I L4 LINENUMBER 17 L4 ALOAD 0 ALOAD 0 INVOKESPECIAL scala/tools/nsc/classpath/Foo$.data2 ()I ICONST1 IADD INVOKESPECIAL scala/tools/nsc/classpath/Foo$.data2$eq (I)V L5 RETURN L6 ... private ()V L0 LINENUMBER 153 L0 ALOAD 0 INVOKESPECIAL java/lang/Object. ()V ALOAD 0 PUTSTATIC scala/tools/nsc/classpath/Foo$.MODULE$ : Lscala/tools/nsc/classpath/Foo$; L1 LINENUMBER 5 L1 ALOAD 0 BIPUSH 7 PUTFIELD scala/tools/nsc/classpath/Foo$.data1 : I L2 LINENUMBER 6 L2 ALOAD 0 BIPUSH 7 PUTFIELD scala/tools/nsc/classpath/Foo$.data2 : I L3 LINENUMBER 7 L3 ALOAD 0 BIPUSH 7 PUTFIELD scala/tools/nsc/classpath/Foo$.data3 : I L4 LINENUMBER 9 L4 ALOAD 0 ALOAD 0 GETFIELD scala/tools/nsc/classpath/Foo$.data1 : I ICONST_1 IADD PUTFIELD scala/tools/nsc/classpath/Foo$.data1 : I L5 LINENUMBER 10 L5 ALOAD 0 ALOAD 0 INVOKESPECIAL scala/tools/nsc/classpath/Foo$.data2 ()I ICONST1 IADD **INVOKESPECIAL scala/tools/nsc/classpath/Foo$.data2$eq (I)V L6 LINENUMBER 11 L6 ALOAD 0 ALOAD 0 INVOKEVIRTUAL scala/tools/nsc/classpath/Foo$.data3 ()I ICONST_1 IADD INVOKEVIRTUAL scala/tools/nsc/classpath/Foo$.data3_$eq (I)V** L7 LINENUMBER 4 L7 RETURN }

compare this with java

public class XX {
    int data1 = 7;

    XX() {
        this.data1 += 1;
    }

    void foo() {
        int data1 = 7;
        data1 += 1;
        this.data1 += 1;
    }
}

generates

I data1

()V ... ALOAD 0 **DUP** **GETFIELD scala/tools/nsc/classpath/XX.data1 : I** ICONST_1 IADD **PUTFIELD scala/tools/nsc/classpath/XX.data1 : I** L3 LINENUMBER 7 L3 RETURN L4 LOCALVARIABLE this Lscala/tools/nsc/classpath/XX; L0 L4 0 MAXSTACK = 3 MAXLOCALS = 1 // access flags 0x0 foo()V L0 LINENUMBER 10 L0 BIPUSH 7 ISTORE 1 L1 LINENUMBER 11 L1 **IINC 1 1** L2 LINENUMBER 12 L2 ALOAD 0 **DUP GETFIELD scala/tools/nsc/classpath/XX.data1 : I ICONST_1 IADD PUTFIELD scala/tools/nsc/classpath/XX.data1 : I** L3 LINENUMBER 13 L3 RETURN } ```