private void prepareLeftOperand( BooleanOperator operation, Class<?> type, Class<?> leftType, Class<?> rightType, Label shortcutEvaluation) { if (leftType.isPrimitive()) { if (type != null) { castOrCoercePrimitive(LEFT_OPERAND, leftType, type); } return; } Label notNullLabel = jitLeftIsNull( type == null || leftType == type ? jitNullSafeOperationStart() : jitNullSafeCoercion(leftType, type)); if (operation.isEquality() && !rightType.isPrimitive()) { // if (left == null) return right == null checkNullEquality(); } else { // if (left == null) return false mv.visitInsn(ICONST_0); } mv.visitJumpInsn(GOTO, shortcutEvaluation); mv.visitLabel(notNullLabel); }
private void jitMapAccessInvocation(MapAccessInvocation invocation, boolean firstInvocation) { if (firstInvocation) { mv.visitVarInsn(ALOAD, 1); cast(Map.class); } Class<?> keyClass = jitExpression(invocation.getKey(), invocation.getKeyType()); if (keyClass.isPrimitive()) { convertPrimitiveToObject(keyClass); } invokeInterface(Map.class, "get", Object.class, Object.class); if (invocation.getReturnType() != Object.class) { cast(invocation.getReturnType()); } }
private void castOrCoercePrimitive(int regNr, Class<?> fromType, Class<?> toType) { if (fromType == toType) { return; } load(regNr); if (toType.isPrimitive()) { castPrimitiveToPrimitive(fromType, toType); } else { Class<?> toTypeAsPrimitive = convertToPrimitiveType(toType); castPrimitiveToPrimitive(fromType, toTypeAsPrimitive); invokeStatic(toType, "valueOf", toType, toTypeAsPrimitive); } store(regNr, toType); }
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 prepareRightOperand( Expression right, Class<?> type, Class<?> rightType, Label shortcutEvaluation) { if (rightType.isPrimitive()) { if (type != null) { castOrCoercePrimitive(RIGHT_OPERAND, rightType, type); } return; } Label nullLabel = new Label(); Label notNullLabel = new Label(); load(RIGHT_OPERAND); mv.visitJumpInsn(IFNULL, nullLabel); if (type != null && !isFixed(right) && rightType != type) { castOrCoerceTo(RIGHT_OPERAND, rightType, type, nullLabel); } mv.visitJumpInsn(GOTO, notNullLabel); mv.visitLabel(nullLabel); mv.visitInsn(ICONST_0); mv.visitJumpInsn(GOTO, shortcutEvaluation); mv.visitLabel(notNullLabel); }
private Class<?> findCommonClass(Class<?> class1, Class<?> class2, boolean canBePrimitive) { if (class1.isAssignableFrom(class2)) { return class1; } if (class1 == boolean.class && class2 == Boolean.class) { return canBePrimitive ? boolean.class : Boolean.class; } if (class1 == char.class && class2 == Character.class) { return canBePrimitive ? char.class : Character.class; } if (class1 == byte.class && class2 == Byte.class) { return canBePrimitive ? byte.class : Byte.class; } if (class1 == short.class && class2 == Short.class) { return canBePrimitive ? short.class : Short.class; } if (class1 == Number.class && class2.isPrimitive()) { return Double.class; } if (class1 == int.class || class1 == short.class || class1 == byte.class) { if (class2 == Integer.class) { return canBePrimitive ? int.class : Integer.class; } if (class2 == long.class) { return long.class; } if (class2 == Long.class) { return canBePrimitive ? long.class : Long.class; } if (class2 == float.class) { return float.class; } if (class2 == Float.class) { return canBePrimitive ? float.class : Float.class; } if (class2 == double.class) { return double.class; } if (class2 == Double.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == BigInteger.class) { return BigInteger.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == long.class) { if (class2 == int.class) { return long.class; } if (class2 == Integer.class) { return canBePrimitive ? long.class : Long.class; } if (class2 == Long.class) { return canBePrimitive ? long.class : Long.class; } if (class2 == float.class) { return double.class; } if (class2 == Float.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == double.class) { return double.class; } if (class2 == Double.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == BigInteger.class) { return BigInteger.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == float.class) { if (class2 == int.class) { return float.class; } if (class2 == Integer.class) { return canBePrimitive ? float.class : Float.class; } if (class2 == long.class) { return double.class; } if (class2 == Long.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == Float.class) { return canBePrimitive ? float.class : Float.class; } if (class2 == double.class) { return double.class; } if (class2 == Double.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == BigInteger.class) { return BigDecimal.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == double.class) { if (class2 == int.class) { return float.class; } if (class2 == Integer.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == long.class) { return double.class; } if (class2 == Long.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == float.class) { return double.class; } if (class2 == Float.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == Double.class) { return canBePrimitive ? double.class : Double.class; } if (class2 == BigInteger.class) { return BigDecimal.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == Integer.class) { if (class2 == Long.class) { return Long.class; } if (class2 == Float.class) { return Float.class; } if (class2 == Double.class) { return Double.class; } if (class2 == BigInteger.class) { return BigInteger.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == Long.class) { if (class2 == Float.class) { return Double.class; } if (class2 == Double.class) { return Double.class; } if (class2 == BigInteger.class) { return BigInteger.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == Float.class) { if (class2 == Double.class) { return Double.class; } if (class2 == BigInteger.class) { return BigDecimal.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == Double.class) { if (class2 == BigInteger.class) { return BigDecimal.class; } if (class2 == BigDecimal.class) { return BigDecimal.class; } } if (class1 == BigInteger.class) { if (class2 == BigDecimal.class) { return BigDecimal.class; } } return null; }
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); }