Package org.springframework.expression.spel

# Class CodeFlow

java.lang.Object
org.springframework.expression.spel.CodeFlow

All Implemented Interfaces:
  `org.springframework.asm.Opcodes`

public class CodeFlow extends Object implements org.springframework.asm.Opcodes
Manages the class being generated by the compilation process.

Records intermediate compilation state as the bytecode is generated.

Also includes various bytecode generation helper functions.

Since:
  4.1
Author:
  Andy Clement, Juergen Hoeller, Sam Brannen

## Nested Class Summary

Nested Classes
Modifier and Type
Class
Description
`static interface`
`CodeFlow.ClinitAdder`
Interface used to generate `clinit` static initializer blocks.
`static interface`
`CodeFlow.FieldAdder`
Interface used to generate fields.

## Field Summary

### Fields inherited from interface org.springframework.asm.Opcodes

`AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_DEPRECATED, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_MANDATED, ACC_MODULE, ACC_NATIVE, ACC_OPEN, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_RECORD, ACC_STATIC, ACC_STATIC_PHASE, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_TRANSITIVE, ACC_VARARGS, ACC_VOLATILE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH, ASM10_EXPERIMENTAL, ASM4, ASM5, ASM6, ASM7, ASM8, ASM9, ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CASTORE, CHECKCAST, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DMUL, DNEG, DOUBLE, DREM, DRETURN, DSTORE, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F_APPEND, F_CHOP, F_FULL, F_NEW, F_SAME, F_SAME1, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAT, FMUL, FNEG, FREM, FRETURN, FSTORE, FSUB, GETFIELD, GETSTATIC, GOTO, H_GETFIELD, H_GETSTATIC, H_INVOKEINTERFACE, H_INVOKESPECIAL, H_INVOKESTATIC, H_INVOKEVIRTUAL, H_NEWINVOKESPECIAL, H_PUTFIELD, H_PUTSTATIC, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILOAD, IMUL, INEG, INSTANCEOF, INTEGER, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISUB, IUSHR, IXOR, JSR, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDIV, LLOAD, LMUL, LNEG, LONG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSUB, LUSHR, LXOR, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, NEW, NEWARRAY, NOP, NULL, POP, POP2, PUTFIELD, PUTSTATIC, RET, RETURN, SALOAD, SASTORE, SIPUSH, SOURCE_DEPRECATED, SOURCE_MASK, SWAP, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_SHORT, TABLESWITCH, TOP, UNINITIALIZED_THIS, V_PREVIEW, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, V1_8, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V9`

## Constructor Summary

Constructors
Constructor
Description
`CodeFlow(String className, org.springframework.asm.ClassWriter classWriter)`
Construct a new `CodeFlow` for the given class.

## Method Summary

Modifier and Type
Method
Description
`static boolean`
`areBoxingCompatible(String desc1, String desc2)`
Determine whether boxing/unboxing can get from one type to the other.
`static int`
`arrayCodeFor(String arrayType)`
Determine the appropriate T tag to use for the NEWARRAY bytecode.
`static String`
`createSignatureDescriptor(Constructor<?> ctor)`
Create the JVM signature descriptor for a constructor.
`static String`
`createSignatureDescriptor(Method method)`
Create the JVM signature descriptor for a method.
`void`
`enterCompilationScope()`
Enter a new compilation scope, usually due to nested expression evaluation.
`void`
`exitCompilationScope()`
Exit a compilation scope, usually after a nested expression has been evaluated.
`void`
`finish()`
Called after the main expression evaluation method has been generated, this method will call back any registered FieldAdders or ClinitAdders to add any extra information to the class representing the compiled expression.
`void`
`generateCodeForArgument(org.springframework.asm.MethodVisitor methodVisitor, SpelNode argument, Class<?> requiredType)`
Generate bytecode that loads the supplied argument onto the stack.
`void`
`generateCodeForArgument(org.springframework.asm.MethodVisitor methodVisitor, SpelNode argument, String requiredTypeDesc)`
Generate bytecode that loads the supplied argument onto the stack.
`String`
`getClassName()`
`static void`
`insertAnyNecessaryTypeConversionBytecodes(org.springframework.asm.MethodVisitor mv, char targetDescriptor, String stackDescriptor)`
Insert any necessary numeric conversion bytecodes based upon what is on the stack and the desired target type.
`static void`
`insertArrayStore(org.springframework.asm.MethodVisitor mv, String arrayComponentType)`
Produce appropriate bytecode to store a stack item in an array.
`static void`
`insertBoxIfNecessary(org.springframework.asm.MethodVisitor mv, char ch)`
Determine the appropriate boxing instruction for a specific type (if it needs boxing) and insert the instruction into the supplied visitor.
`static void`
`insertBoxIfNecessary(org.springframework.asm.MethodVisitor mv, String descriptor)`
Determine the appropriate boxing instruction for a specific type (if it needs boxing) and insert the instruction into the supplied visitor.
`static void`
`insertCheckCast(org.springframework.asm.MethodVisitor mv, String descriptor)`
Insert the appropriate CHECKCAST instruction for the supplied descriptor.
`static void`
`insertNewArrayCode(org.springframework.asm.MethodVisitor mv, int size, String arrayType)`
Produce the correct bytecode to build an array.
`static void`
`insertNumericUnboxOrPrimitiveTypeCoercion(org.springframework.asm.MethodVisitor mv, String stackDescriptor, char targetDescriptor)`
For use in mathematical operators, handles converting from a (possibly boxed) number on the stack to a primitive numeric type.
`static void`
`insertOptimalLoad(org.springframework.asm.MethodVisitor mv, int value)`
Create the optimal instruction for loading a number on the stack.
`static void`
`insertUnboxInsns(org.springframework.asm.MethodVisitor mv, char ch, String stackDescriptor)`
Insert any necessary cast and value call to convert from a boxed type to a primitive value.
`static void`
`insertUnboxNumberInsns(org.springframework.asm.MethodVisitor mv, char targetDescriptor, String stackDescriptor)`
For numbers, use the appropriate method on the number to convert it to the primitive type requested.
`static boolean`
`isBooleanCompatible(String descriptor)`
Determine whether the descriptor is for a boolean primitive or boolean reference type.
`static boolean`
`isIntegerForNumericOp(Number number)`
Determine whether the given number is to be considered as an integer for the purposes of a numeric operation at the bytecode level.
`static boolean`
`isPrimitive(String descriptor)`
Determine whether the descriptor is for a primitive type or `void`.
`static boolean`
`isPrimitiveArray(String descriptor)`
Determine whether the descriptor is for a primitive array (for example, "[[I").
`static boolean`
`isPrimitiveOrUnboxableSupportedNumber(String descriptor)`
Determine if the supplied descriptor is for a supported number.
`static boolean`
`isPrimitiveOrUnboxableSupportedNumberOrBoolean(String descriptor)`
Determine if the supplied descriptor is for a supported number type or boolean.
`static boolean`
`isReferenceTypeArray(String arrayType)`
Return if the supplied array type has a core component reference type.
`String`
`lastDescriptor()`
Return the descriptor for the item currently on top of the stack (in the current scope).
`void`
`loadEvaluationContext(org.springframework.asm.MethodVisitor mv)`
Push the bytecode to load the EvaluationContext (the second parameter passed to the compiled expression method).
`void`
`loadTarget(org.springframework.asm.MethodVisitor mv)`
Push the byte code to load the target (i.e.
`int`
`nextFieldId()`
`int`
`nextFreeVariableId()`
`void`
`pushDescriptor(String descriptor)`
Record the descriptor for the most recently evaluated expression element.
`void`
`registerNewClinit(CodeFlow.ClinitAdder clinitAdder)`
Register a ClinitAdder which will add code to the static initializer in the generated class to support the code produced by an AST node's primary generateCode() method.
`void`
`registerNewField(CodeFlow.FieldAdder fieldAdder)`
Register a FieldAdder which will add a new field to the generated class to support the code produced by an AST node's primary generateCode() method.
`static String`
`toBoxedDescriptor(String primitiveDescriptor)`
`static String`
`toDescriptor(Class<?> type)`
Deduce the descriptor for a type.
`static String`
`toDescriptorFromObject(Object value)`
Determine the descriptor for an object instance (or `null`).
`static String[]`
`toDescriptors(Class<?>[] types)`
Create an array of descriptors from an array of classes.
`static String`
`toJvmDescriptor(Class<?> clazz)`
Determine the JVM descriptor for a specified class.
`static String[]`
`toParamDescriptors(Constructor<?> ctor)`
Create an array of descriptors representing the parameter types for the supplied constructor.
`static String[]`
`toParamDescriptors(Method method)`
Create an array of descriptors representing the parameter types for the supplied method.
`static char`
`toPrimitiveTargetDesc(String descriptor)`
Convert a type descriptor to the single character primitive descriptor.
`void`
`unboxBooleanIfNecessary(org.springframework.asm.MethodVisitor mv)`
If the codeflow shows the last expression evaluated to java.lang.Boolean then insert the necessary instructions to unbox that to a boolean primitive.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Constructor Details

### CodeFlow

public CodeFlow(String className, org.springframework.asm.ClassWriter classWriter)
Construct a new `CodeFlow` for the given class.

Parameters:
  `className` - the name of the class
  `classWriter` - the corresponding ASM `ClassWriter`

## Method Details

### loadTarget

public void loadTarget(org.springframework.asm.MethodVisitor mv)
Push the byte code to load the target (i.e. what was passed as the first argument to CompiledExpression.getValue(target, context))

Parameters:
  `mv` - the method visitor into which the load instruction should be inserted

### loadEvaluationContext

public void loadEvaluationContext(org.springframework.asm.MethodVisitor mv)
Push the bytecode to load the EvaluationContext (the second parameter passed to the compiled expression method).

Parameters:
  `mv` - the method visitor into which the load instruction should be inserted
Since:
  4.3.4

### pushDescriptor

public void pushDescriptor(@Nullable String descriptor)
Record the descriptor for the most recently evaluated expression element.

Parameters:
  `descriptor` - type descriptor for most recently evaluated element

### enterCompilationScope

public void enterCompilationScope()
Enter a new compilation scope, usually due to nested expression evaluation. For example when the arguments for a method invocation expression are being evaluated, each argument will be evaluated in a new scope.

### exitCompilationScope

public void exitCompilationScope()
Exit a compilation scope, usually after a nested expression has been evaluated. For example after an argument for a method invocation has been evaluated this method returns us to the previous (outer) scope.

### lastDescriptor

@Nullable public String lastDescriptor()
Return the descriptor for the item currently on top of the stack (in the current scope).

### unboxBooleanIfNecessary

public void unboxBooleanIfNecessary(org.springframework.asm.MethodVisitor mv)
If the codeflow shows the last expression evaluated to java.lang.Boolean then insert the necessary instructions to unbox that to a boolean primitive.

Parameters:
  `mv` - the method visitor into which new instructions should be inserted

### finish

public void finish()
Called after the main expression evaluation method has been generated, this method will call back any registered FieldAdders or ClinitAdders to add any extra information to the class representing the compiled expression.

### registerNewField

public void registerNewField(CodeFlow.FieldAdder fieldAdder)
Register a FieldAdder which will add a new field to the generated class to support the code produced by an AST node's primary generateCode() method.

### registerNewClinit

public void registerNewClinit(CodeFlow.ClinitAdder clinitAdder)
Register a ClinitAdder which will add code to the static initializer in the generated class to support the code produced by an AST node's primary generateCode() method.

### nextFieldId

public int nextFieldId()

### nextFreeVariableId

public int nextFreeVariableId()

### getClassName

public String getClassName()

### generateCodeForArgument

public void generateCodeForArgument(org.springframework.asm.MethodVisitor methodVisitor, SpelNode argument, Class<?> requiredType)
Generate bytecode that loads the supplied argument onto the stack.

Delegates to `generateCodeForArgument(MethodVisitor, SpelNode, String)` with the descriptor for the supplied `requiredType`.

This method also performs any boxing, unboxing, or check-casting necessary to ensure that the type of the argument on the stack matches the supplied `requiredType`.

Use this method when a node in the AST will be used as an argument for a constructor or method invocation. For example, if you wish to invoke a method with an `indexNode` that must be of type `int` for the actual method invocation within bytecode, you would call `codeFlow.generateCodeForArgument(methodVisitor, indexNode, int.class)`.

Parameters:
  `methodVisitor` - the ASM `MethodVisitor` into which code should be generated
  `argument` - a `SpelNode` that represents an argument to a method or constructor
  `requiredType` - the required type for the argument when invoking the corresponding constructor or method
Since:
  6.2
See Also:
  - `generateCodeForArgument(MethodVisitor, SpelNode, String)`

### generateCodeForArgument

public void generateCodeForArgument(org.springframework.asm.MethodVisitor methodVisitor, SpelNode argument, String requiredTypeDesc)
Generate bytecode that loads the supplied argument onto the stack.

This method also performs any boxing, unboxing, or check-casting necessary to ensure that the type of the argument on the stack matches the supplied `requiredTypeDesc`.

Use this method when a node in the AST will be used as an argument for a constructor or method invocation. For example, if you wish to invoke a method with an `indexNode` that must be of type `int` for the actual method invocation within bytecode, you would call `codeFlow.generateCodeForArgument(methodVisitor, indexNode, "I")`.

Parameters:
  `methodVisitor` - the ASM `MethodVisitor` into which code should be generated
  `argument` - a `SpelNode` that represents an argument to a method or constructor
  `requiredTypeDesc` - a descriptor for the required type for the argument when invoking the corresponding constructor or method
Since:
  6.2
See Also:
  - `generateCodeForArgument(MethodVisitor, SpelNode, Class)`
  - `toDescriptor(Class)`

### insertUnboxInsns

public static void insertUnboxInsns(org.springframework.asm.MethodVisitor mv, char ch, @Nullable String stackDescriptor)
Insert any necessary cast and value call to convert from a boxed type to a primitive value.

Parameters:
  `mv` - the method visitor into which instructions should be inserted
  `ch` - the primitive type desired as output
  `stackDescriptor` - the descriptor of the type on top of the stack

### insertUnboxNumberInsns

public static void insertUnboxNumberInsns(org.springframework.asm.MethodVisitor mv, char targetDescriptor, @Nullable String stackDescriptor)
For numbers, use the appropriate method on the number to convert it to the primitive type requested.

Parameters:
  `mv` - the method visitor into which instructions should be inserted
  `targetDescriptor` - the primitive type desired as output
  `stackDescriptor` - the descriptor of the type on top of the stack

### insertAnyNecessaryTypeConversionBytecodes

public static void insertAnyNecessaryTypeConversionBytecodes(org.springframework.asm.MethodVisitor mv, char targetDescriptor, String stackDescriptor)
Insert any necessary numeric conversion bytecodes based upon what is on the stack and the desired target type.

Parameters:
  `mv` - the method visitor into which instructions should be placed
  `targetDescriptor` - the (primitive) descriptor of the target type
  `stackDescriptor` - the descriptor of the operand on top of the stack

### createSignatureDescriptor

public static String createSignatureDescriptor(Method method)
Create the JVM signature descriptor for a method. This consists of the descriptors for the method parameters surrounded with parentheses, followed by the descriptor for the return type. Note the descriptors here are JVM descriptors, unlike the other descriptor forms the compiler is using which do not include the trailing semicolon.

Parameters:
  `method` - the method
Returns:
  a String signature descriptor (for example, "(ILjava/lang/String;)V")

### createSignatureDescriptor

public static String createSignatureDescriptor(Constructor<?> ctor)
Create the JVM signature descriptor for a constructor. This consists of the descriptors for the constructor parameters surrounded with parentheses, followed by the descriptor for the return type, which is always "V". Note the descriptors here are JVM descriptors, unlike the other descriptor forms the compiler is using which do not include the trailing semicolon.

Parameters:
  `ctor` - the constructor
Returns:
  a String signature descriptor (for example, "(ILjava/lang/String;)V")

### toJvmDescriptor

public static String toJvmDescriptor(Class<?> clazz)
Determine the JVM descriptor for a specified class. Unlike the other descriptors used in the compilation process, this is the one the JVM wants, so this one includes any necessary trailing semicolon (for example, Ljava/lang/String; rather than Ljava/lang/String)

Parameters:
  `clazz` - a class
Returns:
  the JVM descriptor for the class

### toDescriptorFromObject

public static String toDescriptorFromObject(@Nullable Object value)
Determine the descriptor for an object instance (or `null`).

Parameters:
  `value` - an object (possibly `null`)
Returns:
  the type descriptor for the object (descriptor is "Ljava/lang/Object" for `null` value)

### isBooleanCompatible

@Contract("null -> false") public static boolean isBooleanCompatible(@Nullable String descriptor)
Determine whether the descriptor is for a boolean primitive or boolean reference type.

Parameters:
  `descriptor` - type descriptor
Returns:
  `true` if the descriptor is boolean compatible

### isPrimitive

@Contract("null -> false") public static boolean isPrimitive(@Nullable String descriptor)
Determine whether the descriptor is for a primitive type or `void`.

Parameters:
  `descriptor` - type descriptor
Returns:
  `true` if a primitive type or `void`

### isPrimitiveArray

@Contract("null -> false") public static boolean isPrimitiveArray(@Nullable String descriptor)
Determine whether the descriptor is for a primitive array (for example, "[[I").

Parameters:
  `descriptor` - the descriptor for a possible primitive array
Returns:
  `true` if the descriptor a primitive array

### areBoxingCompatible

public static boolean areBoxingCompatible(String desc1, String desc2)
Determine whether boxing/unboxing can get from one type to the other.

Assumes at least one of the types is in boxed form (i.e. single char descriptor).

Returns:
  `true` if it is possible to get (via boxing) from one descriptor to the other

### isPrimitiveOrUnboxableSupportedNumberOrBoolean

@Contract("null -> false") public static boolean isPrimitiveOrUnboxableSupportedNumberOrBoolean(@Nullable String descriptor)
Determine if the supplied descriptor is for a supported number type or boolean. The compilation process only (currently) supports certain number types. These are double, float, long and int.

Parameters:
  `descriptor` - the descriptor for a type
Returns:
  `true` if the descriptor is for a supported numeric type or boolean

### isPrimitiveOrUnboxableSupportedNumber

@Contract("null -> false") public static boolean isPrimitiveOrUnboxableSupportedNumber(@Nullable String descriptor)
Determine if the supplied descriptor is for a supported number. The compilation process only (currently) supports certain number types. These are double, float, long and int.

Parameters:
  `descriptor` - the descriptor for a type
Returns:
  `true` if the descriptor is for a supported numeric type

### isIntegerForNumericOp

public static boolean isIntegerForNumericOp(Number number)
Determine whether the given number is to be considered as an integer for the purposes of a numeric operation at the bytecode level.

Parameters:
  `number` - the number to check
Returns:
  `true` if it is an `Integer`, `Short`, or `Byte`

### toPrimitiveTargetDesc

public static char toPrimitiveTargetDesc(String descriptor)
Convert a type descriptor to the single character primitive descriptor.

Parameters:
  `descriptor` - a descriptor for a type that should have a primitive representation
Returns:
  the single character descriptor for a primitive input descriptor

### insertCheckCast

public static void insertCheckCast(org.springframework.asm.MethodVisitor mv, @Nullable String descriptor)
Insert the appropriate CHECKCAST instruction for the supplied descriptor.

Parameters:
  `mv` - the method visitor into which the instruction should be inserted
  `descriptor` - the descriptor of the type to cast to

### insertBoxIfNecessary

public static void insertBoxIfNecessary(org.springframework.asm.MethodVisitor mv, @Nullable String descriptor)
Determine the appropriate boxing instruction for a specific type (if it needs boxing) and insert the instruction into the supplied visitor.

Parameters:
  `mv` - the method visitor for the new instructions
  `descriptor` - the descriptor of a type that may or may not need boxing

### insertBoxIfNecessary

public static void insertBoxIfNecessary(org.springframework.asm.MethodVisitor mv, char ch)
Determine the appropriate boxing instruction for a specific type (if it needs boxing) and insert the instruction into the supplied visitor.

Parameters:
  `mv` - the method visitor for the new instructions
  `ch` - the descriptor of the type that might need boxing

### toDescriptor

public static String toDescriptor(Class<?> type)
Deduce the descriptor for a type. Descriptors are like JVM type names but missing the trailing ';' so for Object the descriptor is "Ljava/lang/Object" for int it is "I".

Parameters:
  `type` - the type (may be primitive) for which to determine the descriptor
Returns:
  the descriptor

### toParamDescriptors

public static String[] toParamDescriptors(Method method)
Create an array of descriptors representing the parameter types for the supplied method. Returns a zero sized array if there are no parameters.

Parameters:
  `method` - a Method
Returns:
  a String array of descriptors, one entry for each method parameter

### toParamDescriptors

public static String[] toParamDescriptors(Constructor<?> ctor)
Create an array of descriptors representing the parameter types for the supplied constructor. Returns a zero sized array if there are no parameters.

Parameters:
  `ctor` - a Constructor
Returns:
  a String array of descriptors, one entry for each constructor parameter

### toDescriptors

public static String[] toDescriptors(Class<?>[] types)
Create an array of descriptors from an array of classes.

Parameters:
  `types` - the input array of classes
Returns:
  an array of descriptors

### insertOptimalLoad

public static void insertOptimalLoad(org.springframework.asm.MethodVisitor mv, int value)
Create the optimal instruction for loading a number on the stack.

Parameters:
  `mv` - where to insert the bytecode
  `value` - the value to be loaded

### insertArrayStore

public static void insertArrayStore(org.springframework.asm.MethodVisitor mv, String arrayComponentType)
Produce appropriate bytecode to store a stack item in an array.

The instruction to use varies depending on whether the type is a primitive or reference type.

Parameters:
  `mv` - where to insert the bytecode
  `arrayComponentType` - the component type of the array

### arrayCodeFor

public static int arrayCodeFor(String arrayType)
Determine the appropriate T tag to use for the NEWARRAY bytecode.

Parameters:
  `arrayType` - the array primitive component type
Returns:
  the T tag to use for NEWARRAY

### isReferenceTypeArray

public static boolean isReferenceTypeArray(String arrayType)
Return if the supplied array type has a core component reference type.

### insertNewArrayCode

public static void insertNewArrayCode(org.springframework.asm.MethodVisitor mv, int size, String arrayType)
Produce the correct bytecode to build an array. The opcode to use and the signature to pass along with the opcode can vary depending on the signature of the array type.

Parameters:
  `mv` - the method visitor into which code should be inserted
  `size` - the size of the array
  `arrayType` - the type of the array

### insertNumericUnboxOrPrimitiveTypeCoercion

public static void insertNumericUnboxOrPrimitiveTypeCoercion(org.springframework.asm.MethodVisitor mv, @Nullable String stackDescriptor, char targetDescriptor)
For use in mathematical operators, handles converting from a (possibly boxed) number on the stack to a primitive numeric type.

For example, from an Integer to a double, just need to call 'Number.doubleValue()' but from an int to a double, need to use the bytecode 'i2d'.

Parameters:
  `mv` - the method visitor when instructions should be appended
  `stackDescriptor` - a descriptor of the operand on the stack
  `targetDescriptor` - a primitive type descriptor

### toBoxedDescriptor

public static String toBoxedDescriptor(String primitiveDescriptor)