Polishing

This commit is contained in:
Juergen Hoeller 2016-10-31 19:24:45 +01:00
parent eaf80781e8
commit 45fc449550
3 changed files with 48 additions and 47 deletions

View File

@ -58,8 +58,8 @@ public class OpEQ extends Operator {
String leftDesc = left.exitTypeDescriptor; String leftDesc = left.exitTypeDescriptor;
String rightDesc = right.exitTypeDescriptor; String rightDesc = right.exitTypeDescriptor;
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
this.leftActualDescriptor, this.rightActualDescriptor); leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
return (!dc.areNumbers || dc.areCompatible); return (!dc.areNumbers || dc.areCompatible);
} }
@ -73,17 +73,15 @@ public class OpEQ extends Operator {
boolean leftPrim = CodeFlow.isPrimitive(leftDesc); boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
boolean rightPrim = CodeFlow.isPrimitive(rightDesc); boolean rightPrim = CodeFlow.isPrimitive(rightDesc);
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
this.leftActualDescriptor, this.rightActualDescriptor); leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
if (dc.areNumbers && dc.areCompatible) { if (dc.areNumbers && dc.areCompatible) {
char targetType = dc.compatibleType; char targetType = dc.compatibleType;
getLeftOperand().generateCode(mv, cf); getLeftOperand().generateCode(mv, cf);
if (!leftPrim) { if (!leftPrim) {
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc); CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
} }
cf.enterCompilationScope(); cf.enterCompilationScope();
getRightOperand().generateCode(mv, cf); getRightOperand().generateCode(mv, cf);
cf.exitCompilationScope(); cf.exitCompilationScope();
@ -91,23 +89,23 @@ public class OpEQ extends Operator {
CodeFlow.insertUnboxInsns(mv, targetType, rightDesc); CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
} }
// assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc) // assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
if (targetType=='D') { if (targetType == 'D') {
mv.visitInsn(DCMPL); mv.visitInsn(DCMPL);
mv.visitJumpInsn(IFNE, elseTarget); mv.visitJumpInsn(IFNE, elseTarget);
} }
else if (targetType=='F') { else if (targetType == 'F') {
mv.visitInsn(FCMPL); mv.visitInsn(FCMPL);
mv.visitJumpInsn(IFNE, elseTarget); mv.visitJumpInsn(IFNE, elseTarget);
} }
else if (targetType=='J') { else if (targetType == 'J') {
mv.visitInsn(LCMP); mv.visitInsn(LCMP);
mv.visitJumpInsn(IFNE, elseTarget); mv.visitJumpInsn(IFNE, elseTarget);
} }
else if (targetType=='I' || targetType=='Z') { else if (targetType == 'I' || targetType == 'Z') {
mv.visitJumpInsn(IF_ICMPNE, elseTarget); mv.visitJumpInsn(IF_ICMPNE, elseTarget);
} }
else { else {
throw new IllegalStateException("Unexpected descriptor "+leftDesc); throw new IllegalStateException("Unexpected descriptor " + leftDesc);
} }
} }
else { else {
@ -120,11 +118,11 @@ public class OpEQ extends Operator {
CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0)); CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
} }
Label leftNotNull = new Label(); Label leftNotNull = new Label();
mv.visitInsn(DUP_X1); // Dup right on the top of the stack mv.visitInsn(DUP_X1); // dup right on the top of the stack
mv.visitJumpInsn(IFNONNULL,leftNotNull); mv.visitJumpInsn(IFNONNULL, leftNotNull);
// Right is null! // Right is null!
mv.visitInsn(SWAP); mv.visitInsn(SWAP);
mv.visitInsn(POP); // remove it mv.visitInsn(POP); // remove it
Label rightNotNull = new Label(); Label rightNotNull = new Label();
mv.visitJumpInsn(IFNONNULL, rightNotNull); mv.visitJumpInsn(IFNONNULL, rightNotNull);
// Left is null too // Left is null too
@ -132,7 +130,7 @@ public class OpEQ extends Operator {
mv.visitJumpInsn(GOTO, endOfIf); mv.visitJumpInsn(GOTO, endOfIf);
mv.visitLabel(rightNotNull); mv.visitLabel(rightNotNull);
mv.visitInsn(ICONST_0); mv.visitInsn(ICONST_0);
mv.visitJumpInsn(GOTO,endOfIf); mv.visitJumpInsn(GOTO, endOfIf);
mv.visitLabel(leftNotNull); mv.visitLabel(leftNotNull);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false);
mv.visitLabel(endOfIf); mv.visitLabel(endOfIf);
@ -140,7 +138,7 @@ public class OpEQ extends Operator {
return; return;
} }
mv.visitInsn(ICONST_1); mv.visitInsn(ICONST_1);
mv.visitJumpInsn(GOTO,endOfIf); mv.visitJumpInsn(GOTO, endOfIf);
mv.visitLabel(elseTarget); mv.visitLabel(elseTarget);
mv.visitInsn(ICONST_0); mv.visitInsn(ICONST_0);
mv.visitLabel(endOfIf); mv.visitLabel(endOfIf);

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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"; this.exitTypeDescriptor = "Z";
} }
@Override @Override
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException { public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object left = getLeftOperand().getValueInternal(state).getValue(); Object left = getLeftOperand().getValueInternal(state).getValue();
Object right = getRightOperand().getValueInternal(state).getValue(); Object right = getRightOperand().getValueInternal(state).getValue();
leftActualDescriptor = CodeFlow.toDescriptorFromObject(left); this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
rightActualDescriptor = CodeFlow.toDescriptorFromObject(right); this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
return BooleanTypedValue.forValue(!equalityCheck(state, left, right)); return BooleanTypedValue.forValue(!equalityCheck(state, left, right));
} }
@ -57,7 +58,8 @@ public class OpNE extends Operator {
String leftDesc = left.exitTypeDescriptor; String leftDesc = left.exitTypeDescriptor;
String rightDesc = right.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); return (!dc.areNumbers || dc.areCompatible);
} }
@ -70,16 +72,15 @@ public class OpNE extends Operator {
boolean leftPrim = CodeFlow.isPrimitive(leftDesc); boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
boolean rightPrim = CodeFlow.isPrimitive(rightDesc); 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) { if (dc.areNumbers && dc.areCompatible) {
char targetType = dc.compatibleType; char targetType = dc.compatibleType;
getLeftOperand().generateCode(mv, cf); getLeftOperand().generateCode(mv, cf);
if (!leftPrim) { if (!leftPrim) {
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc); CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
} }
cf.enterCompilationScope(); cf.enterCompilationScope();
getRightOperand().generateCode(mv, cf); getRightOperand().generateCode(mv, cf);
cf.exitCompilationScope(); cf.exitCompilationScope();
@ -103,7 +104,7 @@ public class OpNE extends Operator {
mv.visitJumpInsn(IF_ICMPEQ, elseTarget); mv.visitJumpInsn(IF_ICMPEQ, elseTarget);
} }
else { else {
throw new IllegalStateException("Unexpected descriptor "+leftDesc); throw new IllegalStateException("Unexpected descriptor " + leftDesc);
} }
} }
else { else {

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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(); return sb.toString();
} }
protected boolean isCompilableOperatorUsingNumerics() { protected boolean isCompilableOperatorUsingNumerics() {
SpelNodeImpl left = getLeftOperand(); SpelNodeImpl left = getLeftOperand();
SpelNodeImpl right= getRightOperand(); SpelNodeImpl right= getRightOperand();
@ -94,8 +95,8 @@ public abstract class Operator extends SpelNodeImpl {
// Supported operand types for equals (at the moment) // Supported operand types for equals (at the moment)
String leftDesc = left.exitTypeDescriptor; String leftDesc = left.exitTypeDescriptor;
String rightDesc = right.exitTypeDescriptor; String rightDesc = right.exitTypeDescriptor;
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
this.leftActualDescriptor, this.rightActualDescriptor); leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
return (dc.areNumbers && dc.areCompatible); return (dc.areNumbers && dc.areCompatible);
} }
@ -109,9 +110,9 @@ public abstract class Operator extends SpelNodeImpl {
boolean unboxLeft = !CodeFlow.isPrimitive(leftDesc); boolean unboxLeft = !CodeFlow.isPrimitive(leftDesc);
boolean unboxRight = !CodeFlow.isPrimitive(rightDesc); boolean unboxRight = !CodeFlow.isPrimitive(rightDesc);
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(
this.leftActualDescriptor, this.rightActualDescriptor); leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
char targetType = dc.compatibleType;//CodeFlow.toPrimitiveTargetDesc(leftDesc); char targetType = dc.compatibleType; // CodeFlow.toPrimitiveTargetDesc(leftDesc);
getLeftOperand().generateCode(mv, cf); getLeftOperand().generateCode(mv, cf);
if (unboxLeft) { if (unboxLeft) {
@ -128,23 +129,23 @@ public abstract class Operator extends SpelNodeImpl {
// assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc) // assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
Label elseTarget = new Label(); Label elseTarget = new Label();
Label endOfIf = new Label(); Label endOfIf = new Label();
if (targetType=='D') { if (targetType == 'D') {
mv.visitInsn(DCMPG); mv.visitInsn(DCMPG);
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') {
mv.visitJumpInsn(compInstruction2, elseTarget); mv.visitJumpInsn(compInstruction2, elseTarget);
} }
else { 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) // 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 * A descriptor comparison encapsulates the result of comparing descriptor
* describes at what level they are compatible. * for two operands and describes at what level they are compatible.
*/ */
protected static class DescriptorComparison { protected static class DescriptorComparison {
@ -224,12 +225,12 @@ public abstract class Operator extends SpelNodeImpl {
static DescriptorComparison INCOMPATIBLE_NUMBERS = new DescriptorComparison(true, false, ' '); 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) { private DescriptorComparison(boolean areNumbers, boolean areCompatible, char compatibleType) {
this.areNumbers = areNumbers; this.areNumbers = areNumbers;
this.areCompatible = areCompatible; 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 * Return an object that indicates whether the input descriptors are compatible.
* is what could statically be determined (e.g. from looking at the return value of a property accessor * <p>A declared descriptor is what could statically be determined (e.g. from looking
* method) whilst an actual descriptor is the type of an actual object that was returned, which may differ. * at the return value of a property accessor method) whilst an actual descriptor
* For generic types with unbound type variables the declared descriptor discovered may be 'Object' but * is the type of an actual object that was returned, which may differ.
* from the actual descriptor it is possible to observe that the objects are really numeric values (e.g. * <p>For generic types with unbound type variables, the declared descriptor
* ints). * 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 leftDeclaredDescriptor the statically determinable left descriptor
* @param rightDeclaredDescriptor the statically determinable right descriptor * @param rightDeclaredDescriptor the statically determinable right descriptor
* @param leftActualDescriptor the dynamic/runtime left object descriptor * @param leftActualDescriptor the dynamic/runtime left object descriptor