Classfile API Synchronous Stack Tracking in CodeBuilder
Paul Sandoz
paul.sandoz at oracle.com
Wed Aug 24 19:38:23 UTC 2022
The implementation looks good (I did not verify the correctness of all the instructions in StackTracker).
Seems useful functionality that is otherwise laborious and error prone to implement.
Requiring ExceptionCatch (and ExceptionCatchAll, not suppported) be reported before the target label is bound is awkward, but it's clear why. I think that would require documentation, and perhaps it should fail since it will otherwise report incorrect stack data?
Paul.
> On Aug 24, 2022, at 6:54 AM, Adam Sotona <adam.sotona at oracle.com> wrote:
>
> Hi,
> I would like to hear your comments to proposed optional stack tracking functionality integrated in CodeBuilder.
>
> Here is the pull request proposing to add:
> • Classfile.Option::trackStack boolean option with default to false (the new option enabling stack tracking during code build)
> • Optional<Collection<TypeKind>> CodeBuilder::stack – a method returning view of the actual stack synchronously during the build process (if enabled)
> • Optional<Integer> CodeBuilder::maxStackSize - a method calculating maxStackSize (if enabled)
> • impl.StackTracker implementation – a lightweight synchronous stack tracker
> • StackTrackerTest tests
>
> Beside the stack tracking the pull request adds ConstantInstruction::typeKind and LoadableConstantEntry::typeKind methods self-describing ConstantInstruction and LoadableConstantEntry (not just) for the stack tracking purpose.
>
> Here is the pull request:
> https://github.com/openjdk/jdk-sandbox/pull/34
>
> Primary purpose of the lightweight synchronous stack tracking is to support building of complex swap functions like stack-to-locals and locals-to-stack in CodeBuilder.
>
> Example use case can be found in the StackTrackerTest:
> Classfile.build(ClassDesc.of("Foo"), List.of(Classfile.Option.trackStack(true)), clb ->
> clb.withMethodBody("m", MethodTypeDesc.of(ConstantDescs.CD_Void), 0, cob -> {
> assertEquals(cob.stack().get(), List.of());
> cob.aload(0);
> assertEquals(cob.stack().get(), List.of(ReferenceType));
> cob.lconst_0();
> assertEquals(cob.stack().get(), List.of(LongType, ReferenceType));
> cob.trying(tryb -> {
> assertEquals(tryb.stack().get(), List.of(LongType, ReferenceType));
> tryb.iconst_1();
> assertEquals(tryb.stack().get(), List.of(IntType, LongType, ReferenceType));
> tryb.ifThen(thb -> {
> assertEquals(thb.stack().get(), List.of(LongType, ReferenceType));
> thb.constantInstruction(ClassDesc.of("Phee"));
> assertEquals(thb.stack().get(), List.of(ReferenceType, LongType, ReferenceType));
> thb.athrow();
> assertFalse(thb.stack().isPresent());
> });
> assertEquals(tryb.stack().get(), List.of(LongType, ReferenceType));
> tryb.return_();
> assertFalse(tryb.stack().isPresent());
> }, catchb -> catchb.catching(ClassDesc.of("Phee"), cb -> {
> assertEquals(cb.stack().get(), List.of(ReferenceType));
> cb.athrow();
> assertFalse(cb.stack().isPresent());
> }));
> assertTrue(cob.maxStackSize().isPresent());
> assertEquals((int)cob.maxStackSize().get(), 4);
> }));
>
> Thanks,
> Adam
More information about the classfile-api-dev
mailing list