@@ -79,11 +79,9 @@ abstract class AbstractBase<S extends ParameterDescription> extends FilterableLi
7979 * {@inheritDoc}
8080 */
8181 public boolean hasExplicitMetaData () {
82- // cache the size and make sure to avoid iterators here
83- // this pattern reduces the number of allocations and also the CPU usage
8482 int size = size ();
85- for (int i = 0 ; i < size ; i ++) {
86- ParameterDescription parameterDescription = get (i );
83+ for (int index = 0 ; index < size ; index ++) { // Avoid iterator on potential hot path.
84+ ParameterDescription parameterDescription = get (index );
8785 if (!parameterDescription .isNamed () || !parameterDescription .hasModifiers ()) {
8886 return false ;
8987 }
@@ -95,12 +93,10 @@ public boolean hasExplicitMetaData() {
9593 * {@inheritDoc}
9694 */
9795 public ByteCodeElement .Token .TokenList <ParameterDescription .Token > asTokenList (ElementMatcher <? super TypeDescription > matcher ) {
98- // cache the size and make sure to avoid iterators here
99- // this pattern reduces the number of allocations and also the CPU usage
10096 int size = size ();
10197 List <ParameterDescription .Token > tokens = new ArrayList <ParameterDescription .Token >(size );
102- for (int i = 0 ; i < size ; i ++) {
103- tokens .add (get (i ).asToken (matcher ));
98+ for (int index = 0 ; index < size ; index ++) { // Avoid iterator on potential hot path.
99+ tokens .add (get (index ).asToken (matcher ));
104100 }
105101 return new ByteCodeElement .Token .TokenList <ParameterDescription .Token >(tokens );
106102 }
@@ -109,12 +105,10 @@ public ByteCodeElement.Token.TokenList<ParameterDescription.Token> asTokenList(E
109105 * {@inheritDoc}
110106 */
111107 public TypeList .Generic asTypeList () {
112- // cache the size and make sure to avoid iterators here
113- // this pattern reduces the number of allocations and also the CPU usage
114108 int size = size ();
115109 List <TypeDescription .Generic > types = new ArrayList <TypeDescription .Generic >(size );
116- for (int i = 0 ; i < size ; i ++) {
117- types .add (get (i ).getType ());
110+ for (int index = 0 ; index < size ; index ++) { // Avoid iterator on potential hot path.
111+ types .add (get (index ).getType ());
118112 }
119113 return new TypeList .Generic .Explicit (types );
120114 }
@@ -123,12 +117,10 @@ public TypeList.Generic asTypeList() {
123117 * {@inheritDoc}
124118 */
125119 public ParameterList <ParameterDescription .InDefinedShape > asDefined () {
126- // cache the size and make sure to avoid iterators here
127- // this pattern reduces the number of allocations and also the CPU usage
128120 int size = size ();
129121 List <ParameterDescription .InDefinedShape > declaredForms = new ArrayList <ParameterDescription .InDefinedShape >(size );
130- for (int i = 0 ; i < size ; i ++) {
131- declaredForms .add (get (i ).asDefined ());
122+ for (int index = 0 ; index < size ; index ++) { // Avoid iterator on potential hot path.
123+ declaredForms .add (get (index ).asDefined ());
132124 }
133125 return new Explicit <ParameterDescription .InDefinedShape >(declaredForms );
134126 }
@@ -157,16 +149,16 @@ abstract class ForLoadedExecutable<T> extends AbstractBase<ParameterDescription.
157149 protected final T executable ;
158150
159151 /**
160- * The number of parameters of this executable.
161- * <p>
162- * It is important to cache it as calling getParameterCount() via the dispatcher has a high cost.
152+ * The parameter annotation source to query.
163153 */
164- protected final int size ;
154+ protected final ParameterDescription . ForLoadedParameter . ParameterAnnotationSource parameterAnnotationSource ;
165155
166156 /**
167- * The parameter annotation source to query.
157+ * The number of parameters of this executable, or -1, if the size was not yet computed. This avoids recomputation
158+ * what can lead to an unreasonable performance impact if placed on a hot execution path. This field is not
159+ * volatile as the result is stable and can be recomputed from different threads.
168160 */
169- protected final ParameterDescription . ForLoadedParameter . ParameterAnnotationSource parameterAnnotationSource ;
161+ private int size ;
170162
171163 /**
172164 * Creates a new description for a loaded executable.
@@ -176,8 +168,8 @@ abstract class ForLoadedExecutable<T> extends AbstractBase<ParameterDescription.
176168 */
177169 protected ForLoadedExecutable (T executable , ParameterDescription .ForLoadedParameter .ParameterAnnotationSource parameterAnnotationSource ) {
178170 this .executable = executable ;
179- this .size = EXECUTABLE .getParameterCount (executable );
180171 this .parameterAnnotationSource = parameterAnnotationSource ;
172+ size = -1 ;
181173 }
182174
183175 /**
@@ -244,6 +236,9 @@ public static ParameterList<ParameterDescription.InDefinedShape> of(Method metho
244236 * {@inheritDoc}
245237 */
246238 public int size () {
239+ if (size == -1 ) {
240+ size = EXECUTABLE .getParameterCount (executable );
241+ }
247242 return size ;
248243 }
249244
@@ -584,14 +579,16 @@ class TypeSubstituting extends AbstractBase<ParameterDescription.InGenericShape>
584579 private final List <? extends ParameterDescription > parameterDescriptions ;
585580
586581 /**
587- * The number of parameters .
582+ * The visitor to apply to the parameter types before returning them .
588583 */
589- private final int size ;
584+ private final TypeDescription . Generic . Visitor <? extends TypeDescription . Generic > visitor ;
590585
591586 /**
592- * The visitor to apply to the parameter types before returning them.
587+ * The number of parameters of this executable, or -1, if the size was not yet computed. This avoids recomputation
588+ * what can lead to an unreasonable performance impact if placed on a hot execution path. This field is not
589+ * volatile as the result is stable and can be recomputed from different threads.
593590 */
594- private final TypeDescription . Generic . Visitor <? extends TypeDescription . Generic > visitor ;
591+ private int size ;
595592
596593 /**
597594 * Creates a new type substituting parameter list.
@@ -605,8 +602,8 @@ public TypeSubstituting(MethodDescription.InGenericShape declaringMethod,
605602 TypeDescription .Generic .Visitor <? extends TypeDescription .Generic > visitor ) {
606603 this .declaringMethod = declaringMethod ;
607604 this .parameterDescriptions = parameterDescriptions ;
608- this .size = parameterDescriptions .size ();
609605 this .visitor = visitor ;
606+ size = -1 ;
610607 }
611608
612609 /**
@@ -620,6 +617,9 @@ public ParameterDescription.InGenericShape get(int index) {
620617 * {@inheritDoc}
621618 */
622619 public int size () {
620+ if (size == -1 ) {
621+ size = parameterDescriptions .size ();
622+ }
623623 return size ;
624624 }
625625 }
0 commit comments