private SqlTypeBytecodeExpression(Type type, Binding binding, Method bootstrapMethod) { super(type(Type.class)); this.type = requireNonNull(type, "type is null"); this.binding = requireNonNull(binding, "binding is null"); this.bootstrapMethod = requireNonNull(bootstrapMethod, "bootstrapMethod is null"); }
private static MethodDefinition declareAddIntermediate(ClassDefinition definition, boolean grouped) { ImmutableList.Builder<Parameter> parameters = ImmutableList.builder(); if (grouped) { parameters.add(arg("groupIdsBlock", GroupByIdBlock.class)); } parameters.add(arg("block", Block.class)); return definition.declareMethod( a(PUBLIC), "addIntermediate", type(void.class), parameters.build()); }
private InvokeFunctionBytecodeExpression( Scope scope, CallSiteBinder binder, String name, ScalarFunctionImplementation function, Optional<BytecodeNode> instance, List<BytecodeExpression> parameters) { super(type(Primitives.unwrap(function.getMethodHandle().type().returnType()))); this.invocation = generateInvocation( scope, name, function, instance, parameters.stream().map(BytecodeNode.class::cast).collect(toImmutableList()), binder); this.oneLineDescription = name + "(" + Joiner.on(", ").join(parameters) + ")"; }
private Class<? extends PageWithPositionComparator> generatePageWithPositionComparatorClass(List<Type> sortTypes, List<Integer> sortChannels, List<SortOrder> sortOrders) { CallSiteBinder callSiteBinder = new CallSiteBinder(); ClassDefinition classDefinition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName("PageWithPositionComparator"), type(Object.class), type(PageWithPositionComparator.class)); classDefinition.declareDefaultConstructor(a(PUBLIC)); generateMergeSortCompareTo(classDefinition, callSiteBinder, sortTypes, sortChannels, sortOrders); return defineClass(classDefinition, PageWithPositionComparator.class, callSiteBinder.getBindings(), getClass().getClassLoader()); }
private <T> Class<? extends T> compileProcessor( RowExpression filter, List<RowExpression> projections, BodyCompiler bodyCompiler, Class<? extends T> superType) { ClassDefinition classDefinition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName(superType.getSimpleName()), type(Object.class), type(superType)); CallSiteBinder callSiteBinder = new CallSiteBinder(); bodyCompiler.generateMethods(classDefinition, callSiteBinder, filter, projections); // // toString method // generateToString( classDefinition, callSiteBinder, toStringHelper(classDefinition.getType().getJavaClassName()) .add("filter", filter) .add("projections", projections) .toString()); return defineClass(classDefinition, superType, callSiteBinder.getBindings(), getClass().getClassLoader()); }
private Class<? extends PagesIndexComparator> compilePagesIndexComparator( List<Type> sortTypes, List<Integer> sortChannels, List<SortOrder> sortOrders) { CallSiteBinder callSiteBinder = new CallSiteBinder(); ClassDefinition classDefinition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName("PagesIndexComparator"), type(Object.class), type(PagesIndexComparator.class)); classDefinition.declareDefaultConstructor(a(PUBLIC)); generatePageIndexCompareTo(classDefinition, callSiteBinder, sortTypes, sortChannels, sortOrders); return defineClass(classDefinition, PagesIndexComparator.class, callSiteBinder.getBindings(), getClass().getClassLoader()); }
private Class<? extends InternalJoinFilterFunction> compileInternalJoinFilterFunction(RowExpression filterExpression, int leftBlocksSize) { ClassDefinition classDefinition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName("JoinFilterFunction"), type(Object.class), type(InternalJoinFilterFunction.class)); CallSiteBinder callSiteBinder = new CallSiteBinder(); new JoinFilterFunctionCompiler(metadata).generateMethods(classDefinition, callSiteBinder, filterExpression, leftBlocksSize); // // toString method // generateToString( classDefinition, callSiteBinder, toStringHelper(classDefinition.getType().getJavaClassName()) .add("filter", filterExpression) .add("leftBlocksSize", leftBlocksSize) .toString()); return defineClass(classDefinition, InternalJoinFilterFunction.class, callSiteBinder.getBindings(), getClass().getClassLoader()); }
private static void generatePrepareFinal(ClassDefinition definition) { MethodDefinition method = definition.declareMethod( a(PUBLIC), "prepareFinal", type(void.class)); method.getBody().ret(); }
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(); }
private static void generateGetChannelCountMethod(ClassDefinition classDefinition, int outputChannelCount) { classDefinition.declareMethod( a(PUBLIC), "getChannelCount", type(int.class)) .getBody() .push(outputChannelCount) .retInt(); }
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 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 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 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 generateGroupedEvaluateFinal( ClassDefinition definition, List<FieldDefinition> stateFields, MethodHandle outputFunction, CallSiteBinder callSiteBinder) { Parameter groupId = arg("groupId", int.class); Parameter out = arg("out", BlockBuilder.class); MethodDefinition method = definition.declareMethod(a(PUBLIC), "evaluateFinal", type(void.class), groupId, out); BytecodeBlock body = method.getBody(); Variable thisVariable = method.getThis(); List<BytecodeExpression> states = new ArrayList<>(); for (FieldDefinition stateField : stateFields) { BytecodeExpression state = thisVariable.getField(stateField); body.append(state.invoke("setGroupId", void.class, groupId.cast(long.class))); states.add(state); } body.comment("output(state_0, state_1, ..., out)"); states.forEach(body::append); body.append(out); body.append(invoke(callSiteBinder.bind(outputFunction), "output")); body.ret(); }
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 static void generateHashRowMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes) { Parameter position = arg("position", int.class); Parameter page = arg("blocks", Page.class); MethodDefinition hashRowMethod = classDefinition.declareMethod(a(PUBLIC), "hashRow", type(long.class), position, page); Variable resultVariable = hashRowMethod.getScope().declareVariable(long.class, "result"); hashRowMethod.getBody().push(0L).putVariable(resultVariable); for (int index = 0; index < joinChannelTypes.size(); index++) { BytecodeExpression type = constantType(callSiteBinder, joinChannelTypes.get(index)); BytecodeExpression block = page.invoke("getBlock", Block.class, constantInt(index)); hashRowMethod .getBody() .getVariable(resultVariable) .push(31L) .append(OpCode.LMUL) .append(typeHashCode(type, block, position)) .append(OpCode.LADD) .putVariable(resultVariable); } hashRowMethod .getBody() .getVariable(resultVariable) .retLong(); }
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 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(); } }