@ -41,7 +41,7 @@ import org.springframework.util.ObjectUtils;
public abstract class Operator extends SpelNodeImpl {
public abstract class Operator extends SpelNodeImpl {
private final String operatorName ;
private final String operatorName ;
// The descriptors of the runtime operand values are used if the discovered declared
// The descriptors of the runtime operand values are used if the discovered declared
// descriptors are not providing enough information (for example a generic type
// descriptors are not providing enough information (for example a generic type
// whose accessors seem to only be returning 'Object' - the actual descriptors may
// whose accessors seem to only be returning 'Object' - the actual descriptors may
@ -104,8 +104,8 @@ public abstract class Operator extends SpelNodeImpl {
return ( dc . areNumbers & & dc . areCompatible ) ;
return ( dc . areNumbers & & dc . areCompatible ) ;
}
}
/ * *
/ * *
* Numeric comparison operators share very similar generated code , only differing in
* Numeric comparison operators share very similar generated code , only differing in
* two comparison instructions .
* two comparison instructions .
* /
* /
protected void generateComparisonCode ( MethodVisitor mv , CodeFlow cf , int compInstruction1 , int compInstruction2 ) {
protected void generateComparisonCode ( MethodVisitor mv , CodeFlow cf , int compInstruction1 , int compInstruction2 ) {
@ -113,20 +113,20 @@ public abstract class Operator extends SpelNodeImpl {
SpelNodeImpl right = getRightOperand ( ) ;
SpelNodeImpl right = getRightOperand ( ) ;
String leftDesc = left . exitTypeDescriptor ;
String leftDesc = left . exitTypeDescriptor ;
String rightDesc = right . exitTypeDescriptor ;
String rightDesc = right . exitTypeDescriptor ;
boolean unboxLeft = ! CodeFlow . isPrimitive ( leftDesc ) ;
boolean unboxLeft = ! CodeFlow . isPrimitive ( leftDesc ) ;
boolean unboxRight = ! CodeFlow . isPrimitive ( rightDesc ) ;
boolean unboxRight = ! CodeFlow . isPrimitive ( rightDesc ) ;
DescriptorComparison dc = DescriptorComparison . checkNumericCompatibility (
DescriptorComparison dc = DescriptorComparison . checkNumericCompatibility (
leftDesc , rightDesc , this . leftActualDescriptor , this . rightActualDescriptor ) ;
leftDesc , rightDesc , this . leftActualDescriptor , this . rightActualDescriptor ) ;
char targetType = dc . compatibleType ; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
char targetType = dc . compatibleType ; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
cf . enterCompilationScope ( ) ;
cf . enterCompilationScope ( ) ;
left . generateCode ( mv , cf ) ;
left . generateCode ( mv , cf ) ;
cf . exitCompilationScope ( ) ;
cf . exitCompilationScope ( ) ;
if ( unboxLeft ) {
if ( unboxLeft ) {
CodeFlow . insertUnboxInsns ( mv , targetType , leftDesc ) ;
CodeFlow . insertUnboxInsns ( mv , targetType , leftDesc ) ;
}
}
cf . enterCompilationScope ( ) ;
cf . enterCompilationScope ( ) ;
right . generateCode ( mv , cf ) ;
right . generateCode ( mv , cf ) ;
cf . exitCompilationScope ( ) ;
cf . exitCompilationScope ( ) ;
@ -142,11 +142,11 @@ public abstract class Operator extends SpelNodeImpl {
mv . visitJumpInsn ( compInstruction1 , elseTarget ) ;
mv . visitJumpInsn ( compInstruction1 , elseTarget ) ;
}
}
else if ( targetType = = 'F' ) {
else if ( targetType = = 'F' ) {
mv . visitInsn ( FCMPG ) ;
mv . visitInsn ( FCMPG ) ;
mv . visitJumpInsn ( compInstruction1 , elseTarget ) ;
mv . visitJumpInsn ( compInstruction1 , elseTarget ) ;
}
}
else if ( targetType = = 'J' ) {
else if ( targetType = = 'J' ) {
mv . visitInsn ( LCMP ) ;
mv . visitInsn ( LCMP ) ;
mv . visitJumpInsn ( compInstruction1 , elseTarget ) ;
mv . visitJumpInsn ( compInstruction1 , elseTarget ) ;
}
}
else if ( targetType = = 'I' ) {
else if ( targetType = = 'I' ) {
@ -231,13 +231,13 @@ public abstract class Operator extends SpelNodeImpl {
return false ;
return false ;
}
}
/ * *
/ * *
* A descriptor comparison encapsulates the result of comparing descriptor
* A descriptor comparison encapsulates the result of comparing descriptor
* for two operands and describes at what level they are compatible .
* for two operands and describes at what level they are compatible .
* /
* /
protected static class DescriptorComparison {
protected static final class DescriptorComparison {
static final DescriptorComparison NOT_NUMBERS = new DescriptorComparison ( false , false , ' ' ) ;
static final DescriptorComparison NOT_NUMBERS = new DescriptorComparison ( false , false , ' ' ) ;
@ -254,7 +254,7 @@ public abstract class Operator extends SpelNodeImpl {
this . areCompatible = areCompatible ;
this . areCompatible = areCompatible ;
this . compatibleType = compatibleType ;
this . compatibleType = compatibleType ;
}
}
/ * *
/ * *
* Return an object that indicates whether the input descriptors are compatible .
* Return an object that indicates whether the input descriptors are compatible .
* < p > A declared descriptor is what could statically be determined ( e . g . from looking
* < p > A declared descriptor is what could statically be determined ( e . g . from looking
@ -278,7 +278,7 @@ public abstract class Operator extends SpelNodeImpl {
boolean leftNumeric = CodeFlow . isPrimitiveOrUnboxableSupportedNumberOrBoolean ( ld ) ;
boolean leftNumeric = CodeFlow . isPrimitiveOrUnboxableSupportedNumberOrBoolean ( ld ) ;
boolean rightNumeric = CodeFlow . isPrimitiveOrUnboxableSupportedNumberOrBoolean ( rd ) ;
boolean rightNumeric = CodeFlow . isPrimitiveOrUnboxableSupportedNumberOrBoolean ( rd ) ;
// If the declared descriptors aren't providing the information, try the actual descriptors
// If the declared descriptors aren't providing the information, try the actual descriptors
if ( ! leftNumeric & & ! ObjectUtils . nullSafeEquals ( ld , leftActualDescriptor ) ) {
if ( ! leftNumeric & & ! ObjectUtils . nullSafeEquals ( ld , leftActualDescriptor ) ) {
ld = leftActualDescriptor ;
ld = leftActualDescriptor ;
@ -288,7 +288,7 @@ public abstract class Operator extends SpelNodeImpl {
rd = rightActualDescriptor ;
rd = rightActualDescriptor ;
rightNumeric = CodeFlow . isPrimitiveOrUnboxableSupportedNumberOrBoolean ( rd ) ;
rightNumeric = CodeFlow . isPrimitiveOrUnboxableSupportedNumberOrBoolean ( rd ) ;
}
}
if ( leftNumeric & & rightNumeric ) {
if ( leftNumeric & & rightNumeric ) {
if ( CodeFlow . areBoxingCompatible ( ld , rd ) ) {
if ( CodeFlow . areBoxingCompatible ( ld , rd ) ) {
return new DescriptorComparison ( true , true , CodeFlow . toPrimitiveTargetDesc ( ld ) ) ;
return new DescriptorComparison ( true , true , CodeFlow . toPrimitiveTargetDesc ( ld ) ) ;
@ -299,7 +299,7 @@ public abstract class Operator extends SpelNodeImpl {
}
}
else {
else {
return DescriptorComparison . NOT_NUMBERS ;
return DescriptorComparison . NOT_NUMBERS ;
}
}
}
}
}
}