Merge branch '5.1.x'
This commit is contained in:
@@ -140,68 +140,68 @@ public abstract class Operator extends SpelNodeImpl {
|
||||
// This code block checks whether the left or right operand is null and handles
|
||||
// those cases before letting the original code (that only handled actual numbers) run
|
||||
Label rightIsNonNull = new Label();
|
||||
mv.visitInsn(DUP); // stack: left/right/right
|
||||
mv.visitJumpInsn(IFNONNULL, rightIsNonNull); // stack: left/right
|
||||
mv.visitInsn(DUP); // stack: left/right/right
|
||||
mv.visitJumpInsn(IFNONNULL, rightIsNonNull); // stack: left/right
|
||||
// here: RIGHT==null LEFT==unknown
|
||||
mv.visitInsn(SWAP); // right/left
|
||||
mv.visitInsn(SWAP); // right/left
|
||||
Label leftNotNullRightIsNull = new Label();
|
||||
mv.visitJumpInsn(IFNONNULL, leftNotNullRightIsNull); // stack: right
|
||||
mv.visitJumpInsn(IFNONNULL, leftNotNullRightIsNull); // stack: right
|
||||
// here: RIGHT==null LEFT==null
|
||||
mv.visitInsn(POP); // stack: <nothing>
|
||||
mv.visitInsn(POP); // stack: <nothing>
|
||||
// load 0 or 1 depending on comparison instruction
|
||||
switch (compInstruction1) {
|
||||
case IFGE: // OpLT
|
||||
case IFLE: // OpGT
|
||||
mv.visitInsn(ICONST_0); // false - null is not < or > null
|
||||
mv.visitInsn(ICONST_0); // false - null is not < or > null
|
||||
break;
|
||||
case IFGT: // OpLE
|
||||
case IFLT: // OpGE
|
||||
mv.visitInsn(ICONST_1); // true - null is <= or >= null
|
||||
mv.visitInsn(ICONST_1); // true - null is <= or >= null
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported: "+compInstruction1);
|
||||
throw new IllegalStateException("Unsupported: " + compInstruction1);
|
||||
}
|
||||
mv.visitJumpInsn(GOTO, endOfIf);
|
||||
mv.visitLabel(leftNotNullRightIsNull); // stack: right
|
||||
mv.visitLabel(leftNotNullRightIsNull); // stack: right
|
||||
// RIGHT==null LEFT!=null
|
||||
mv.visitInsn(POP); // stack: <nothing>
|
||||
mv.visitInsn(POP); // stack: <nothing>
|
||||
// load 0 or 1 depending on comparison instruction
|
||||
switch (compInstruction1) {
|
||||
case IFGE: // OpLT
|
||||
case IFGT: // OpLE
|
||||
mv.visitInsn(ICONST_0); // false - something is not < or <= null
|
||||
mv.visitInsn(ICONST_0); // false - something is not < or <= null
|
||||
break;
|
||||
case IFLE: // OpGT
|
||||
case IFLT: // OpGE
|
||||
mv.visitInsn(ICONST_1); // true - something is > or >= null
|
||||
mv.visitInsn(ICONST_1); // true - something is > or >= null
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported: "+compInstruction1);
|
||||
throw new IllegalStateException("Unsupported: " + compInstruction1);
|
||||
}
|
||||
mv.visitJumpInsn(GOTO, endOfIf);
|
||||
|
||||
mv.visitLabel(rightIsNonNull); // stack: left/right
|
||||
mv.visitLabel(rightIsNonNull); // stack: left/right
|
||||
// here: RIGHT!=null LEFT==unknown
|
||||
mv.visitInsn(SWAP); // stack: right/left
|
||||
mv.visitInsn(DUP); // stack: right/left/left
|
||||
mv.visitInsn(SWAP); // stack: right/left
|
||||
mv.visitInsn(DUP); // stack: right/left/left
|
||||
Label neitherRightNorLeftAreNull = new Label();
|
||||
mv.visitJumpInsn(IFNONNULL, neitherRightNorLeftAreNull); // stack: right/left
|
||||
mv.visitJumpInsn(IFNONNULL, neitherRightNorLeftAreNull); // stack: right/left
|
||||
// here: RIGHT!=null LEFT==null
|
||||
mv.visitInsn(POP2); // stack: <nothing>
|
||||
mv.visitInsn(POP2); // stack: <nothing>
|
||||
switch (compInstruction1) {
|
||||
case IFGE: // OpLT
|
||||
case IFGT: // OpLE
|
||||
mv.visitInsn(ICONST_1); // true - null is < or <= something
|
||||
mv.visitInsn(ICONST_1); // true - null is < or <= something
|
||||
break;
|
||||
case IFLE: // OpGT
|
||||
case IFLT: // OpGE
|
||||
mv.visitInsn(ICONST_0); // false - null is not > or >= something
|
||||
mv.visitInsn(ICONST_0); // false - null is not > or >= something
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported: "+compInstruction1);
|
||||
throw new IllegalStateException("Unsupported: " + compInstruction1);
|
||||
}
|
||||
mv.visitJumpInsn(GOTO, endOfIf);
|
||||
mv.visitLabel(neitherRightNorLeftAreNull); // stack: right/left
|
||||
mv.visitLabel(neitherRightNorLeftAreNull); // stack: right/left
|
||||
// neither were null so unbox and proceed with numeric comparison
|
||||
if (unboxLeft) {
|
||||
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
|
||||
|
||||
@@ -4994,7 +4994,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
|
||||
private void verifyCompilationAndBehaviourWithNull(String expressionText, SpelExpressionParser parser, StandardEvaluationContext ctx) {
|
||||
Reg r = (Reg)ctx.getRootObject().getValue();
|
||||
r.setValue2(1); // having a value in value2 fields will enable compilation to succeed, then can switch it to null
|
||||
r.setValue2(1); // having a value in value2 fields will enable compilation to succeed, then can switch it to null
|
||||
SpelExpression fast = (SpelExpression) parser.parseExpression(expressionText);
|
||||
SpelExpression slow = (SpelExpression) parser.parseExpression(expressionText);
|
||||
fast.getValue(ctx);
|
||||
@@ -5124,7 +5124,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
|
||||
// helper methods
|
||||
// Helper methods
|
||||
|
||||
private SpelNodeImpl getAst() {
|
||||
SpelExpression spelExpression = (SpelExpression) expression;
|
||||
@@ -5196,69 +5196,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
|
||||
// nested types
|
||||
|
||||
public class Reg {
|
||||
private Integer _value,_value2;
|
||||
private Long _valueL,_valueL2;
|
||||
private Double _valueD,_valueD2;
|
||||
private Float _valueF,_valueF2;
|
||||
|
||||
|
||||
public Reg(int v) {
|
||||
this._value = v;
|
||||
this._valueL = new Long(v);
|
||||
this._valueD = new Double(v);
|
||||
this._valueF = new Float(v);
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public Long getValueL() {
|
||||
return _valueL;
|
||||
}
|
||||
|
||||
public Double getValueD() {
|
||||
return _valueD;
|
||||
}
|
||||
|
||||
public Float getValueF() {
|
||||
return _valueF;
|
||||
}
|
||||
|
||||
public Integer getValue2() {
|
||||
return _value2;
|
||||
}
|
||||
|
||||
public Long getValueL2() {
|
||||
return _valueL2;
|
||||
}
|
||||
|
||||
public Double getValueD2() {
|
||||
return _valueD2;
|
||||
}
|
||||
|
||||
public Float getValueF2() {
|
||||
return _valueF2;
|
||||
}
|
||||
|
||||
public void setValue(Integer value) {
|
||||
_value = value;
|
||||
_valueL = value==null?null:new Long(value);
|
||||
_valueD = value==null?null:new Double(value);
|
||||
_valueF = value==null?null:new Float(value);
|
||||
}
|
||||
|
||||
public void setValue2(Integer value) {
|
||||
_value2 = value;
|
||||
_valueL2 = value==null?null:new Long(value);
|
||||
_valueD2 = value==null?null:new Double(value);
|
||||
_valueF2 = value==null?null:new Float(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Nested types
|
||||
|
||||
public interface Message<T> {
|
||||
|
||||
@@ -6276,4 +6214,66 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
public Long someLong = 3L;
|
||||
}
|
||||
|
||||
|
||||
public class Reg {
|
||||
|
||||
private Integer _value,_value2;
|
||||
private Long _valueL,_valueL2;
|
||||
private Double _valueD,_valueD2;
|
||||
private Float _valueF,_valueF2;
|
||||
|
||||
public Reg(int v) {
|
||||
this._value = v;
|
||||
this._valueL = new Long(v);
|
||||
this._valueD = new Double(v);
|
||||
this._valueF = new Float(v);
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public Long getValueL() {
|
||||
return _valueL;
|
||||
}
|
||||
|
||||
public Double getValueD() {
|
||||
return _valueD;
|
||||
}
|
||||
|
||||
public Float getValueF() {
|
||||
return _valueF;
|
||||
}
|
||||
|
||||
public Integer getValue2() {
|
||||
return _value2;
|
||||
}
|
||||
|
||||
public Long getValueL2() {
|
||||
return _valueL2;
|
||||
}
|
||||
|
||||
public Double getValueD2() {
|
||||
return _valueD2;
|
||||
}
|
||||
|
||||
public Float getValueF2() {
|
||||
return _valueF2;
|
||||
}
|
||||
|
||||
public void setValue(Integer value) {
|
||||
_value = value;
|
||||
_valueL = value==null?null:new Long(value);
|
||||
_valueD = value==null?null:new Double(value);
|
||||
_valueF = value==null?null:new Float(value);
|
||||
}
|
||||
|
||||
public void setValue2(Integer value) {
|
||||
_value2 = value;
|
||||
_valueL2 = value==null?null:new Long(value);
|
||||
_valueD2 = value==null?null:new Double(value);
|
||||
_valueF2 = value==null?null:new Float(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user