11/*
2- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2525 */
2626package jdk .internal .classfile .impl ;
2727
28- import java .lang .constant .ClassDesc ;
29- import java .lang .constant .MethodTypeDesc ;
30- import java .nio .ByteBuffer ;
31- import java .util .BitSet ;
32- import java .util .LinkedHashMap ;
33- import java .util .List ;
34- import java .util .stream .Collectors ;
3528import java .lang .classfile .TypeKind ;
3629import java .lang .classfile .constantpool .ConstantDynamicEntry ;
3730import java .lang .classfile .constantpool .DynamicConstantPoolEntry ;
3831import java .lang .classfile .constantpool .MemberRefEntry ;
39- import static java .lang .classfile .ClassFile .*;
32+ import java .lang .constant .MethodTypeDesc ;
33+ import java .nio .ByteBuffer ;
34+ import java .util .ArrayDeque ;
35+ import java .util .BitSet ;
36+ import java .util .List ;
37+ import java .util .Queue ;
4038
39+ import static java .lang .classfile .ClassFile .*;
4140
4241public final class StackCounter {
4342
43+ private record Target (int bci , int stack ) {}
44+
4445 static StackCounter of (DirectCodeBuilder dcb , BufWriterImpl buf ) {
4546 return new StackCounter (
4647 dcb ,
47- buf .thisClass ().asSymbol (),
4848 dcb .methodInfo .methodName ().stringValue (),
4949 dcb .methodInfo .methodTypeSymbol (),
5050 (dcb .methodInfo .methodFlags () & ACC_STATIC ) != 0 ,
@@ -59,12 +59,12 @@ static StackCounter of(DirectCodeBuilder dcb, BufWriterImpl buf) {
5959 private final String methodName ;
6060 private final MethodTypeDesc methodDesc ;
6161 private final SplitConstantPool cp ;
62- private final LinkedHashMap < Integer , Integer > map ;
62+ private final Queue < Target > targets ;
6363 private final BitSet visited ;
6464
6565 private void jump (int targetBci ) {
6666 if (!visited .get (targetBci )) {
67- map . put ( targetBci , stack );
67+ targets . add ( new Target ( targetBci , stack ) );
6868 }
6969 }
7070
@@ -78,13 +78,11 @@ private void ensureLocalSlot(int index) {
7878 }
7979
8080 private boolean next () {
81- var it = map .entrySet ().iterator ();
82- while (it .hasNext ()) {
83- var en = it .next ();
84- it .remove ();
85- if (!visited .get (en .getKey ())) {
86- bcs .nextBci = en .getKey ();
87- stack = en .getValue ();
81+ Target en ;
82+ while ((en = targets .poll ()) != null ) {
83+ if (!visited .get (en .bci )) {
84+ bcs .nextBci = en .bci ;
85+ stack = en .stack ;
8886 return true ;
8987 }
9088 }
@@ -93,7 +91,6 @@ private boolean next() {
9391 }
9492
9593 public StackCounter (LabelContext labelContext ,
96- ClassDesc thisClass ,
9794 String methodName ,
9895 MethodTypeDesc methodDesc ,
9996 boolean isStatic ,
@@ -103,16 +100,14 @@ public StackCounter(LabelContext labelContext,
103100 this .methodName = methodName ;
104101 this .methodDesc = methodDesc ;
105102 this .cp = cp ;
106- map = new LinkedHashMap <>();
103+ targets = new ArrayDeque <>();
107104 maxStack = stack = rets = 0 ;
108- for (var h : handlers ) map . put ( labelContext .labelToBci (h .handler ), 1 );
105+ for (var h : handlers ) targets . add ( new Target ( labelContext .labelToBci (h .handler ), 1 ) );
109106 maxLocals = isStatic ? 0 : 1 ;
110- for (var cd : methodDesc .parameterList ()) {
111- maxLocals += Util .slotSize (cd );
112- }
107+ maxLocals += Util .parameterSlots (methodDesc );
113108 bcs = new RawBytecodeHelper (bytecode );
114109 visited = new BitSet (bcs .endBci );
115- map . put ( 0 , 0 );
110+ targets . add ( new Target ( 0 , 0 ) );
116111 while (next ()) {
117112 while (!bcs .isLastBytecode ()) {
118113 bcs .rawNext ();
@@ -307,14 +302,11 @@ public StackCounter(LabelContext labelContext,
307302 case INVOKEVIRTUAL , INVOKESPECIAL , INVOKESTATIC , INVOKEINTERFACE , INVOKEDYNAMIC -> {
308303 var cpe = cp .entryByIndex (bcs .getIndexU2 ());
309304 var nameAndType = opcode == INVOKEDYNAMIC ? ((DynamicConstantPoolEntry )cpe ).nameAndType () : ((MemberRefEntry )cpe ).nameAndType ();
310- var mDesc = MethodTypeDesc .ofDescriptor (nameAndType .type ().stringValue ());
311- for (var arg : mDesc .parameterList ()) {
312- addStackSlot (-TypeKind .from (arg ).slotSize ());
313- }
305+ var mtd = Util .methodTypeSymbol (nameAndType );
306+ addStackSlot (Util .slotSize (mtd .returnType ()) - Util .parameterSlots (mtd ));
314307 if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC ) {
315308 addStackSlot (-1 );
316309 }
317- addStackSlot (TypeKind .from (mDesc .returnType ()).slotSize ());
318310 }
319311 case MULTIANEWARRAY ->
320312 addStackSlot (1 - bcs .getU1 (bcs .bci + 3 ));
0 commit comments