11/*
2- * Copyright 2002-2014 the original author or authors.
2+ * Copyright 2002-2016 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1616
1717package org .springframework .expression .spel .ast ;
1818
19- import org .springframework .asm .Label ;
2019import org .springframework .asm .MethodVisitor ;
20+ import org .springframework .expression .EvaluationContext ;
2121import org .springframework .expression .EvaluationException ;
2222import org .springframework .expression .spel .CodeFlow ;
2323import org .springframework .expression .spel .ExpressionState ;
@@ -36,112 +36,61 @@ public OpEQ(int pos, SpelNodeImpl... operands) {
3636 this .exitTypeDescriptor = "Z" ;
3737 }
3838
39-
4039 @ Override
41- public BooleanTypedValue getValueInternal (ExpressionState state ) throws EvaluationException {
40+ public BooleanTypedValue getValueInternal (ExpressionState state )
41+ throws EvaluationException {
4242 Object left = getLeftOperand ().getValueInternal (state ).getValue ();
4343 Object right = getRightOperand ().getValueInternal (state ).getValue ();
4444 this .leftActualDescriptor = CodeFlow .toDescriptorFromObject (left );
4545 this .rightActualDescriptor = CodeFlow .toDescriptorFromObject (right );
46- return BooleanTypedValue .forValue (equalityCheck (state , left , right ));
46+ return BooleanTypedValue .forValue (
47+ equalityCheck (state .getEvaluationContext (), left , right ));
4748 }
48-
49+
4950 // This check is different to the one in the other numeric operators (OpLt/etc)
5051 // because it allows for simple object comparison
5152 @ Override
5253 public boolean isCompilable () {
5354 SpelNodeImpl left = getLeftOperand ();
54- SpelNodeImpl right = getRightOperand ();
55+ SpelNodeImpl right = getRightOperand ();
5556 if (!left .isCompilable () || !right .isCompilable ()) {
5657 return false ;
5758 }
5859
5960 String leftDesc = left .exitTypeDescriptor ;
6061 String rightDesc = right .exitTypeDescriptor ;
61- DescriptorComparison dc = DescriptorComparison .checkNumericCompatibility (
62- leftDesc , rightDesc , this .leftActualDescriptor , this .rightActualDescriptor );
62+ DescriptorComparison dc = DescriptorComparison .checkNumericCompatibility (leftDesc ,
63+ rightDesc , this .leftActualDescriptor , this .rightActualDescriptor );
6364 return (!dc .areNumbers || dc .areCompatible );
6465 }
65-
66-
66+
6767 @ Override
6868 public void generateCode (MethodVisitor mv , CodeFlow cf ) {
69+ cf .loadEvaluationContext (mv );
6970 String leftDesc = getLeftOperand ().exitTypeDescriptor ;
7071 String rightDesc = getRightOperand ().exitTypeDescriptor ;
71- Label elseTarget = new Label ();
72- Label endOfIf = new Label ();
7372 boolean leftPrim = CodeFlow .isPrimitive (leftDesc );
7473 boolean rightPrim = CodeFlow .isPrimitive (rightDesc );
7574
76- DescriptorComparison dc = DescriptorComparison .checkNumericCompatibility (
77- leftDesc , rightDesc , this .leftActualDescriptor , this .rightActualDescriptor );
78-
79- if (dc .areNumbers && dc .areCompatible ) {
80- char targetType = dc .compatibleType ;
81- getLeftOperand ().generateCode (mv , cf );
82- if (!leftPrim ) {
83- CodeFlow .insertUnboxInsns (mv , targetType , leftDesc );
84- }
85- cf .enterCompilationScope ();
86- getRightOperand ().generateCode (mv , cf );
87- cf .exitCompilationScope ();
88- if (!rightPrim ) {
89- CodeFlow .insertUnboxInsns (mv , targetType , rightDesc );
90- }
91- // assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
92- if (targetType == 'D' ) {
93- mv .visitInsn (DCMPL );
94- mv .visitJumpInsn (IFNE , elseTarget );
95- }
96- else if (targetType == 'F' ) {
97- mv .visitInsn (FCMPL );
98- mv .visitJumpInsn (IFNE , elseTarget );
99- }
100- else if (targetType == 'J' ) {
101- mv .visitInsn (LCMP );
102- mv .visitJumpInsn (IFNE , elseTarget );
103- }
104- else if (targetType == 'I' || targetType == 'Z' ) {
105- mv .visitJumpInsn (IF_ICMPNE , elseTarget );
106- }
107- else {
108- throw new IllegalStateException ("Unexpected descriptor " + leftDesc );
109- }
75+ cf .enterCompilationScope ();
76+ getLeftOperand ().generateCode (mv , cf );
77+ cf .exitCompilationScope ();
78+ if (leftPrim ) {
79+ CodeFlow .insertBoxIfNecessary (mv , leftDesc .charAt (0 ));
11080 }
111- else {
112- getLeftOperand ().generateCode (mv , cf );
113- if (leftPrim ) {
114- CodeFlow .insertBoxIfNecessary (mv , leftDesc .charAt (0 ));
115- }
116- getRightOperand ().generateCode (mv , cf );
117- if (rightPrim ) {
118- CodeFlow .insertBoxIfNecessary (mv , rightDesc .charAt (0 ));
119- }
120- Label leftNotNull = new Label ();
121- mv .visitInsn (DUP_X1 ); // dup right on the top of the stack
122- mv .visitJumpInsn (IFNONNULL , leftNotNull );
123- // Right is null!
124- mv .visitInsn (SWAP );
125- mv .visitInsn (POP ); // remove it
126- Label rightNotNull = new Label ();
127- mv .visitJumpInsn (IFNONNULL , rightNotNull );
128- // Left is null too
129- mv .visitInsn (ICONST_1 );
130- mv .visitJumpInsn (GOTO , endOfIf );
131- mv .visitLabel (rightNotNull );
132- mv .visitInsn (ICONST_0 );
133- mv .visitJumpInsn (GOTO , endOfIf );
134- mv .visitLabel (leftNotNull );
135- mv .visitMethodInsn (INVOKEVIRTUAL , "java/lang/Object" , "equals" , "(Ljava/lang/Object;)Z" , false );
136- mv .visitLabel (endOfIf );
137- cf .pushDescriptor ("Z" );
138- return ;
81+ cf .enterCompilationScope ();
82+ getRightOperand ().generateCode (mv , cf );
83+ cf .exitCompilationScope ();
84+ if (rightPrim ) {
85+ CodeFlow .insertBoxIfNecessary (mv , rightDesc .charAt (0 ));
13986 }
140- mv .visitInsn (ICONST_1 );
141- mv .visitJumpInsn (GOTO , endOfIf );
142- mv .visitLabel (elseTarget );
143- mv .visitInsn (ICONST_0 );
144- mv .visitLabel (endOfIf );
87+
88+ String operatorClassName = Operator .class .getName ().replace ('.' , '/' );
89+ String evaluationContextClassName = EvaluationContext .class .getName ().replace ('.' ,
90+ '/' );
91+ mv .visitMethodInsn (INVOKESTATIC , operatorClassName , "equalityCheck" , "(L"
92+ + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z" ,
93+ false );
14594 cf .pushDescriptor ("Z" );
14695 }
14796
0 commit comments