use of io.airlift.bytecode.control.IfStatement in project trino by trinodb.
the class BytecodeUtils method handleNullValue.
public static BytecodeNode handleNullValue(Scope scope, LabelNode label, Class<?> returnType, List<Class<?>> stackArgsToPop, boolean clearNullFlag) {
Variable wasNull = scope.getVariable("wasNull");
BytecodeBlock nullCheck = new BytecodeBlock().setDescription("ifWasNullGoto").append(wasNull);
String clearComment = null;
if (clearNullFlag) {
nullCheck.append(wasNull.set(constantFalse()));
clearComment = "clear wasNull";
}
BytecodeBlock isNull = new BytecodeBlock();
for (Class<?> parameterType : stackArgsToPop) {
isNull.pop(parameterType);
}
isNull.pushJavaDefault(returnType);
String loadDefaultComment;
loadDefaultComment = format("loadJavaDefault(%s)", returnType.getName());
isNull.gotoLabel(label);
String popComment = null;
if (!stackArgsToPop.isEmpty()) {
popComment = format("pop(%s)", Joiner.on(", ").join(stackArgsToPop));
}
return new IfStatement("if wasNull then %s", Joiner.on(", ").skipNulls().join(clearComment, popComment, loadDefaultComment, "goto " + label.getLabel())).condition(nullCheck).ifTrue(isNull);
}
use of io.airlift.bytecode.control.IfStatement in project trino by trinodb.
the class CoalesceCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext) {
List<BytecodeNode> operands = new ArrayList<>();
for (RowExpression expression : arguments) {
operands.add(generatorContext.generate(expression));
}
Variable wasNull = generatorContext.wasNull();
BytecodeNode nullValue = new BytecodeBlock().append(wasNull.set(constantTrue())).pushJavaDefault(returnType.getJavaType());
// reverse list because current if statement builder doesn't support if/else so we need to build the if statements bottom up
for (BytecodeNode operand : Lists.reverse(operands)) {
IfStatement ifStatement = new IfStatement();
ifStatement.condition().append(operand).append(wasNull);
// if value was null, pop the null value, clear the null flag, and process the next operand
ifStatement.ifTrue().pop(returnType.getJavaType()).append(wasNull.set(constantFalse())).append(nullValue);
nullValue = ifStatement;
}
return nullValue;
}
use of io.airlift.bytecode.control.IfStatement in project trino by trinodb.
the class StateCompiler method generateSerialize.
private static <T> void generateSerialize(ClassDefinition definition, CallSiteBinder binder, Class<T> clazz, List<StateField> fields) {
Parameter state = arg("state", AccumulatorState.class);
Parameter out = arg("out", BlockBuilder.class);
MethodDefinition method = definition.declareMethod(a(PUBLIC), "serialize", type(void.class), state, out);
Scope scope = method.getScope();
BytecodeBlock serializerBody = method.getBody();
if (fields.size() == 0) {
serializerBody.append(out.invoke("appendNull", BlockBuilder.class).pop());
} else if (fields.size() == 1) {
Method getter = getGetter(clazz, getOnlyElement(fields));
SqlTypeBytecodeExpression sqlType = constantType(binder, getOnlyElement(fields).getSqlType());
Variable fieldValue = scope.declareVariable(getter.getReturnType(), "value");
serializerBody.append(fieldValue.set(state.cast(getter.getDeclaringClass()).invoke(getter)));
if (!getOnlyElement(fields).isPrimitiveType()) {
serializerBody.append(new IfStatement().condition(equal(fieldValue, constantNull(getter.getReturnType()))).ifTrue(out.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(sqlType.writeValue(out, fieldValue)));
} else {
// For primitive type, we need to cast here because we serialize byte fields with TINYINT/INTEGER (whose java type is long).
serializerBody.append(sqlType.writeValue(out, fieldValue.cast(getOnlyElement(fields).getSqlType().getJavaType())));
}
} else if (fields.size() > 1) {
Variable rowBuilder = scope.declareVariable(BlockBuilder.class, "rowBuilder");
serializerBody.append(rowBuilder.set(out.invoke("beginBlockEntry", BlockBuilder.class)));
for (StateField field : fields) {
Method getter = getGetter(clazz, field);
SqlTypeBytecodeExpression sqlType = constantType(binder, field.getSqlType());
Variable fieldValue = scope.createTempVariable(getter.getReturnType());
serializerBody.append(fieldValue.set(state.cast(getter.getDeclaringClass()).invoke(getter)));
if (!field.isPrimitiveType()) {
serializerBody.append(new IfStatement().condition(equal(fieldValue, constantNull(getter.getReturnType()))).ifTrue(rowBuilder.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(sqlType.writeValue(rowBuilder, fieldValue)));
} else {
// For primitive type, we need to cast here because we serialize byte fields with TINYINT/INTEGER (whose java type is long).
serializerBody.append(sqlType.writeValue(rowBuilder, fieldValue.cast(field.getSqlType().getJavaType())));
}
}
serializerBody.append(out.invoke("closeEntry", BlockBuilder.class).pop());
}
serializerBody.ret();
}
use of io.airlift.bytecode.control.IfStatement in project trino by trinodb.
the class StateCompiler method generateCopy.
private static void generateCopy(ClassDefinition definition, List<StateField> fields, List<FieldDefinition> fieldDefinitions) {
MethodDefinition copy = definition.declareMethod(a(PUBLIC), "copy", type(AccumulatorState.class));
Variable thisVariable = copy.getThis();
BytecodeBlock body = copy.getBody();
List<BytecodeExpression> fieldCopyExpressions = new ArrayList<>();
for (int i = 0; i < fields.size(); i++) {
Optional<BytecodeExpression> fieldCopy = copyField(thisVariable, fieldDefinitions.get(i), fields.get(i).getType());
if (fieldCopy.isEmpty()) {
body.append(newInstance(UnsupportedOperationException.class, constantString(format("copy not supported for %s (cannot copy field of type %s)", definition.getName(), fields.get(i).getType())))).throwObject();
return;
}
fieldCopyExpressions.add(fieldCopy.get());
}
Variable instanceCopy = copy.getScope().declareVariable(definition.getType(), "instanceCopy");
body.append(instanceCopy.set(newInstance(definition.getType())));
for (int i = 0; i < fieldDefinitions.size(); i++) {
FieldDefinition fieldDefinition = fieldDefinitions.get(i);
Class<?> type = fields.get(i).getType();
if (type == long.class || type == double.class || type == boolean.class || type == byte.class || type == int.class) {
body.append(instanceCopy.setField(fieldDefinition, fieldCopyExpressions.get(i)));
} else {
body.append(new IfStatement("if field value is null").condition(isNull(thisVariable.getField(fieldDefinition))).ifTrue(instanceCopy.setField(fieldDefinition, thisVariable.getField(fieldDefinition))).ifFalse(instanceCopy.setField(fieldDefinition, fieldCopyExpressions.get(i))));
}
}
copy.getBody().append(instanceCopy.ret());
}
Aggregations