From 45fc4495503dc62ee96eeed2cda0f27aaeafaff5 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 31 Oct 2016 19:24:45 +0100 Subject: [PATCH] Polishing --- .../expression/spel/ast/OpEQ.java | 30 ++++++------ .../expression/spel/ast/OpNE.java | 17 +++---- .../expression/spel/ast/Operator.java | 48 ++++++++++--------- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpEQ.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpEQ.java index 73ad67603e9..f40bbf30148 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpEQ.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpEQ.java @@ -58,8 +58,8 @@ public class OpEQ extends Operator { String leftDesc = left.exitTypeDescriptor; String rightDesc = right.exitTypeDescriptor; - DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, - this.leftActualDescriptor, this.rightActualDescriptor); + DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility( + leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor); return (!dc.areNumbers || dc.areCompatible); } @@ -73,17 +73,15 @@ public class OpEQ extends Operator { boolean leftPrim = CodeFlow.isPrimitive(leftDesc); boolean rightPrim = CodeFlow.isPrimitive(rightDesc); - DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, - this.leftActualDescriptor, this.rightActualDescriptor); + DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility( + leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor); if (dc.areNumbers && dc.areCompatible) { char targetType = dc.compatibleType; - getLeftOperand().generateCode(mv, cf); if (!leftPrim) { CodeFlow.insertUnboxInsns(mv, targetType, leftDesc); } - cf.enterCompilationScope(); getRightOperand().generateCode(mv, cf); cf.exitCompilationScope(); @@ -91,23 +89,23 @@ public class OpEQ extends Operator { CodeFlow.insertUnboxInsns(mv, targetType, rightDesc); } // assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc) - if (targetType=='D') { + if (targetType == 'D') { mv.visitInsn(DCMPL); mv.visitJumpInsn(IFNE, elseTarget); } - else if (targetType=='F') { + else if (targetType == 'F') { mv.visitInsn(FCMPL); mv.visitJumpInsn(IFNE, elseTarget); } - else if (targetType=='J') { + else if (targetType == 'J') { mv.visitInsn(LCMP); mv.visitJumpInsn(IFNE, elseTarget); } - else if (targetType=='I' || targetType=='Z') { + else if (targetType == 'I' || targetType == 'Z') { mv.visitJumpInsn(IF_ICMPNE, elseTarget); } else { - throw new IllegalStateException("Unexpected descriptor "+leftDesc); + throw new IllegalStateException("Unexpected descriptor " + leftDesc); } } else { @@ -120,11 +118,11 @@ public class OpEQ extends Operator { CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0)); } Label leftNotNull = new Label(); - mv.visitInsn(DUP_X1); // Dup right on the top of the stack - mv.visitJumpInsn(IFNONNULL,leftNotNull); + mv.visitInsn(DUP_X1); // dup right on the top of the stack + mv.visitJumpInsn(IFNONNULL, leftNotNull); // Right is null! mv.visitInsn(SWAP); - mv.visitInsn(POP); // remove it + mv.visitInsn(POP); // remove it Label rightNotNull = new Label(); mv.visitJumpInsn(IFNONNULL, rightNotNull); // Left is null too @@ -132,7 +130,7 @@ public class OpEQ extends Operator { mv.visitJumpInsn(GOTO, endOfIf); mv.visitLabel(rightNotNull); mv.visitInsn(ICONST_0); - mv.visitJumpInsn(GOTO,endOfIf); + mv.visitJumpInsn(GOTO, endOfIf); mv.visitLabel(leftNotNull); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); mv.visitLabel(endOfIf); @@ -140,7 +138,7 @@ public class OpEQ extends Operator { return; } mv.visitInsn(ICONST_1); - mv.visitJumpInsn(GOTO,endOfIf); + mv.visitJumpInsn(GOTO, endOfIf); mv.visitLabel(elseTarget); mv.visitInsn(ICONST_0); mv.visitLabel(endOfIf); diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpNE.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpNE.java index 543e459ebeb..4f96b3bbddf 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpNE.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpNE.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,12 +36,13 @@ public class OpNE extends Operator { this.exitTypeDescriptor = "Z"; } + @Override public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException { Object left = getLeftOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue(); - leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); - rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); + this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); + this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); return BooleanTypedValue.forValue(!equalityCheck(state, left, right)); } @@ -57,7 +58,8 @@ public class OpNE extends Operator { String leftDesc = left.exitTypeDescriptor; String rightDesc = right.exitTypeDescriptor; - DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, leftActualDescriptor, rightActualDescriptor); + DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility( + leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor); return (!dc.areNumbers || dc.areCompatible); } @@ -70,16 +72,15 @@ public class OpNE extends Operator { boolean leftPrim = CodeFlow.isPrimitive(leftDesc); boolean rightPrim = CodeFlow.isPrimitive(rightDesc); - DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, leftActualDescriptor, rightActualDescriptor); + DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility( + leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor); if (dc.areNumbers && dc.areCompatible) { char targetType = dc.compatibleType; - getLeftOperand().generateCode(mv, cf); if (!leftPrim) { CodeFlow.insertUnboxInsns(mv, targetType, leftDesc); } - cf.enterCompilationScope(); getRightOperand().generateCode(mv, cf); cf.exitCompilationScope(); @@ -103,7 +104,7 @@ public class OpNE extends Operator { mv.visitJumpInsn(IF_ICMPEQ, elseTarget); } else { - throw new IllegalStateException("Unexpected descriptor "+leftDesc); + throw new IllegalStateException("Unexpected descriptor " + leftDesc); } } else { diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Operator.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Operator.java index 7172dd966bf..73ed4a75c7b 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Operator.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Operator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,6 +84,7 @@ public abstract class Operator extends SpelNodeImpl { return sb.toString(); } + protected boolean isCompilableOperatorUsingNumerics() { SpelNodeImpl left = getLeftOperand(); SpelNodeImpl right= getRightOperand(); @@ -94,8 +95,8 @@ public abstract class Operator extends SpelNodeImpl { // Supported operand types for equals (at the moment) String leftDesc = left.exitTypeDescriptor; String rightDesc = right.exitTypeDescriptor; - DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, - this.leftActualDescriptor, this.rightActualDescriptor); + DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility( + leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor); return (dc.areNumbers && dc.areCompatible); } @@ -109,9 +110,9 @@ public abstract class Operator extends SpelNodeImpl { boolean unboxLeft = !CodeFlow.isPrimitive(leftDesc); boolean unboxRight = !CodeFlow.isPrimitive(rightDesc); - DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, - this.leftActualDescriptor, this.rightActualDescriptor); - char targetType = dc.compatibleType;//CodeFlow.toPrimitiveTargetDesc(leftDesc); + DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility( + leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor); + char targetType = dc.compatibleType; // CodeFlow.toPrimitiveTargetDesc(leftDesc); getLeftOperand().generateCode(mv, cf); if (unboxLeft) { @@ -128,23 +129,23 @@ public abstract class Operator extends SpelNodeImpl { // assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc) Label elseTarget = new Label(); Label endOfIf = new Label(); - if (targetType=='D') { + if (targetType == 'D') { mv.visitInsn(DCMPG); mv.visitJumpInsn(compInstruction1, elseTarget); } - else if (targetType=='F') { + else if (targetType == 'F') { mv.visitInsn(FCMPG); mv.visitJumpInsn(compInstruction1, elseTarget); } - else if (targetType=='J') { + else if (targetType == 'J') { mv.visitInsn(LCMP); mv.visitJumpInsn(compInstruction1, elseTarget); } - else if (targetType=='I') { + else if (targetType == 'I') { mv.visitJumpInsn(compInstruction2, elseTarget); } else { - throw new IllegalStateException("Unexpected descriptor "+leftDesc); + throw new IllegalStateException("Unexpected descriptor " + leftDesc); } // Other numbers are not yet supported (isCompilable will not have returned true) @@ -215,8 +216,8 @@ public abstract class Operator extends SpelNodeImpl { /** - * A descriptor comparison encapsulates the result of comparing descriptor for two operands and - * describes at what level they are compatible. + * A descriptor comparison encapsulates the result of comparing descriptor + * for two operands and describes at what level they are compatible. */ protected static class DescriptorComparison { @@ -224,12 +225,12 @@ public abstract class Operator extends SpelNodeImpl { static DescriptorComparison INCOMPATIBLE_NUMBERS = new DescriptorComparison(true, false, ' '); - final boolean areNumbers; // Were the two compared descriptor both for numbers? + final boolean areNumbers; // Were the two compared descriptor both for numbers? - final boolean areCompatible; // If they were numbers, were they compatible? + final boolean areCompatible; // If they were numbers, were they compatible? + + final char compatibleType; // When compatible, what is the descriptor of the common type - final char compatibleType; // When compatible, what is the descriptor of the common type - private DescriptorComparison(boolean areNumbers, boolean areCompatible, char compatibleType) { this.areNumbers = areNumbers; this.areCompatible = areCompatible; @@ -237,12 +238,13 @@ public abstract class Operator extends SpelNodeImpl { } /** - * Returns an object that indicates whether the input descriptors are compatible. A declared descriptor - * is what could statically be determined (e.g. from looking at the return value of a property accessor - * method) whilst an actual descriptor is the type of an actual object that was returned, which may differ. - * For generic types with unbound type variables the declared descriptor discovered may be 'Object' but - * from the actual descriptor it is possible to observe that the objects are really numeric values (e.g. - * ints). + * Return an object that indicates whether the input descriptors are compatible. + *

A declared descriptor is what could statically be determined (e.g. from looking + * at the return value of a property accessor method) whilst an actual descriptor + * is the type of an actual object that was returned, which may differ. + *

For generic types with unbound type variables, the declared descriptor + * discovered may be 'Object' but from the actual descriptor it is possible to + * observe that the objects are really numeric values (e.g. ints). * @param leftDeclaredDescriptor the statically determinable left descriptor * @param rightDeclaredDescriptor the statically determinable right descriptor * @param leftActualDescriptor the dynamic/runtime left object descriptor