Polishing
This commit is contained in:
parent
eaf80781e8
commit
45fc449550
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue