public void generateInitializations(Variable thisVariable, BytecodeBlock block) { for (Map.Entry<FieldDefinition, MethodHandle> entry : initializers.entrySet()) { Binding binding = callSiteBinder.bind(entry.getValue()); block.append(thisVariable) .append(invoke(binding, "instanceFieldConstructor")) .putField(entry.getKey()); } } }
@Override public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Scope context) { ParameterAndType parameterAndType = parameterMap.get(reference.getName()); Parameter parameter = parameterAndType.getParameter(); Class<?> type = parameterAndType.getType(); return new BytecodeBlock() .append(parameter) .append(unboxPrimitiveIfNecessary(context, type)); } };
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext context, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) { Preconditions.checkArgument(arguments.size() == 3); Variable wasNull = context.wasNull(); BytecodeBlock condition = new BytecodeBlock() .append(context.generate(arguments.get(0), Optional.empty())) .comment("... and condition value was not null") .append(wasNull) .invokeStatic(CompilerOperations.class, "not", boolean.class, boolean.class) .invokeStatic(CompilerOperations.class, "and", boolean.class, boolean.class, boolean.class) .append(wasNull.set(constantFalse())); BytecodeBlock block = new BytecodeBlock() .append(new IfStatement() .condition(condition) .ifTrue(context.generate(arguments.get(1), Optional.empty())) .ifFalse(context.generate(arguments.get(2), Optional.empty()))); outputBlockVariable.ifPresent(output -> block.append(generateWrite(context, returnType, output))); return block; } }
@Override public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) { RowExpression argument = arguments.get(0); Signature function = generatorContext .getRegistry() .getCoercion(argument.getType(), returnType); BytecodeBlock block = new BytecodeBlock() .append(generatorContext.generateCall( function.getName(), generatorContext.getRegistry().getScalarFunctionImplementation(function), ImmutableList.of(generatorContext.generate(argument, Optional.empty())))); outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output))); return block; } }
private static MethodDefinition generateGetIntermediateType(ClassDefinition definition, CallSiteBinder callSiteBinder, List<Type> type) { MethodDefinition methodDefinition = definition.declareMethod(a(PUBLIC), "getIntermediateType", type(Type.class)); if (type.size() == 1) { methodDefinition.getBody() .append(constantType(callSiteBinder, getOnlyElement(type))) .retObject(); } else { methodDefinition.getBody() .append(constantType(callSiteBinder, RowType.anonymous(type))) .retObject(); } return methodDefinition; }
private static void generateGetSerializedType(ClassDefinition definition, List<StateField> fields, CallSiteBinder callSiteBinder) { BytecodeBlock body = definition.declareMethod(a(PUBLIC), "getSerializedType", type(Type.class)).getBody(); Type type; if (fields.size() > 1) { List<Type> types = fields.stream().map(StateField::getSqlType).collect(toImmutableList()); type = RowType.anonymous(types); } else if (fields.size() == 1) { type = getOnlyElement(fields).getSqlType(); } else { type = UNKNOWN; } body.comment("return %s", type.getTypeSignature()) .append(constantType(callSiteBinder, type)) .retObject(); }
@Override public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Context context) { BytecodeNode variableReferenceByteCode = fieldReferenceCompiler.visitVariableReference(reference, context.getScope()); if (!context.getOutputBlockVariable().isPresent()) { return variableReferenceByteCode; } return new BytecodeBlock() .append(variableReferenceByteCode) .append(generateWrite( callSiteBinder, context.getScope(), context.getScope().getVariable("wasNull"), reference.getType(), context.getOutputBlockVariable().get())); } }
@Override public BytecodeNode visitInputReference(InputReferenceExpression node, Context context) { BytecodeNode inputReferenceBytecode = fieldReferenceCompiler.visitInputReference(node, context.getScope()); if (!context.getOutputBlockVariable().isPresent()) { return inputReferenceBytecode; } return new BytecodeBlock() .append(inputReferenceBytecode) .append(generateWrite( callSiteBinder, context.getScope(), context.getScope().getVariable("wasNull"), node.getType(), context.getOutputBlockVariable().get())); }
private static void generateEnsureCapacity(Scope scope, List<FieldDefinition> stateFields, BytecodeBlock block) { Variable groupIdsBlock = scope.getVariable("groupIdsBlock"); for (FieldDefinition stateField : stateFields) { BytecodeExpression state = scope.getThis().getField(stateField); block.append(state.invoke("ensureCapacity", void.class, groupIdsBlock.invoke("getGroupCount", long.class))); } }
private static void generateGetEstimatedSize(ClassDefinition definition, List<FieldDefinition> stateFields) { MethodDefinition method = definition.declareMethod(a(PUBLIC), "getEstimatedSize", type(long.class)); Variable estimatedSize = method.getScope().declareVariable(long.class, "estimatedSize"); method.getBody().append(estimatedSize.set(constantLong(0L))); for (FieldDefinition stateField : stateFields) { method.getBody() .append(estimatedSize.set( BytecodeExpressions.add( estimatedSize, method.getThis().getField(stateField).invoke("getEstimatedSize", long.class)))); } method.getBody().append(estimatedSize.ret()); }
private static void generateSetGroupIdFromGroupIdsBlock(Scope scope, List<FieldDefinition> stateFields, BytecodeBlock block) { Variable groupIdsBlock = scope.getVariable("groupIdsBlock"); Variable position = scope.getVariable("position"); for (FieldDefinition stateField : stateFields) { BytecodeExpression state = scope.getThis().getField(stateField); block.append(state.invoke("setGroupId", void.class, groupIdsBlock.invoke("getGroupId", long.class, position))); } }
private static void generateConstructor( ClassDefinition classDefinition, FieldDefinition sessionField, CachedInstanceBinder cachedInstanceBinder) { Parameter sessionParameter = arg("session", ConnectorSession.class); MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), sessionParameter); BytecodeBlock body = constructorDefinition.getBody(); Variable thisVariable = constructorDefinition.getThis(); body.comment("super();") .append(thisVariable) .invokeConstructor(Object.class); body.append(thisVariable.setField(sessionField, sessionParameter)); cachedInstanceBinder.generateInitializations(thisVariable, body); body.ret(); }
private static MethodDefinition generateGetFinalType(ClassDefinition definition, CallSiteBinder callSiteBinder, Type type) { MethodDefinition methodDefinition = definition.declareMethod(a(PUBLIC), "getFinalType", type(Type.class)); methodDefinition.getBody() .append(constantType(callSiteBinder, type)) .retObject(); return methodDefinition; }
private static void generateConstructor( ClassDefinition classDefinition, CachedInstanceBinder cachedInstanceBinder, Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap, Consumer<MethodDefinition> additionalStatements) { MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC)); BytecodeBlock body = constructorDefinition.getBody(); Variable thisVariable = constructorDefinition.getThis(); body.comment("super();") .append(thisVariable) .invokeConstructor(Object.class); additionalStatements.accept(constructorDefinition); cachedInstanceBinder.generateInitializations(thisVariable, body); body.ret(); }
private static void generateGetSizeInBytesMethod(ClassDefinition classDefinition, FieldDefinition sizeField) { MethodDefinition getSizeInBytesMethod = classDefinition.declareMethod(a(PUBLIC), "getSizeInBytes", type(long.class)); Variable thisVariable = getSizeInBytesMethod.getThis(); getSizeInBytesMethod.getBody() .append(thisVariable.getField(sizeField)) .retLong(); }
private static void generateToString(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, String string) { // bind constant via invokedynamic to avoid constant pool issues due to large strings classDefinition.declareMethod(a(PUBLIC), "toString", type(String.class)) .getBody() .append(invoke(callSiteBinder.bind(string, String.class), "toString")) .retObject(); }
private static void generateToString(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, String string) { // bind constant via invokedynamic to avoid constant pool issues due to large strings classDefinition.declareMethod(a(PUBLIC), "toString", type(String.class)) .getBody() .append(invoke(callSiteBinder.bind(string, String.class), "toString")) .retObject(); }
private static void generateField(ClassDefinition definition, MethodDefinition constructor, StateField stateField) { FieldDefinition field = definition.declareField(a(PRIVATE), UPPER_CAMEL.to(LOWER_CAMEL, stateField.getName()) + "Value", stateField.getType()); // Generate getter MethodDefinition getter = definition.declareMethod(a(PUBLIC), stateField.getGetterName(), type(stateField.getType())); getter.getBody() .append(getter.getThis().getField(field).ret()); // Generate setter Parameter value = arg("value", stateField.getType()); MethodDefinition setter = definition.declareMethod(a(PUBLIC), stateField.getSetterName(), type(void.class), value); setter.getBody() .append(setter.getThis().setField(field, value)) .ret(); constructor.getBody() .append(constructor.getThis().setField(field, stateField.initialValueExpression())); }
private void generateOutputMethod(ClassDefinition definition, CallSiteBinder binder, Type valueType, Class<?> stateClass) { Parameter state = arg("state", stateClass); Parameter out = arg("out", BlockBuilder.class); MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "output", type(void.class), state, out); IfStatement ifStatement = new IfStatement() .condition(or(state.invoke("isFirstNull", boolean.class), state.invoke("isSecondNull", boolean.class))) .ifTrue(new BytecodeBlock().append(out.invoke("appendNull", BlockBuilder.class)).pop()); SqlTypeBytecodeExpression valueSqlType = constantType(binder, valueType); BytecodeExpression getValueExpression; if (valueType.getJavaType().isPrimitive()) { getValueExpression = state.invoke("getSecond", valueType.getJavaType()); } else { getValueExpression = valueSqlType.getValue(state.invoke("getSecondBlock", Block.class), state.invoke("getSecondPosition", int.class)); } ifStatement.ifFalse(valueSqlType.writeValue(out, getValueExpression)); method.getBody().append(ifStatement).ret(); } }