private static void generatePrepareFinal(ClassDefinition definition) { MethodDefinition method = definition.declareMethod( a(PUBLIC), "prepareFinal", type(void.class)); method.getBody().ret(); }
private static <T> Class<? extends T> generateSingleStateClass(Class<T> clazz, Map<String, Type> fieldTypes, DynamicClassLoader classLoader) { ClassDefinition definition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName("Single" + clazz.getSimpleName()), type(Object.class), type(clazz)); FieldDefinition instanceSize = generateInstanceSize(definition); // Add getter for class size definition.declareMethod(a(PUBLIC), "getEstimatedSize", type(long.class)) .getBody() .getStaticField(instanceSize) .retLong(); // Generate constructor MethodDefinition constructor = definition.declareConstructor(a(PUBLIC)); constructor.getBody() .append(constructor.getThis()) .invokeConstructor(Object.class); // Generate fields List<StateField> fields = enumerateFields(clazz, fieldTypes); for (StateField field : fields) { generateField(definition, constructor, field); } constructor.getBody() .ret(); return defineClass(definition, clazz, classLoader); }
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(); }
@Override public void generateMethods(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, RowExpression filter, List<RowExpression> projections) { CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder); generateProcessMethod(classDefinition, projections.size()); Map<LambdaDefinitionExpression, CompiledLambda> filterCompiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, filter, "filter"); generateFilterMethod(classDefinition, callSiteBinder, cachedInstanceBinder, filterCompiledLambdaMap, filter); for (int i = 0; i < projections.size(); i++) { String methodName = "project_" + i; Map<LambdaDefinitionExpression, CompiledLambda> projectCompiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, projections.get(i), methodName); generateProjectMethod(classDefinition, callSiteBinder, cachedInstanceBinder, projectCompiledLambdaMap, methodName, projections.get(i)); } MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC)); BytecodeBlock constructorBody = constructorDefinition.getBody(); Variable thisVariable = constructorDefinition.getThis(); constructorBody.comment("super();") .append(thisVariable) .invokeConstructor(Object.class); cachedInstanceBinder.generateInitializations(thisVariable, constructorBody); constructorBody.ret(); }
private static void generateEvaluateFinal( ClassDefinition definition, List<FieldDefinition> stateFields, MethodHandle outputFunction, CallSiteBinder callSiteBinder) { Parameter out = arg("out", BlockBuilder.class); MethodDefinition method = definition.declareMethod( a(PUBLIC), "evaluateFinal", type(void.class), out); BytecodeBlock body = method.getBody(); Variable thisVariable = method.getThis(); List<BytecodeExpression> states = new ArrayList<>(); for (FieldDefinition stateField : stateFields) { BytecodeExpression state = thisVariable.getField(stateField); 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 generateEvaluateIntermediate(ClassDefinition definition, List<StateFieldAndDescriptor> stateFieldAndDescriptors) { Parameter out = arg("out", BlockBuilder.class); MethodDefinition method = definition.declareMethod( a(PUBLIC), "evaluateIntermediate", type(void.class), out); Variable thisVariable = method.getThis(); BytecodeBlock body = method.getBody(); if (stateFieldAndDescriptors.size() == 1) { BytecodeExpression stateSerializer = thisVariable.getField(getOnlyElement(stateFieldAndDescriptors).getStateSerializerField()); BytecodeExpression state = thisVariable.getField(getOnlyElement(stateFieldAndDescriptors).getStateField()); body.append(stateSerializer.invoke("serialize", void.class, state.cast(Object.class), out)) .ret(); } else { Variable rowBuilder = method.getScope().declareVariable(BlockBuilder.class, "rowBuilder"); body.append(rowBuilder.set(out.invoke("beginBlockEntry", BlockBuilder.class))); for (int i = 0; i < stateFieldAndDescriptors.size(); i++) { BytecodeExpression stateSerializer = thisVariable.getField(stateFieldAndDescriptors.get(i).getStateSerializerField()); BytecodeExpression state = thisVariable.getField(stateFieldAndDescriptors.get(i).getStateField()); body.append(stateSerializer.invoke("serialize", void.class, state.cast(Object.class), rowBuilder)); } body.append(out.invoke("closeEntry", BlockBuilder.class).pop()) .ret(); } }
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(); }
body.append(outputBlockVariable.set(thisVariable.getField(blockBuilder))) .append(compiler.compile(projection, scope, Optional.of(outputBlockVariable))) .ret(); return method;
private static void generateGroupedEvaluateIntermediate(ClassDefinition definition, List<StateFieldAndDescriptor> stateFieldAndDescriptors) { Parameter groupId = arg("groupId", int.class); Parameter out = arg("out", BlockBuilder.class); MethodDefinition method = definition.declareMethod(a(PUBLIC), "evaluateIntermediate", type(void.class), groupId, out); Variable thisVariable = method.getThis(); BytecodeBlock body = method.getBody(); if (stateFieldAndDescriptors.size() == 1) { BytecodeExpression stateSerializer = thisVariable.getField(getOnlyElement(stateFieldAndDescriptors).getStateSerializerField()); BytecodeExpression state = thisVariable.getField(getOnlyElement(stateFieldAndDescriptors).getStateField()); body.append(state.invoke("setGroupId", void.class, groupId.cast(long.class))) .append(stateSerializer.invoke("serialize", void.class, state.cast(Object.class), out)) .ret(); } else { Variable rowBuilder = method.getScope().declareVariable(BlockBuilder.class, "rowBuilder"); body.append(rowBuilder.set(out.invoke("beginBlockEntry", BlockBuilder.class))); for (int i = 0; i < stateFieldAndDescriptors.size(); i++) { BytecodeExpression stateSerializer = thisVariable.getField(stateFieldAndDescriptors.get(i).getStateSerializerField()); BytecodeExpression state = thisVariable.getField(stateFieldAndDescriptors.get(i).getStateField()); body.append(state.invoke("setGroupId", void.class, groupId.cast(long.class))) .append(stateSerializer.invoke("serialize", void.class, state.cast(Object.class), rowBuilder)); } body.append(out.invoke("closeEntry", BlockBuilder.class).pop()) .ret(); } }
@Inject public EmbedVersion(ServerConfig serverConfig) { ClassDefinition classDefinition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName(baseClassName(serverConfig)), type(Object.class), type(Runnable.class)); FieldDefinition field = classDefinition.declareField(a(PRIVATE), "runnable", Runnable.class); Parameter parameter = arg("runnable", type(Runnable.class)); MethodDefinition constructor = classDefinition.declareConstructor(a(PUBLIC), parameter); constructor.getBody() .comment("super(runnable);") .append(constructor.getThis()) .invokeConstructor(Object.class) .append(constructor.getThis()) .append(parameter) .putField(field) .ret(); MethodDefinition run = classDefinition.declareMethod(a(PUBLIC), "run", type(void.class)); run.getBody() .comment("runnable.run();") .append(run.getThis()) .getField(field) .invokeInterface(Runnable.class, "run", void.class) .ret(); Class<? extends Runnable> generatedClass = defineClass(classDefinition, Runnable.class, ImmutableMap.of(), getClass().getClassLoader()); this.runnableConstructor = constructorMethodHandle(generatedClass, Runnable.class); }
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(); }
.invokeInterface(Type.class, "appendTo", void.class, Block.class, int.class, BlockBuilder.class); appendToBody.ret();
private static CompiledLambda defineLambdaMethod( RowExpressionCompiler innerExpressionCompiler, ClassDefinition classDefinition, String methodName, List<Parameter> inputParameters, LambdaDefinitionExpression lambda) { checkCondition(inputParameters.size() <= 254, NOT_SUPPORTED, "Too many arguments for lambda expression"); Class<?> returnType = Primitives.wrap(lambda.getBody().getType().getJavaType()); MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(returnType), inputParameters); Scope scope = method.getScope(); Variable wasNull = scope.declareVariable(boolean.class, "wasNull"); BytecodeNode compiledBody = innerExpressionCompiler.compile(lambda.getBody(), scope, Optional.empty()); method.getBody() .putVariable(wasNull, false) .append(compiledBody) .append(boxPrimitiveIfNecessary(scope, returnType)) .ret(returnType); Handle lambdaAsmHandle = new Handle( Opcodes.H_INVOKEVIRTUAL, method.getThis().getType().getClassName(), method.getName(), method.getMethodDescriptor(), false); return new CompiledLambda( lambdaAsmHandle, method.getReturnType(), method.getParameterTypes()); }
private void generateProjectMethod( ClassDefinition classDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap, String methodName, RowExpression projection) { Parameter session = arg("session", ConnectorSession.class); Parameter cursor = arg("cursor", RecordCursor.class); Parameter output = arg("output", BlockBuilder.class); MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(void.class), session, cursor, output); method.comment("Projection: %s", projection.toString()); Scope scope = method.getScope(); Variable wasNullVariable = scope.declareVariable(type(boolean.class), "wasNull"); RowExpressionCompiler compiler = new RowExpressionCompiler( callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cursor), metadata.getFunctionRegistry(), compiledLambdaMap); method.getBody() .comment("boolean wasNull = false;") .putVariable(wasNullVariable, false) .comment("evaluate projection: " + projection.toString()) .append(compiler.compile(projection, scope, Optional.of(output))) .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 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(); } }
private void generateCombineMethod(ClassDefinition definition, CallSiteBinder binder, MethodHandle compareMethod, Type keyType, Type valueType, Class<?> stateClass) { Parameter state = arg("state", stateClass); Parameter otherState = arg("otherState", stateClass); MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "combine", type(void.class), state, otherState); Class<?> keyJavaType = keyType.getJavaType(); BytecodeBlock ifBlock = new BytecodeBlock() .append(state.invoke("setFirst", void.class, otherState.invoke("getFirst", keyJavaType))) .append(state.invoke("setFirstNull", void.class, otherState.invoke("isFirstNull", boolean.class))) .append(state.invoke("setSecondNull", void.class, otherState.invoke("isSecondNull", boolean.class))); if (valueType.getJavaType().isPrimitive()) { ifBlock.append(state.invoke("setSecond", void.class, otherState.invoke("getSecond", valueType.getJavaType()))); } else { ifBlock.append(new BytecodeBlock() .append(state.invoke("setSecondBlock", void.class, otherState.invoke("getSecondBlock", Block.class))) .append(state.invoke("setSecondPosition", void.class, otherState.invoke("getSecondPosition", int.class)))); } method.getBody() .append(new IfStatement() .condition(or( state.invoke("isFirstNull", boolean.class), and( not(otherState.invoke("isFirstNull", boolean.class)), loadConstant(binder, compareMethod, MethodHandle.class).invoke("invokeExact", boolean.class, otherState.invoke("getFirst", keyJavaType), state.invoke("getFirst", keyJavaType))))) .ifTrue(ifBlock)) .ret(); }
private static FieldDefinition generateGroupedField(ClassDefinition definition, MethodDefinition constructor, MethodDefinition ensureCapacity, StateField stateField) { Class<?> bigArrayType = getBigArrayType(stateField.getType()); FieldDefinition field = definition.declareField(a(PRIVATE), UPPER_CAMEL.to(LOWER_CAMEL, stateField.getName()) + "Values", bigArrayType); // Generate getter MethodDefinition getter = definition.declareMethod(a(PUBLIC), stateField.getGetterName(), type(stateField.getType())); getter.getBody() .append(getter.getThis().getField(field).invoke( "get", stateField.getType(), getter.getThis().invoke("getGroupId", long.class)) .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().getField(field).invoke( "set", void.class, setter.getThis().invoke("getGroupId", long.class), value)) .ret(); Scope ensureCapacityScope = ensureCapacity.getScope(); ensureCapacity.getBody() .append(ensureCapacity.getThis().getField(field).invoke("ensureCapacity", void.class, ensureCapacityScope.getVariable("size"))); // Initialize field in constructor constructor.getBody() .append(constructor.getThis().setField(field, newInstance(field.getType(), stateField.initialValueExpression()))); return field; }
loadConstant(binder, compareMethod, MethodHandle.class).invoke("invokeExact", boolean.class, keySqlType.getValue(key, position), state.invoke("getFirst", keyType.getJavaType()))))) .ifTrue(ifBlock)) .ret();