@@ -211,18 +211,22 @@ protected ValueRef getValueRef(ExpressionState state) throws EvaluationException
211
211
212
212
213
213
/**
214
- * Generate code that handles building the argument values for the specified method.
215
- * <p>This method will take into account whether the invoked method is a varargs method,
216
- * and if it is then the argument values will be appropriately packaged into an array.
214
+ * Generate code that handles building the argument values for the specified
215
+ * {@link Member} (method or constructor).
216
+ * <p>This method takes into account whether the method or constructor was
217
+ * declared to accept varargs, and if it was then the argument values will be
218
+ * appropriately packaged into an array.
217
219
* @param mv the method visitor where code should be generated
218
- * @param cf the current codeflow
220
+ * @param cf the current {@link CodeFlow}
219
221
* @param member the method or constructor for which arguments are being set up
220
222
* @param arguments the expression nodes for the expression supplied argument values
221
223
* @deprecated As of Spring Framework 6.2, in favor of
222
224
* {@link #generateCodeForArguments(MethodVisitor, CodeFlow, Executable, SpelNodeImpl[])}
223
225
*/
224
226
@ Deprecated (since = "6.2" )
225
- protected static void generateCodeForArguments (MethodVisitor mv , CodeFlow cf , Member member , SpelNodeImpl [] arguments ) {
227
+ protected static void generateCodeForArguments (
228
+ MethodVisitor mv , CodeFlow cf , Member member , SpelNodeImpl [] arguments ) {
229
+
226
230
if (member instanceof Executable executable ) {
227
231
generateCodeForArguments (mv , cf , executable , arguments );
228
232
}
@@ -233,7 +237,7 @@ protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Me
233
237
/**
234
238
* Generate code that handles building the argument values for the specified
235
239
* {@link Executable} (method or constructor).
236
- * <p>This method takes into account whether the invoked executable was
240
+ * <p>This method takes into account whether the method or constructor was
237
241
* declared to accept varargs, and if it was then the argument values will be
238
242
* appropriately packaged into an array.
239
243
* @param mv the method visitor where code should be generated
@@ -244,52 +248,56 @@ protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Me
244
248
* values
245
249
* @since 6.2
246
250
*/
247
- protected static void generateCodeForArguments (MethodVisitor mv , CodeFlow cf , Executable executable , SpelNodeImpl [] arguments ) {
251
+ protected static void generateCodeForArguments (
252
+ MethodVisitor mv , CodeFlow cf , Executable executable , SpelNodeImpl [] arguments ) {
253
+
248
254
Class <?>[] parameterTypes = executable .getParameterTypes ();
249
- String [] paramDescriptors = CodeFlow .toDescriptors (parameterTypes );
255
+ String [] parameterDescriptors = CodeFlow .toDescriptors (parameterTypes );
256
+ int parameterCount = parameterTypes .length ;
250
257
251
258
if (executable .isVarArgs ()) {
252
259
// The final parameter may or may not need packaging into an array, or nothing may
253
- // have been passed to satisfy the varargs and so something needs to be built.
254
- int p = 0 ; // Current supplied argument being processed
255
- int childCount = arguments .length ;
260
+ // have been passed to satisfy the varargs which means something needs to be built.
261
+
262
+ int varargsIndex = parameterCount - 1 ;
263
+ int argumentCount = arguments .length ;
264
+ int p = 0 ; // Current supplied argument being processed
256
265
257
- // Fulfill all the parameter requirements except the last one
258
- for (p = 0 ; p < paramDescriptors . length - 1 ; p ++) {
259
- cf .generateCodeForArgument (mv , arguments [p ], paramDescriptors [p ]);
266
+ // Fulfill all the parameter requirements except the last one (the varargs array).
267
+ for (p = 0 ; p < varargsIndex ; p ++) {
268
+ cf .generateCodeForArgument (mv , arguments [p ], parameterDescriptors [p ]);
260
269
}
261
270
262
- SpelNodeImpl lastChild = (childCount == 0 ? null : arguments [childCount - 1 ]);
271
+ SpelNodeImpl lastArgument = (argumentCount != 0 ? arguments [argumentCount - 1 ] : null );
263
272
ClassLoader classLoader = executable .getDeclaringClass ().getClassLoader ();
264
- Class <?> lastChildType = (lastChild != null ?
265
- loadClassForExitDescriptor (lastChild .getExitDescriptor (), classLoader ) : null );
266
- Class <?> lastParameterType = parameterTypes [parameterTypes . length - 1 ];
273
+ Class <?> lastArgumentType = (lastArgument != null ?
274
+ loadClassForExitDescriptor (lastArgument .getExitDescriptor (), classLoader ) : null );
275
+ Class <?> lastParameterType = parameterTypes [varargsIndex ];
267
276
268
277
// Determine if the final passed argument is already suitably packaged in array
269
- // form to be passed to the method
270
- if (lastChild != null && lastChildType != null && lastParameterType .isAssignableFrom (lastChildType )) {
271
- cf .generateCodeForArgument (mv , lastChild , paramDescriptors [p ]);
278
+ // form to be passed to the method.
279
+ if (lastArgument != null && lastArgumentType != null && lastParameterType .isAssignableFrom (lastArgumentType )) {
280
+ cf .generateCodeForArgument (mv , lastArgument , parameterDescriptors [p ]);
272
281
}
273
282
else {
274
- String arrayType = paramDescriptors [ paramDescriptors . length - 1 ];
275
- arrayType = arrayType . substring ( 1 ); // trim the leading '[', may leave other '['
276
- // build array big enough to hold remaining arguments
277
- CodeFlow . insertNewArrayCode ( mv , childCount - p , arrayType );
278
- // Package up the remaining arguments into the array
279
- int arrayindex = 0 ;
280
- while ( p < childCount ) {
281
- SpelNodeImpl child = arguments [ p ];
283
+ String arrayComponentType = parameterDescriptors [ varargsIndex ];
284
+ // Trim the leading '[', potentially leaving other '[' characters.
285
+ arrayComponentType = arrayComponentType . substring ( 1 );
286
+ // Build array big enough to hold remaining arguments.
287
+ CodeFlow . insertNewArrayCode ( mv , argumentCount - p , arrayComponentType );
288
+ // Package up the remaining arguments into the array.
289
+ int arrayIndex = 0 ;
290
+ while ( p < argumentCount ) {
282
291
mv .visitInsn (DUP );
283
- CodeFlow .insertOptimalLoad (mv , arrayindex ++);
284
- cf .generateCodeForArgument (mv , child , arrayType );
285
- CodeFlow .insertArrayStore (mv , arrayType );
286
- p ++;
292
+ CodeFlow .insertOptimalLoad (mv , arrayIndex ++);
293
+ cf .generateCodeForArgument (mv , arguments [p ++], arrayComponentType );
294
+ CodeFlow .insertArrayStore (mv , arrayComponentType );
287
295
}
288
296
}
289
297
}
290
298
else {
291
- for (int i = 0 ; i < paramDescriptors . length ; i ++) {
292
- cf .generateCodeForArgument (mv , arguments [i ], paramDescriptors [i ]);
299
+ for (int i = 0 ; i < parameterCount ; i ++) {
300
+ cf .generateCodeForArgument (mv , arguments [i ], parameterDescriptors [i ]);
293
301
}
294
302
}
295
303
}
@@ -308,8 +316,10 @@ private static Class<?> loadClassForExitDescriptor(@Nullable String exitDescript
308
316
}
309
317
310
318
/**
311
- * Ask an argument to generate its bytecode and then follow it up
312
- * with any boxing/unboxing/checkcasting to ensure it matches the expected parameter descriptor.
319
+ * Generate bytecode that loads the supplied argument onto the stack.
320
+ * <p>This method also performs any boxing, unboxing, or check-casting
321
+ * necessary to ensure that the type of the argument on the stack matches the
322
+ * supplied {@code paramDesc}.
313
323
* @deprecated As of Spring Framework 6.2, in favor of
314
324
* {@link CodeFlow#generateCodeForArgument(MethodVisitor, SpelNode, String)}
315
325
*/
0 commit comments