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

compile time constants #60

Open
mkeskells opened this issue Mar 19, 2018 · 6 comments
Open

compile time constants #60

mkeskells opened this issue Mar 19, 2018 · 6 comments

Comments

@mkeskells
Copy link
Collaborator

It seems that some constants are deferred to run time.
This means that they generate more bytecode, and cant (probably) be inlined

e.g. Flags.scala has code like

  final val PRIVATE       = 1 << 2
...
  final val LateShift     = 47
  final val AntiShift     = 56
...
  final val notPRIVATE    = (PRIVATE: Long) << AntiShift

generate bytecode like


  // access flags 0x11
  public final AntiFlags()J
   L0
    LDC 504403158265495552
    LRETURN
   L1
    LOCALVARIABLE this Lscala/reflect/internal/Flags; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x11
  public final LateShift()I
   L0
    BIPUSH 47
    IRETURN
   L1
    LOCALVARIABLE this Lscala/reflect/internal/Flags; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

but not for all fields
e.g


  // access flags 0x11
  public final notPRIVATE()J
   L0
    LINENUMBER 231 L0
    ALOAD 0
    GETFIELD scala/reflect/internal/Flags.notPRIVATE : J
    LRETURN
   L1
    LOCALVARIABLE this Lscala/reflect/internal/Flags; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 1
@retronym
Copy link

(PRIVATE: Long) << AntiShift is not a constant expression, so it fall through the constant folder.

We could update that to make a widening of a constant also be a constant. In addition to changing that code, this part of the spec would need to be augmented.

@retronym
Copy link

retronym commented Mar 20, 2018

Or, without changing the spec, we could just use 0L + PRIVATE instead of (PRIVATE: Long).

scala> object C { final val PRIVATE = 1 << 2; final val AntiShift     = 56; final val notPRIVATE = (0L + PRIVATE) << AntiShift }
defined object C

scala> class Test { def foo = C.notPRIVATE }
defined class Test

scala> :javap -c Test#foo
  public long foo();
    Code:
       0: ldc2_w        #16                 // long 288230376151711744l
       3: lreturn

@retronym
Copy link

scala#6445

@mkeskells
Copy link
Collaborator Author

mkeskells commented Mar 20, 2018

I think that it is worth considering changing the spec, as that will be beneficial to other cases outside the Flags.

It seem strange that implicit widening is optimised, but explicit is not. Presumably narrowing isn't either

This will have an impact on performance I think as these constants get inlined to the caller
@retronym @adriaanm do you have any concerns about widened the spec (in 2.13)

@mkeskells
Copy link
Collaborator Author

discussed with @retronym on gitter -
~Long is not folding as expected

@retronym
Copy link

WIP https://github.com/scala/scala/compare/2.13.x...retronym:topic/constant-folder-unary?expand=1

There is overlap with scala#6452, which also needs to introduce some constant-related logic in typedSelect. We're discussing it all over there.

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

No branches or pull requests

2 participants