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

Shorter bytecode sequences to record array and Set values #104

Open
Sanne opened this issue Apr 29, 2022 · 0 comments
Open

Shorter bytecode sequences to record array and Set values #104

Sanne opened this issue Apr 29, 2022 · 0 comments

Comments

@Sanne
Copy link
Member

Sanne commented Apr 29, 2022

In Quarkus, and in particular in ArC, there's the frequent need to generate code to record a Set of Class constants; for example any created InjectableBean will have a field private final Set types; which needs to be initialized in the constructor.

The code being generated today is very verbose and generates intermediate variables for each individual element of the array; for example, focusing on the "type" use case we'd typically have:

		Object[] var1 = new Object[2];
		Class var2 = someClazz();
		var1[0] = var2;
		Class var3 = someClazz();
		var1[1] = var3;
		Set var4 = Set.of(var1);
		this.types = var4;

as bytecode:

         0: iconst_2
         1: anewarray     #2                  // class java/lang/Object
         4: astore_1
         5: invokestatic  #3                  // Method someClazz:()Ljava/lang/Class;
         8: astore_2
         9: aload_1
        10: iconst_0
        11: aload_2
        12: aastore
        13: invokestatic  #3                  // Method someClazz:()Ljava/lang/Class;
        16: astore_3
        17: aload_1
        18: iconst_1
        19: aload_3
        20: aastore
        21: aload_1
        22: invokestatic  #4                  // InterfaceMethod java/util/Set.of:([Ljava/lang/Object;)Ljava/util/Set;
        25: astore        4
        27: aload_0
        28: aload         4
        30: putfield      #5                  // Field types:Ljava/util/Set;

While this could have been expressed better as:

this.types = Set.of(someClazz(), someClazz());
         0: aload_0
         1: invokestatic  #3                  // Method someClazz:()Ljava/lang/Class;
         4: invokestatic  #3                  // Method someClazz:()Ljava/lang/Class;
         7: invokestatic  #7                  // InterfaceMethod java/util/Set.of:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Set;
        10: putfield      #5                  // Field types:Ljava/util/Set;

There's several minor benefits such ask bytecode size and the ability to skip allocating the array, but most importantly the lack of need for local variables would allow us to save space in the Constant Pool.

It would be nice to introduce some ad-hoc optimisations for these common patterns as required by ArC; we could simplify quite some code by just having specific support for recording immutable Sets and arrays.

I'm suggesting to add both optimisations:

ad-hoc optimized method for immutable, small Set creation

As made clear above, there's many benefits from this and set creation seems to be a very common need - in both ArC and likely other components too.

ad-hoc optimized method for storing arrays

This should help cover many other usecases; there are cases in which we need to store arrays that get non-trivial in size, and not all of them get folded into a Set. Having ad-hoc optimisations for arrays would give some more flexibility and address the largest consumers of space in the constant table.

Automatic elision of variable allocations

Ideally, but probably a much larger effort, it would be nice to see if gizmo could automatically chain directly consumed ResultHandler(s) which are consumed only once so to not need local variables in such cases but use the stack.

That would have a more pervasive effect in removing many more variables, however seems to require some substantial design changes and I also suspect it wouldn't be able to generate the above optimal bytecode, so I'd focus on the Set and Array optimisations first.

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

1 participant