From 7c76e52310b33ad1af245c7dd8a52e796fa07786 Mon Sep 17 00:00:00 2001 From: liach Date: Wed, 16 Apr 2025 18:58:46 -0500 Subject: [PATCH 1/3] 8354899: Reduce overhead associated with type switches --- .../java/lang/runtime/SwitchBootstraps.java | 31 +++++++++++++++++-- .../classfile/impl/BlockCodeBuilderImpl.java | 11 +++---- .../classfile/impl/ChainedClassBuilder.java | 8 ++--- .../classfile/impl/ChainedFieldBuilder.java | 8 ++--- .../classfile/impl/ChainedMethodBuilder.java | 8 ++--- .../jdk/internal/classfile/impl/CodeImpl.java | 12 ++++--- .../classfile/impl/DirectCodeBuilder.java | 13 ++++++-- .../impl/NonterminalCodeBuilder.java | 12 ++++--- 8 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index 2c31b1d060669..5334fb38a5643 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -27,6 +27,8 @@ import java.lang.Enum.EnumDesc; import java.lang.classfile.CodeBuilder; +import java.lang.classfile.attribute.StackMapFrameInfo; +import java.lang.classfile.attribute.StackMapTableAttribute; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDesc; import java.lang.constant.MethodTypeDesc; @@ -48,6 +50,7 @@ import java.lang.classfile.Label; import java.lang.classfile.instruction.SwitchCase; +import jdk.internal.classfile.impl.DirectCodeBuilder; import jdk.internal.constant.ClassOrInterfaceDescImpl; import jdk.internal.constant.ConstantUtils; import jdk.internal.constant.MethodTypeDescImpl; @@ -103,6 +106,13 @@ private SwitchBootstraps() {} private static final MethodType MT_TYPE_SWITCH = MethodType.methodType(int.class, Object.class, int.class); + private static final List TYPE_SWITCH_LOCALS = List.of( + StackMapFrameInfo.ObjectVerificationTypeInfo.of(CD_Object), StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER + ); + private static final List TYPE_SWITCH_EXTRA_LOCALS = List.of( + StackMapFrameInfo.ObjectVerificationTypeInfo.of(CD_Object), StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER, + StackMapFrameInfo.ObjectVerificationTypeInfo.of(CD_BiPredicate), StackMapFrameInfo.ObjectVerificationTypeInfo.of(CD_List) + ); private static class StaticHolders { private static final MethodHandle MAPPED_ENUM_SWITCH; @@ -482,25 +492,33 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto int ENUM_CACHE = 2; int EXTRA_CLASS_LABELS = 3; + var locals = enumDescs == null && extraClassLabels == null ? TYPE_SWITCH_LOCALS : TYPE_SWITCH_EXTRA_LOCALS; + int maxLocals = locals.size(); + return cb -> { // Objects.checkIndex(RESTART_IDX, labelConstants + 1) + var stackMapFrames = new ArrayList(labelConstants.length * 2); cb.iload(RESTART_IDX) .loadConstant(labelConstants.length + 1) .invokestatic(CD_Objects, "checkIndex", CHECK_INDEX_DESCRIPTOR) .pop() .aload(SELECTOR_OBJ); Label nonNullLabel = cb.newLabel(); + stackMapFrames.add(StackMapFrameInfo.of(nonNullLabel, locals, List.of())); cb.ifnonnull(nonNullLabel) .iconst_m1() .ireturn() .labelBinding(nonNullLabel); if (labelConstants.length == 0) { cb.loadConstant(0) - .ireturn(); + .ireturn() + .with(StackMapTableAttribute.of(stackMapFrames)); + DirectCodeBuilder.withMaxs(cb, 2, locals.size()); // checkIndex uses 2 return; } cb.iload(RESTART_IDX); Label dflt = cb.newLabel(); + stackMapFrames.add(StackMapFrameInfo.of(dflt, locals, List.of())); Label[] caseTargets = new Label[labelConstants.length]; Label[] caseNext = new Label[labelConstants.length]; Object[] caseLabels = new Object[labelConstants.length]; @@ -509,6 +527,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto for (int idx = labelConstants.length - 1; idx >= 0; idx--) { Object currentLabel = labelConstants[idx]; Label target = cb.newLabel(); + stackMapFrames.add(StackMapFrameInfo.of(target, locals, List.of())); Label next; if (lastLabel == null) { next = dflt; @@ -542,6 +561,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto // Integer i = ... or int i = ... // o instanceof float Label notNumber = cb.newLabel(); + stackMapFrames.add(StackMapFrameInfo.of(notNumber, locals, List.of())); cb.aload(SELECTOR_OBJ) .instanceOf(CD_Number); if (selectorType == long.class || selectorType == float.class || selectorType == double.class || @@ -566,6 +586,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto MethodTypeDesc.of(CD_double)); } else { Label compare = cb.newLabel(); + stackMapFrames.add(StackMapFrameInfo.of(compare, locals, List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER))); cb.invokevirtual(CD_Number, "intValue", MethodTypeDesc.of(CD_int)) @@ -639,6 +660,8 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto } else if (caseLabel instanceof Integer integerLabel) { Label compare = cb.newLabel(); Label notNumber = cb.newLabel(); + stackMapFrames.add(StackMapFrameInfo.of(notNumber, locals, List.of())); + stackMapFrames.add(StackMapFrameInfo.of(compare, locals, List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER))); cb.aload(SELECTOR_OBJ) .instanceOf(CD_Number) .ifeq(notNumber) @@ -690,7 +713,9 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto } cb.labelBinding(dflt) .loadConstant(labelConstants.length) - .ireturn(); + .ireturn() + .with(StackMapTableAttribute.of(stackMapFrames)); + DirectCodeBuilder.withMaxs(cb, 3, locals.size()); // enum labels use 3 stack, others use 2 }; } @@ -702,7 +727,7 @@ private static MethodHandle generateTypeSwitch(MethodHandles.Lookup caller, Clas List> enumDescs = addExtraInfo ? new ArrayList<>() : null; List> extraClassLabels = addExtraInfo ? new ArrayList<>() : null; - byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())), + byte[] classBytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())), clb -> { clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC) .withMethodBody("typeSwitch", diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java index 62d812ce8d41f..56682214566d4 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,11 +72,10 @@ public boolean isEmpty() { } private int topLocal(CodeBuilder parent) { - return switch (parent) { - case BlockCodeBuilderImpl b -> b.topLocal; - case ChainedCodeBuilder b -> b.terminal.curTopLocal(); - case TerminalCodeBuilder b -> b.curTopLocal(); - }; + if (parent instanceof BlockCodeBuilderImpl bcb) { + return bcb.topLocal; + } + return findTerminal(parent).curTopLocal(); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java index 48d5ceb72d641..b4c8ad5870535 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,10 +39,8 @@ public final class ChainedClassBuilder public ChainedClassBuilder(ClassBuilder downstream, Consumer consumer) { this.consumer = consumer; - this.terminal = switch (downstream) { - case ChainedClassBuilder cb -> cb.terminal; - case DirectClassBuilder db -> db; - }; + this.terminal = downstream instanceof ChainedClassBuilder ccb ? + ccb.terminal : (DirectClassBuilder) downstream; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java index 13ca52f18de2f..9eac25d567c8a 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,10 +38,8 @@ public final class ChainedFieldBuilder implements FieldBuilder { public ChainedFieldBuilder(FieldBuilder downstream, Consumer consumer) { this.consumer = consumer; - this.terminal = switch (downstream) { - case ChainedFieldBuilder cb -> cb.terminal; - case TerminalFieldBuilder tb -> tb; - }; + this.terminal = downstream instanceof ChainedFieldBuilder cfb ? + cfb.terminal : (TerminalFieldBuilder) downstream; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java index 7bd0fc2ca1b23..e96351b88567e 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,10 +41,8 @@ public final class ChainedMethodBuilder implements MethodBuilder { public ChainedMethodBuilder(MethodBuilder downstream, Consumer consumer) { this.consumer = consumer; - this.terminal = switch (downstream) { - case ChainedMethodBuilder cb -> cb.terminal; - case TerminalMethodBuilder tb -> tb; - }; + this.terminal = downstream instanceof ChainedMethodBuilder cmb ? + cmb.terminal : (TerminalMethodBuilder) downstream; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java index 286d29029ad24..c8c6d2546502b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java @@ -264,14 +264,16 @@ private void inflateJumpTargets() { //fallback to jump targets inflation without StackMapTableAttribute for (int pos=codeStart; pos br.target(); - case DiscontinuedInstruction.JsrInstruction jsr -> jsr.target(); - case LookupSwitchInstruction ls -> { + switch (i.opcode().kind()) { + case BRANCH -> ((BranchInstruction) i).target(); + case DISCONTINUED_JSR -> ((DiscontinuedInstruction.JsrInstruction) i).target(); + case LOOKUP_SWITCH -> { + var ls = (LookupSwitchInstruction) i; ls.defaultTarget(); ls.cases(); } - case TableSwitchInstruction ts -> { + case TABLE_SWITCH -> { + var ts = (TableSwitchInstruction) i; ts.defaultTarget(); ts.cases(); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java index 2741d1918caeb..bc563482f79d2 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java @@ -48,10 +48,8 @@ public final class DirectCodeBuilder extends AbstractDirectBuilder implements TerminalCodeBuilder { private static final CharacterRange[] EMPTY_CHARACTER_RANGE = {}; - private static final DeferredLabel[] EMPTY_LABEL_ARRAY = {}; private static final LocalVariable[] EMPTY_LOCAL_VARIABLE_ARRAY = {}; private static final LocalVariableType[] EMPTY_LOCAL_VARIABLE_TYPE_ARRAY = {}; - private static final AbstractPseudoInstruction.ExceptionCatchImpl[] EMPTY_HANDLER_ARRAY = {}; private static final DeferredLabel[] EMPTY_DEFERRED_LABEL_ARRAY = {}; final List handlers = new ArrayList<>(); @@ -74,6 +72,9 @@ public final class DirectCodeBuilder private DeferredLabel[] deferredLabels = EMPTY_DEFERRED_LABEL_ARRAY; private int deferredLabelsCount = 0; + private int maxStackHint = -1; + private int maxLocalsHint = -1; + /* Locals management lazily computed maxLocal = -1 first time: derive count from methodType descriptor (for new methods) & ACC_STATIC, @@ -173,6 +174,12 @@ public MethodInfo methodInfo() { return methodInfo; } + public static void withMaxs(CodeBuilder cob, int stacks, int locals) { + var dcb = (DirectCodeBuilder) cob; + dcb.maxStackHint = stacks; + dcb.maxLocalsHint = locals; + } + private UnboundAttribute content = null; private void writeExceptionHandlers(BufWriterImpl buf) { @@ -319,6 +326,8 @@ private void writeCounters(boolean codeMatch, BufWriterImpl buf) { if (codeMatch) { var originalAttribute = (CodeImpl) original; buf.writeU2U2(originalAttribute.maxStack(), originalAttribute.maxLocals()); + } else if (maxLocalsHint >= 0 && maxStackHint >= 0) { + buf.writeU2U2(maxStackHint, maxLocalsHint); } else { StackCounter cntr = StackCounter.of(DirectCodeBuilder.this, buf); buf.writeU2U2(cntr.maxStack(), cntr.maxLocals()); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java index f40da3a2beac6..d7eaffb325072 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,10 +35,12 @@ public abstract sealed class NonterminalCodeBuilder implements CodeBuilder public NonterminalCodeBuilder(CodeBuilder parent) { this.parent = parent; - this.terminal = switch (parent) { - case NonterminalCodeBuilder cb -> cb.terminal; - case TerminalCodeBuilder cb -> cb; - }; + this.terminal = findTerminal(parent); + } + + static TerminalCodeBuilder findTerminal(CodeBuilder cob) { + return cob instanceof NonterminalCodeBuilder ncb ? + ncb.terminal : (TerminalCodeBuilder) cob; } @Override From cbc3fd34705d6605e334353769206e9c43cb2b09 Mon Sep 17 00:00:00 2001 From: liach Date: Thu, 17 Apr 2025 12:14:43 -0500 Subject: [PATCH 2/3] Fix adding potentially unbound labels --- .../java/lang/runtime/SwitchBootstraps.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index 5334fb38a5643..f724d7355b005 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -493,7 +493,6 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto int EXTRA_CLASS_LABELS = 3; var locals = enumDescs == null && extraClassLabels == null ? TYPE_SWITCH_LOCALS : TYPE_SWITCH_EXTRA_LOCALS; - int maxLocals = locals.size(); return cb -> { // Objects.checkIndex(RESTART_IDX, labelConstants + 1) @@ -504,11 +503,11 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto .pop() .aload(SELECTOR_OBJ); Label nonNullLabel = cb.newLabel(); - stackMapFrames.add(StackMapFrameInfo.of(nonNullLabel, locals, List.of())); cb.ifnonnull(nonNullLabel) .iconst_m1() .ireturn() .labelBinding(nonNullLabel); + stackMapFrames.add(StackMapFrameInfo.of(nonNullLabel, locals, List.of())); if (labelConstants.length == 0) { cb.loadConstant(0) .ireturn() @@ -518,7 +517,6 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto } cb.iload(RESTART_IDX); Label dflt = cb.newLabel(); - stackMapFrames.add(StackMapFrameInfo.of(dflt, locals, List.of())); Label[] caseTargets = new Label[labelConstants.length]; Label[] caseNext = new Label[labelConstants.length]; Object[] caseLabels = new Object[labelConstants.length]; @@ -560,8 +558,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto } else if (!unconditionalExactnessCheck(Wrapper.asPrimitiveType(selectorType), classLabel)) { // Integer i = ... or int i = ... // o instanceof float - Label notNumber = cb.newLabel(); - stackMapFrames.add(StackMapFrameInfo.of(notNumber, locals, List.of())); + Label notNumber = cb.newLabel(); // this label may end up unbound cb.aload(SELECTOR_OBJ) .instanceOf(CD_Number); if (selectorType == long.class || selectorType == float.class || selectorType == double.class || @@ -586,13 +583,13 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto MethodTypeDesc.of(CD_double)); } else { Label compare = cb.newLabel(); - stackMapFrames.add(StackMapFrameInfo.of(compare, locals, List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER))); cb.invokevirtual(CD_Number, "intValue", MethodTypeDesc.of(CD_int)) .goto_(compare) - .labelBinding(notNumber) - .aload(SELECTOR_OBJ) + .labelBinding(notNumber); + stackMapFrames.add(StackMapFrameInfo.of(notNumber, locals, List.of())); + cb.aload(SELECTOR_OBJ) .instanceOf(CD_Character) .ifeq(next) .aload(SELECTOR_OBJ) @@ -601,6 +598,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto "charValue", MethodTypeDesc.of(CD_char)) .labelBinding(compare); + stackMapFrames.add(StackMapFrameInfo.of(compare, locals, List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER))); } TypePairs typePair = TypePairs.of(Wrapper.asPrimitiveType(selectorType), classLabel); @@ -660,8 +658,6 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto } else if (caseLabel instanceof Integer integerLabel) { Label compare = cb.newLabel(); Label notNumber = cb.newLabel(); - stackMapFrames.add(StackMapFrameInfo.of(notNumber, locals, List.of())); - stackMapFrames.add(StackMapFrameInfo.of(compare, locals, List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER))); cb.aload(SELECTOR_OBJ) .instanceOf(CD_Number) .ifeq(notNumber) @@ -671,8 +667,9 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto "intValue", MethodTypeDesc.of(CD_int)) .goto_(compare) - .labelBinding(notNumber) - .aload(SELECTOR_OBJ) + .labelBinding(notNumber); + stackMapFrames.add(StackMapFrameInfo.of(notNumber, locals, List.of())); + cb.aload(SELECTOR_OBJ) .instanceOf(CD_Character) .ifeq(next) .aload(SELECTOR_OBJ) @@ -680,9 +677,9 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto .invokevirtual(CD_Character, "charValue", MethodTypeDesc.of(CD_char)) - .labelBinding(compare) - - .loadConstant(integerLabel) + .labelBinding(compare); + stackMapFrames.add(StackMapFrameInfo.of(compare, locals, List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.INTEGER))); + cb.loadConstant(integerLabel) .if_icmpne(next); } else if ((caseLabel instanceof Long || caseLabel instanceof Float || @@ -711,6 +708,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto cb.loadConstant(idx) .ireturn(); } + stackMapFrames.add(StackMapFrameInfo.of(dflt, locals, List.of())); cb.labelBinding(dflt) .loadConstant(labelConstants.length) .ireturn() From 2c17dd1c7ce1a84d7c5ab682fc3cf4aedeeef9e7 Mon Sep 17 00:00:00 2001 From: liach Date: Tue, 22 Apr 2025 10:11:55 -0500 Subject: [PATCH 3/3] Rollback classfile boot speed changes --- .../classfile/impl/BlockCodeBuilderImpl.java | 11 ++++++----- .../internal/classfile/impl/ChainedClassBuilder.java | 8 +++++--- .../internal/classfile/impl/ChainedFieldBuilder.java | 8 +++++--- .../classfile/impl/ChainedMethodBuilder.java | 8 +++++--- .../jdk/internal/classfile/impl/CodeImpl.java | 12 +++++------- .../classfile/impl/NonterminalCodeBuilder.java | 12 +++++------- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java index 56682214566d4..62d812ce8d41f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BlockCodeBuilderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,10 +72,11 @@ public boolean isEmpty() { } private int topLocal(CodeBuilder parent) { - if (parent instanceof BlockCodeBuilderImpl bcb) { - return bcb.topLocal; - } - return findTerminal(parent).curTopLocal(); + return switch (parent) { + case BlockCodeBuilderImpl b -> b.topLocal; + case ChainedCodeBuilder b -> b.terminal.curTopLocal(); + case TerminalCodeBuilder b -> b.curTopLocal(); + }; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java index b4c8ad5870535..48d5ceb72d641 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,10 @@ public final class ChainedClassBuilder public ChainedClassBuilder(ClassBuilder downstream, Consumer consumer) { this.consumer = consumer; - this.terminal = downstream instanceof ChainedClassBuilder ccb ? - ccb.terminal : (DirectClassBuilder) downstream; + this.terminal = switch (downstream) { + case ChainedClassBuilder cb -> cb.terminal; + case DirectClassBuilder db -> db; + }; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java index 9eac25d567c8a..13ca52f18de2f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedFieldBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,10 @@ public final class ChainedFieldBuilder implements FieldBuilder { public ChainedFieldBuilder(FieldBuilder downstream, Consumer consumer) { this.consumer = consumer; - this.terminal = downstream instanceof ChainedFieldBuilder cfb ? - cfb.terminal : (TerminalFieldBuilder) downstream; + this.terminal = switch (downstream) { + case ChainedFieldBuilder cb -> cb.terminal; + case TerminalFieldBuilder tb -> tb; + }; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java index e96351b88567e..7bd0fc2ca1b23 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedMethodBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,10 @@ public final class ChainedMethodBuilder implements MethodBuilder { public ChainedMethodBuilder(MethodBuilder downstream, Consumer consumer) { this.consumer = consumer; - this.terminal = downstream instanceof ChainedMethodBuilder cmb ? - cmb.terminal : (TerminalMethodBuilder) downstream; + this.terminal = switch (downstream) { + case ChainedMethodBuilder cb -> cb.terminal; + case TerminalMethodBuilder tb -> tb; + }; } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java index c8c6d2546502b..286d29029ad24 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java @@ -264,16 +264,14 @@ private void inflateJumpTargets() { //fallback to jump targets inflation without StackMapTableAttribute for (int pos=codeStart; pos ((BranchInstruction) i).target(); - case DISCONTINUED_JSR -> ((DiscontinuedInstruction.JsrInstruction) i).target(); - case LOOKUP_SWITCH -> { - var ls = (LookupSwitchInstruction) i; + switch (i) { + case BranchInstruction br -> br.target(); + case DiscontinuedInstruction.JsrInstruction jsr -> jsr.target(); + case LookupSwitchInstruction ls -> { ls.defaultTarget(); ls.cases(); } - case TABLE_SWITCH -> { - var ts = (TableSwitchInstruction) i; + case TableSwitchInstruction ts -> { ts.defaultTarget(); ts.cases(); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java index d7eaffb325072..f40da3a2beac6 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/NonterminalCodeBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,12 +35,10 @@ public abstract sealed class NonterminalCodeBuilder implements CodeBuilder public NonterminalCodeBuilder(CodeBuilder parent) { this.parent = parent; - this.terminal = findTerminal(parent); - } - - static TerminalCodeBuilder findTerminal(CodeBuilder cob) { - return cob instanceof NonterminalCodeBuilder ncb ? - ncb.terminal : (TerminalCodeBuilder) cob; + this.terminal = switch (parent) { + case NonterminalCodeBuilder cb -> cb.terminal; + case TerminalCodeBuilder cb -> cb; + }; } @Override