private void jitBinary(SingleCondition singleCondition) { Expression left = singleCondition.getLeft(); Expression right = singleCondition.getRight(); Class<?> commonType = singleCondition.getOperation().needsSameType() ? findCommonClass( left.getType(), !left.canBeNull(), right.getType(), !right.canBeNull()) : null; if (commonType == Object.class && singleCondition.getOperation().isComparison()) { commonType = Comparable.class; } if (commonType != null && commonType.isPrimitive()) { jitPrimitiveBinary(singleCondition, left, right, commonType); } else { jitObjectBinary(singleCondition, left, right, commonType); } }
private void jitPrimitiveBinary( SingleCondition singleCondition, Expression left, Expression right, Class<?> type) { if (isFixed(right) && right.canBeNull()) { // a primitive cannot be null mv.visitInsn(singleCondition.getOperation() == BooleanOperator.NE ? ICONST_1 : ICONST_0); return; } Label nullArg = new Label(); ensureNotNullArgs(left, right, nullArg); jitExpression(left, type); castExpressionResultToPrimitive(left, type); jitExpression(right, type); castExpressionResultToPrimitive(right, type); jitPrimitiveOperation(singleCondition.getOperation(), type); Label nonNullArg = new Label(); mv.visitJumpInsn(GOTO, nonNullArg); mv.visitLabel(nullArg); mv.visitInsn(ICONST_0); mv.visitLabel(nonNullArg); }
private void jitSingleCondition(SingleCondition singleCondition) { if (singleCondition.isBinary()) { switch (singleCondition.getOperation()) { case MATCHES: jitMatches(singleCondition); break; case INSTANCEOF: jitInstanceof(singleCondition); break; default: jitBinary(singleCondition); } } else { jitUnary(singleCondition); } }
private void jitObjectBinary( SingleCondition singleCondition, Expression left, Expression right, Class<?> type) { Class<?> leftType = isDeclarationExpression(left) ? convertFromPrimitiveType(left.getType()) : left.getType(); Class<?> rightType = isDeclarationExpression(right) ? convertFromPrimitiveType(right.getType()) : right.getType(); jitExpression(left, type != null ? type : leftType); if (isDeclarationExpression(left) && left.getType().isPrimitive()) { castFromPrimitive(left.getType()); } store(LEFT_OPERAND, leftType); jitExpression(right, type != null ? type : rightType); if (isDeclarationExpression(right) && right.getType().isPrimitive()) { castFromPrimitive(right.getType()); } store(RIGHT_OPERAND, rightType); Label shortcutEvaluation = new Label(); BooleanOperator operation = singleCondition.getOperation(); prepareLeftOperand(operation, type, leftType, rightType, shortcutEvaluation); prepareRightOperand(right, type, rightType, shortcutEvaluation); load(LEFT_OPERAND); load(RIGHT_OPERAND); switch (operation) { case CONTAINS: invokeStatic( EvaluatorHelper.class, "contains", boolean.class, Object.class, rightType.isPrimitive() ? rightType : Object.class); break; case MATCHES: invokeVirtual(type, "matches", boolean.class, String.class); break; case SOUNDSLIKE: invokeStatic( EvaluatorHelper.class, "soundslike", boolean.class, String.class, String.class); break; default: if (operation.isEquality()) { if (type.isInterface()) { invokeInterface(type, "equals", boolean.class, Object.class); } else { invokeVirtual(type, "equals", boolean.class, Object.class); } if (operation == BooleanOperator.NE) { singleCondition.toggleNegation(); } } else { if (type.isInterface()) { invokeInterface( type, "compareTo", int.class, type == Comparable.class ? Object.class : type); } else { invokeVirtual(type, "compareTo", int.class, type); } mv.visitInsn(ICONST_0); jitPrimitiveOperation(operation, int.class); } } mv.visitLabel(shortcutEvaluation); }