This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch ignite-13618-javapoet
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit b3223bfd05fb9d9fa48098d823df787d8d10212a
Author: Andrew Mashenkov <andrey.mashen...@gmail.com>
AuthorDate: Sat Dec 12 22:19:31 2020 +0300

    wip.
    rewrite codegen with javapoet
---
 modules/commons/pom.xml                            |   7 +-
 .../internal/schema/marshaller/MarshallerUtil.java |  11 +-
 .../IdentityObjectMarshallerExprGenerator.java     |  22 +-
 .../generator/JaninoSerializerGenerator.java       | 289 ++++++++++++++++++---
 .../generator/MarshallerExprGenerator.java         |  28 +-
 .../marshaller/generator/TupleAccessorExpr.java    | 158 +++++++++++
 .../marshaller/reflection/FieldAccessor.java       |   4 +-
 .../apache/ignite/internal/util/ObjectFactory.java |  26 +-
 pom.xml                                            |   1 +
 9 files changed, 485 insertions(+), 61 deletions(-)

diff --git a/modules/commons/pom.xml b/modules/commons/pom.xml
index 05a2fff..a5b64e8 100644
--- a/modules/commons/pom.xml
+++ b/modules/commons/pom.xml
@@ -43,12 +43,11 @@
             <version>${jetbrains.annotations.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.janino</groupId>
-            <artifactId>janino</artifactId>
-            <version>${janino.version}</version>
+            <groupId>com.squareup</groupId>
+            <artifactId>javapoet</artifactId>
+            <version>${javapoet.version}</version>
         </dependency>
 
-
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.junit.jupiter</groupId>
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
index c111ba8..f43f9b5 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/MarshallerUtil.java
@@ -21,6 +21,7 @@ import java.util.BitSet;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.schema.TupleAssembler;
+import org.apache.ignite.internal.util.ObjectFactory;
 
 /**
  * Marshaller utility class.
@@ -96,8 +97,16 @@ public final class MarshallerUtil {
         return null;
     }
 
+    public static  <T> ObjectFactory<T> factoryForClass(Class<T> type) {
+        if (mode(type) == null)
+            return new ObjectFactory<>(type);
+        else
+            return null;
+    }
+
     /**
      * Stub.
      */
-    private MarshallerUtil() {}
+    private MarshallerUtil() {
+    }
 }
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
index e574e61..f86bc0b 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.schema.marshaller.generator;
 
+import com.squareup.javapoet.CodeBlock;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 
 /**
@@ -27,9 +28,16 @@ class IdentityObjectMarshallerExprGenerator extends 
MarshallerExprGenerator {
      * Constructor.
      *
      * @param accessor Object field access expression generators.
+     * @param tupleAccessorGen
      */
-    IdentityObjectMarshallerExprGenerator(FieldAccessExprGenerator accessor) {
-        super(null /* no instantiation needed */, new 
FieldAccessExprGenerator[] {accessor});
+    IdentityObjectMarshallerExprGenerator(FieldAccessExprGenerator accessor,
+        TupleAccessorExpr tupleAccessorGen) {
+        super(
+            null /* no instantiation needed */,
+            new FieldAccessExprGenerator[] {accessor},
+            new TupleAccessorExpr[] {tupleAccessorGen}
+        );
+
     }
 
     /** {@inheritDoc} */
@@ -42,4 +50,14 @@ class IdentityObjectMarshallerExprGenerator extends 
MarshallerExprGenerator {
     @Override public void appendUnmarshallObjectExpr(StringBuilder sb, String 
indent) {
         sb.append(indent).append("Object obj = 
").append(accessors[0].readColumnExpr()).append(";" + 
JaninoSerializerGenerator.LF);
     }
+
+    @Override public CodeBlock unmarshallObjectCode(String tupleExpr) {
+        return CodeBlock.builder()
+            .add("return ").addStatement(tupleAccessors[0].read(tupleExpr))
+            .build();
+    }
+
+    @Override public CodeBlock marshallObjectCode(String asm, String objVar) {
+        return tupleAccessors[0].write(asm, objVar);
+    }
 }
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
index 654bf97..a45a8be 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/JaninoSerializerGenerator.java
@@ -17,23 +17,53 @@
 
 package org.apache.ignite.internal.schema.marshaller.generator;
 
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ArrayTypeName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import java.lang.invoke.VarHandle;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
+import java.util.HashMap;
+import javax.annotation.processing.Generated;
+import javax.lang.model.element.Modifier;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.ToolProvider;
+import org.apache.ignite.internal.schema.ByteBufferTuple;
 import org.apache.ignite.internal.schema.Columns;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.schema.Tuple;
+import org.apache.ignite.internal.schema.TupleAssembler;
 import org.apache.ignite.internal.schema.marshaller.BinaryMode;
 import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
+import org.apache.ignite.internal.schema.marshaller.SerializationException;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 import org.apache.ignite.internal.schema.marshaller.SerializerFactory;
-import org.apache.ignite.internal.util.IgniteUnsafeUtils;
-import org.codehaus.commons.compiler.CompilerFactoryFactory;
+import org.apache.ignite.internal.util.ObjectFactory;
 import org.codehaus.commons.compiler.IClassBodyEvaluator;
+import org.codehaus.janino.ClassLoaderIClassLoader;
+import org.codehaus.janino.Compiler;
+import org.codehaus.janino.util.ResourceFinderClassLoader;
+import org.codehaus.janino.util.resource.MapResourceCreator;
+import org.codehaus.janino.util.resource.MapResourceFinder;
+import org.codehaus.janino.util.resource.Resource;
+import org.codehaus.janino.util.resource.StringResource;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * {@link Serializer} code generator backed with Janino.
  */
 public class JaninoSerializerGenerator implements SerializerFactory {
+
+    public static final String SERIALIZER_PACKAGE_NAME = 
"org.apache.ignite.internal.schema.marshaller";
+
+    public static final String SERIALIZER_CLASS_NAME_PREFIX = 
"JaninoSerializerForSchema_";
+
     /** Tabulate. */
     static final String TAB = "    ";
 
@@ -52,38 +82,106 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
         Class<?> keyClass,
         Class<?> valClass
     ) {
-        try {
-            final IClassBodyEvaluator ce = 
CompilerFactoryFactory.getDefaultCompilerFactory().newClassBodyEvaluator();
+        // Generate Serializer code.
+        final String className = SERIALIZER_CLASS_NAME_PREFIX + 
schema.version();
 
-            // Generate Serializer code.
-            String code = generateSerializerClassCode(ce, schema, keyClass, 
valClass);
+        String code = generateSerializerClassCode(className, schema, keyClass, 
valClass);
 
-            //TODO: pass code to logger on trace level.
+        //TODO: pass code to logger on trace level.
 
-            if (enabledDebug) {
-                ce.setDebuggingInformation(true, true, true);
+        final HashMap<String, byte[]> classes = new HashMap<>();
+        final Compiler cmp = new Compiler(
+            new MapResourceFinder(classes),
+            new ClassLoaderIClassLoader(getClass().getClassLoader())
+        );
 
-                //TODO: dump code to log.
-//                System.out.println(code);
-            }
+        cmp.setClassFileCreator(new MapResourceCreator(classes));
 
-            try {  // Compile and load class.
-                ce.setParentClassLoader(getClass().getClassLoader());
-                ce.cook(code);
+        if (enabledDebug) {
+            cmp.setDebugSource(true);
+            cmp.setDebugLines(true);
+            cmp.setDebugVars(true);
+            cmp.setVerbose(true);
 
-                // Create and return Serializer instance.
-                final Constructor<Serializer> ctor = 
(Constructor<Serializer>)ce.getClazz()
-                    .getDeclaredConstructor(schema.getClass(), Class.class, 
Class.class);
+            System.out.print(code);
+        }
 
-                return ctor.newInstance(schema, keyClass, valClass);
-            }
-            catch (Exception ex) {
-                if (enabledDebug)
-                    throw new IllegalStateException("Failed to 
compile/instantiate generated Serializer: code=" +
-                        LF + code + LF, ex);
-                else
-                    throw new IllegalStateException("Failed to 
compile/instantiate generated Serializer.", ex);
-            }
+        try {  // Compile code.
+            cmp.compile(new Resource[] {
+                new StringResource("file", code)});
+
+            ClassLoader cl = new ResourceFinderClassLoader(
+                new MapResourceFinder(classes),
+                getClass().getClassLoader()
+            );
+
+            // Load class and create instance.
+            final Class<?> aClass = cl.loadClass(SERIALIZER_PACKAGE_NAME + '.' 
+ className);
+
+            final Constructor<Serializer> ctor = 
(Constructor<Serializer>)aClass
+                .getDeclaredConstructor(schema.getClass(), Class.class, 
Class.class);
+
+            return ctor.newInstance(schema, keyClass, valClass);
+        }
+        catch (Throwable ex) {
+            if (enabledDebug)
+                throw new IllegalStateException("Failed to compile generated 
Serializer code:\n" + code, ex);
+            else
+                throw new IllegalStateException("Failed to compile/instantiate 
generated Serializer.", ex);
+        }
+    }
+
+    /**
+     * Generates serializer code.
+     *
+     * @param className Serializer class name.
+     * @param valClass Value class.
+     * @return Generated class code.
+     */
+    private String generateSerializerClassCode(String className, 
SchemaDescriptor schema, Class<?> keyClass,
+        Class<?> valClass) {
+        try {
+            final StringBuilder sb = new StringBuilder();
+
+            // Build field accessor generators.
+            final MarshallerExprGenerator keyMarsh = 
createObjectMarshaller(valClass, "valFactory", schema.valueColumns(), 
schema.keyColumns().length());
+            final MarshallerExprGenerator valMarsh = 
createObjectMarshaller(valClass, "valFactory", schema.valueColumns(), 
schema.keyColumns().length());
+
+            JavaFile
+                .builder(
+                    SERIALIZER_PACKAGE_NAME,
+                    TypeSpec.classBuilder(className)
+                        .addSuperinterface(Serializer.class)
+                        .addModifiers(Modifier.PUBLIC)
+                        
.addAnnotation(AnnotationSpec.builder(Generated.class).addMember("value", 
getClass().getCanonicalName()).build())
+                        .addField(SchemaDescriptor.class, "schema", 
Modifier.PRIVATE, Modifier.FINAL)
+                        .addField(ObjectFactory.class, "keyFactory", 
Modifier.PRIVATE, Modifier.FINAL)
+                        .addField(ObjectFactory.class, "valFactory", 
Modifier.PRIVATE, Modifier.FINAL)
+                        .addField(ArrayTypeName.of(VarHandle.class), 
"fieldAccessors", Modifier.PRIVATE, Modifier.FINAL)
+                        .addMethod(
+                            MethodSpec.constructorBuilder()
+                                .addModifiers(Modifier.PUBLIC)
+                                .addParameter(SchemaDescriptor.class, "schema")
+                                .addParameter(Class.class, "keyClass")
+                                .addParameter(Class.class, "valClass")
+                                .addStatement("this.schema = schema")
+                                .addStatement("this.keyFactory = 
$T.factoryForClass(keyClass)", MarshallerUtil.class)
+                                .addStatement("this.valFactory = 
$T.factoryForClass(keyClass)", MarshallerUtil.class)
+                                .addStatement("this.fieldAccessors = null")
+                                .build()
+                        )
+                        .addMethod(generateHelpersMetod(schema))
+                        .addMethod(generateSerializeMethod(keyMarsh, valMarsh))
+                        .addMethod(generateDeserializeKeyMethod(keyMarsh))
+                        .addMethod(generateDeserializeValueMethod())
+                        .build()
+                )
+                .skipJavaLangImports(true)
+                .indent(TAB)
+                .build()
+                .writeTo(sb);
+
+            return sb.toString();
         }
         catch (Exception ex) {
             //TODO: fallback to java serializer?
@@ -91,6 +189,128 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
         }
     }
 
+    private MethodSpec generateHelpersMetod(SchemaDescriptor schema) {
+        final MethodSpec.Builder builder = MethodSpec
+            .methodBuilder("createAssembler")
+            .addModifiers(Modifier.PRIVATE)
+            .addParameter(Object.class, "key")
+            .addParameter(Object.class, "val")
+            .returns(TupleAssembler.class)
+
+            .addStatement("int nonNullVarlenKeys = 0; int nonNullVarlenValues 
= 0")
+            .addStatement("int nonNullVarlenKeysSize = 0; int 
nonNullVarlenValuesSize = 0")
+            .addStatement("$T keyCols = schema.keyColumns()", Columns.class)
+            .addStatement("$T valCols = schema.valueColumns()", Columns.class);
+
+        Columns keyCols = schema.keyColumns();
+        if (keyCols.firstVarlengthColumn() >= 0) {
+            final CodeBlock.Builder block = CodeBlock.builder().indent()
+                .addStatement("$T fVal", Object.class);// Temporary vars.
+
+            for (int i = keyCols.firstVarlengthColumn(); i < keyCols.length(); 
i++) {
+                assert !keyCols.column(i).type().spec().fixedLength();
+
+                block.addStatement("assert 
!keyCols.column($L).type().spec().fixedLength()", i)
+                    .addStatement("fVal = fieldAccessors[$L].get(key)", i)
+                    .beginControlFlow("if (fVal != null)")
+                    .addStatement("nonNullVarlenKeysSize += 
$T.getValueSize(fVal, keyCols.column($L).type())", MarshallerUtil.class, i)
+                    .addStatement("nonNullVarlenKeys++")
+                    .endControlFlow();
+            }
+            block.unindent();
+
+            builder
+                .addCode("{\n")
+                .addCode(block.build())
+                .addCode("}\n");
+        }
+
+        Columns valCols = schema.keyColumns();
+        if (valCols.firstVarlengthColumn() >= 0) {
+            final CodeBlock.Builder block = CodeBlock.builder().indent()
+                .addStatement("$T fVal", Object.class);// Temporary vars.
+
+            for (int i = valCols.firstVarlengthColumn(); i < valCols.length(); 
i++) {
+                assert !valCols.column(i).type().spec().fixedLength();
+
+                block.addStatement("assert 
!valCols.column($L).type().spec().fixedLength()", i)
+                    .addStatement("fVal = fieldAccessors[$L].get(val)", i + 
schema.keyColumns().length())
+                    .beginControlFlow("if (fVal != null)")
+                    .addStatement("nonNullVarlenValuesSize += 
$T.getValueSize(fVal, valCols.column($L).type())", MarshallerUtil.class, i)
+                    .addStatement("nonNullVarlenValues++")
+                    .endControlFlow();
+            }
+            block.unindent();
+
+            builder
+                .addCode("{\n")
+                .addCode(block.build())
+                .addCode("}\n");
+        }
+
+        builder.addStatement("int size = $T.tupleSize(keyCols, 
nonNullVarlenKeys, nonNullVarlenKeysSize," +
+            "valCols, nonNullVarlenValues, nonNullVarlenValuesSize)", 
TupleAssembler.class);
+
+        builder.addStatement("return new $T(schema, size, nonNullVarlenKeys, 
nonNullVarlenValues)", TupleAssembler.class);
+
+        return builder.build();
+    }
+
+    @NotNull private MethodSpec generateDeserializeValueMethod() {
+        return MethodSpec
+            .methodBuilder("deserializeValue")
+            .addAnnotation(Override.class)
+            .addModifiers(Modifier.PUBLIC)
+            .addParameter(ArrayTypeName.of(TypeName.BYTE), "data")
+            .addException(SerializationException.class)
+            .returns(TypeName.OBJECT)
+            .addStatement("return null")
+            .build();
+    }
+
+    @NotNull private MethodSpec 
generateDeserializeKeyMethod(MarshallerExprGenerator keyMarsh) {
+        final MethodSpec.Builder builder = MethodSpec
+            .methodBuilder("deserializeKey")
+            .addAnnotation(Override.class)
+            .addModifiers(Modifier.PUBLIC)
+            .addParameter(ArrayTypeName.of(TypeName.BYTE), "data")
+            .addException(SerializationException.class)
+            .returns(TypeName.OBJECT)
+
+            .beginControlFlow("try")
+            .addStatement("$T tuple = new $T(schema, data)", Tuple.class, 
ByteBufferTuple.class)
+            .addCode(keyMarsh.unmarshallObjectCode("tuple"))
+
+            .nextControlFlow("catch($T th)", Throwable.class)
+            .addStatement("throw new $T(th)", SerializationException.class)
+            .endControlFlow();
+
+        return builder.build();
+    }
+
+    @NotNull
+    private MethodSpec generateSerializeMethod(MarshallerExprGenerator 
keyMarsh, MarshallerExprGenerator valMarsh) {
+        return MethodSpec.
+            methodBuilder("serialize")
+            .addAnnotation(Override.class)
+            .addModifiers(Modifier.PUBLIC)
+            .addParameter(TypeName.OBJECT, "key")
+            .addParameter(TypeName.OBJECT, "val")
+            .addException(SerializationException.class)
+            .returns(ArrayTypeName.of(TypeName.BYTE.unbox()))
+
+            .beginControlFlow("try")
+            .addStatement("$T asm = createAssembler(key, val)", 
TupleAssembler.class)
+            .addCode(keyMarsh.marshallObjectCode("asm", "key"))
+            .addCode(valMarsh.marshallObjectCode("asm", "val"))
+            .addStatement("return asm.build()")
+
+            .nextControlFlow("catch($T th)", Throwable.class)
+            .addStatement("throw new $T(th)", SerializationException.class)
+            .endControlFlow()
+            .build();
+    }
+
     /**
      * Generates serializer code.
      *
@@ -106,11 +326,10 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
         Class<?> keyClass,
         Class<?> valClass
     ) {
-        final String packageName = 
"org.apache.ignite.internal.schema.marshaller.";
-        final String className = "JaninoSerializerForSchema_" + 
schema.version();
+        final String className = SERIALIZER_CLASS_NAME_PREFIX + 
schema.version();
 
         // Prerequisites.
-        ce.setClassName(packageName + className);
+        ce.setClassName(SERIALIZER_PACKAGE_NAME + className);
         ce.setImplementedInterfaces(new Class[] {Serializer.class});
         ce.setDefaultImports(
             "java.util.UUID",
@@ -178,9 +397,13 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
         BinaryMode mode = MarshallerUtil.mode(aClass);
 
         if (mode != null)
-            return new 
IdentityObjectMarshallerExprGenerator(FieldAccessExprGenerator.createIdentityAccessor(mode,
 firstColIdx));
+            return new IdentityObjectMarshallerExprGenerator(
+                FieldAccessExprGenerator.createIdentityAccessor(mode, 
firstColIdx),
+                TupleAccessorExpr.createAccessor(mode, firstColIdx)
+            );
 
         FieldAccessExprGenerator[] accessors = new 
FieldAccessExprGenerator[columns.length()];
+        TupleAccessorExpr[] tupleAccessorExprs = new TupleAccessorExpr[] {};
         try {
             for (int i = 0; i < columns.length(); i++) {
                 final Field field = 
aClass.getDeclaredField(columns.column(i).name());
@@ -188,14 +411,14 @@ public class JaninoSerializerGenerator implements 
SerializerFactory {
                 accessors[i] = FieldAccessExprGenerator.createAccessor(
                     MarshallerUtil.mode(field.getType()),
                     firstColIdx + i /* schma absolute index. */,
-                    IgniteUnsafeUtils.objectFieldOffset(field));
+                    0L);//   IgniteUnsafeUtils.objectFieldOffset(field));
             }
         }
         catch (NoSuchFieldException ex) {
             throw new IllegalStateException(ex);
         }
 
-        return new MarshallerExprGenerator(factoryRefExpr, accessors);
+        return new MarshallerExprGenerator(factoryRefExpr, accessors, 
tupleAccessorExprs);
     }
 
     /**
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java
index 433b567..8087e2c 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerExprGenerator.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.schema.marshaller.generator;
 
+import com.squareup.javapoet.CodeBlock;
+import java.lang.invoke.VarHandle;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 
 /**
@@ -28,6 +30,7 @@ class MarshallerExprGenerator {
 
     /** Object field access expression generators. */
     protected FieldAccessExprGenerator[] accessors;
+    protected TupleAccessorExpr[] tupleAccessors;
 
     /**
      * Constructor.
@@ -35,9 +38,11 @@ class MarshallerExprGenerator {
      * @param factoryRefExpr Object factory regerence expression.
      * @param accessors Object field access expression generators.
      */
-    public MarshallerExprGenerator(String factoryRefExpr, 
FieldAccessExprGenerator[] accessors) {
+    public MarshallerExprGenerator(String factoryRefExpr, 
FieldAccessExprGenerator[] accessors,
+        TupleAccessorExpr[] tupleAccessors) {
         this.accessors = accessors;
         this.factoryRefExpr = factoryRefExpr;
+        this.tupleAccessors = tupleAccessors;
     }
 
     /**
@@ -91,4 +96,25 @@ class MarshallerExprGenerator {
         sb.append(indent).append(JaninoSerializerGenerator.TAB + "throw new 
SerializationException(ex);").append(JaninoSerializerGenerator.LF);
         sb.append(indent).append("}" + JaninoSerializerGenerator.LF);
     }
+
+    public CodeBlock unmarshallObjectCode(String tupleExpr) {
+        final CodeBlock.Builder builder = CodeBlock.builder()
+            .add("Object obj = 
").add(factoryRefExpr).addStatement(".create()");
+
+        for (int i = 0; i < tupleAccessors.length; i++) {
+            builder.addStatement("fieldAccessor[$L].set(obj, $L)", i, 
tupleAccessors[i].read(tupleExpr).toString());
+        }
+
+            builder.addStatement("return obj");
+        return builder.build();
+    }
+
+    public CodeBlock marshallObjectCode(String asm, String objVar) {
+        final CodeBlock.Builder builder = CodeBlock.builder();
+
+        for (int i = 0; i < tupleAccessors.length; i++)
+            builder.addStatement(tupleAccessors[i].write(asm, 
CodeBlock.of("fieldAccessor[$L].get($L)", i, objVar).toString()));
+
+        return builder.build();
+    }
 }
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleAccessorExpr.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleAccessorExpr.java
new file mode 100644
index 0000000..e1b782d
--- /dev/null
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleAccessorExpr.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.schema.marshaller.generator;
+
+import com.squareup.javapoet.CodeBlock;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import org.apache.ignite.internal.schema.Tuple;
+import org.apache.ignite.internal.schema.TupleAssembler;
+import org.apache.ignite.internal.schema.marshaller.BinaryMode;
+
+/**
+ * Object field access expression generators.
+ */
+public class TupleAccessorExpr {
+    public static final MethodHandle BYTE_READ;
+    public static final MethodHandle SHORT_READ;
+    public static final MethodHandle INT_READ;
+    public static final MethodHandle LONG_READ;
+    public static final MethodHandle FLOAT_READ;
+    public static final MethodHandle DOUBLE_READ;
+    public static final MethodHandle BYTE_BOXED_READ;
+    public static final MethodHandle SHORT_BOXED_READ;
+    public static final MethodHandle INT_BOXED_READ;
+    public static final MethodHandle LONG_BOXED_READ;
+    public static final MethodHandle FLOAT_BOXED_READ;
+    public static final MethodHandle DOUBLE_BOXED_READ;
+
+    public static final MethodHandle BYTE_WRITE;
+    public static final MethodHandle SHORT_WRITE;
+    public static final MethodHandle INT_WRITE;
+    public static final MethodHandle LONG_WRITE;
+    public static final MethodHandle FLOAT_WRITE;
+    public static final MethodHandle DOUBLE_WRITE;
+    public static final MethodHandle NULL_WRITE;
+
+    static {
+        try {
+            MethodHandles.Lookup lookup = 
MethodHandles.privateLookupIn(Tuple.class,MethodHandles.lookup());
+
+            BYTE_READ = lookup.findVirtual(Tuple.class, "byteValue", 
MethodType.methodType(byte.class, int.class));
+            SHORT_READ = lookup.findVirtual(Tuple.class, "shortValue", 
MethodType.methodType(short.class, int.class));
+            INT_READ = lookup.findVirtual(Tuple.class, "intValue", 
MethodType.methodType(int.class, int.class));
+            LONG_READ = lookup.findVirtual(Tuple.class, "longValue", 
MethodType.methodType(long.class, int.class));
+            FLOAT_READ = lookup.findVirtual(Tuple.class, "floatValue", 
MethodType.methodType(float.class, int.class));
+            DOUBLE_READ = lookup.findVirtual(Tuple.class, "doubleValue", 
MethodType.methodType(double.class, int.class));
+            BYTE_BOXED_READ = lookup.findVirtual(Tuple.class, 
"byteValueBoxed", MethodType.methodType(Byte.class, int.class));
+            SHORT_BOXED_READ = lookup.findVirtual(Tuple.class, 
"shortValueBoxed", MethodType.methodType(Short.class, int.class));
+            INT_BOXED_READ = lookup.findVirtual(Tuple.class, "intValueBoxed", 
MethodType.methodType(Integer.class, int.class));
+            LONG_BOXED_READ = lookup.findVirtual(Tuple.class, 
"longValueBoxed", MethodType.methodType(Long.class, int.class));
+            FLOAT_BOXED_READ = lookup.findVirtual(Tuple.class, 
"floatValueBoxed", MethodType.methodType(Float.class, int.class));
+            DOUBLE_BOXED_READ = lookup.findVirtual(Tuple.class, 
"doubleValueBoxed", MethodType.methodType(Double.class, int.class));
+
+            lookup = 
MethodHandles.privateLookupIn(TupleAssembler.class,MethodHandles.lookup());
+            NULL_WRITE = lookup.findVirtual(TupleAssembler.class, 
"appendNull", MethodType.methodType(void.class));
+            BYTE_WRITE = lookup.findVirtual(TupleAssembler.class, 
"appendByte", MethodType.methodType(void.class, byte.class));
+            SHORT_WRITE = lookup.findVirtual(TupleAssembler.class, 
"appendShort", MethodType.methodType(void.class, short.class));
+            INT_WRITE = lookup.findVirtual(TupleAssembler.class, "appendInt", 
MethodType.methodType(void.class, int.class));
+            LONG_WRITE = lookup.findVirtual(TupleAssembler.class, 
"appendLong", MethodType.methodType(void.class, long.class));
+            FLOAT_WRITE = lookup.findVirtual(TupleAssembler.class, 
"appendFloat", MethodType.methodType(void.class, float.class));
+            DOUBLE_WRITE = lookup.findVirtual(TupleAssembler.class, 
"appendDouble", MethodType.methodType(void.class, double.class));
+        }
+        catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        }
+
+    }
+
+    private final Class<?> rType;
+
+    static TupleAccessorExpr createAccessor(BinaryMode mode, int colIdx) {
+        switch (mode) {
+            case P_BYTE:
+                return new TupleAccessorExpr("BYTE_READ", "BYTE_WRITE", 
byte.class, colIdx);
+            case P_SHORT:
+                break;
+            case P_INT:
+                break;
+            case P_LONG:
+                break;
+            case P_FLOAT:
+                break;
+            case P_DOUBLE:
+                break;
+            case BYTE:
+                return new TupleAccessorExpr("BYTE_BOXED_READ", "BYTE_WRITE", 
Byte.class, colIdx);
+            case SHORT:
+                break;
+            case INT:
+                break;
+            case LONG:
+                break;
+            case FLOAT:
+                break;
+            case DOUBLE:
+                break;
+            case STRING:
+                break;
+            case UUID:
+                break;
+            case BYTE_ARR:
+                break;
+            case BITSET:
+                break;
+        }
+
+        throw new IllegalStateException("Unsupported binary mode: " + mode);
+    }
+
+    private final String readExpr;
+    private final String writeExpr;
+    private final int colIdx;
+
+    private TupleAccessorExpr(String readExpr, String writeExpr, Class<?> 
rType, int colIdx) {
+        this.readExpr = readExpr;
+        this.writeExpr = writeExpr;
+        this.colIdx = colIdx;
+        this.rType = rType;
+    }
+
+    public CodeBlock read(String tuple) {
+        return CodeBlock.of("($T)$T.$L.invoke($L, $L)", rType, 
TupleAccessorExpr.class, readExpr, tuple, colIdx);
+    }
+
+    public CodeBlock write(String asmVar, String valExpr) {
+        if (rType.isPrimitive())
+            return CodeBlock.of("$T.$L.invoke($L, $L)", 
TupleAccessorExpr.class, writeExpr, asmVar, valExpr);
+        else {
+            return CodeBlock.builder()
+                .add("{\n").indent()
+                .addStatement("$T fVal", rType)
+                .beginControlFlow("if((fVal = ($T)$L) == null)", rType, 
valExpr)
+                .addStatement("$T.NULL_WRITE.invokeExact($L)", 
TupleAccessorExpr.class, asmVar)
+                .nextControlFlow("else")
+                .addStatement("$T.$L.invoke($L, fVal)", 
TupleAccessorExpr.class, writeExpr, asmVar)
+                .endControlFlow()
+                .unindent()
+                .add("}\n")
+                .build();
+        }
+    }
+}
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
index 97ea038..812b02e 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/reflection/FieldAccessor.java
@@ -478,9 +478,7 @@ public abstract class FieldAccessor {
             assert obj != null;
             assert writer != null;
 
-            Object val;
-
-            val = varHandle.get(obj);
+            Object val = varHandle.get(obj);
 
             if (val == null) {
                 writer.appendNull();
diff --git 
a/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java
 
b/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java
index f31965f..b888955 100644
--- 
a/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java
+++ 
b/modules/commons/src/main/java/org/apache/ignite/internal/util/ObjectFactory.java
@@ -17,15 +17,16 @@
 
 package org.apache.ignite.internal.util;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 
 /**
  * Object factory.
  */
 public class ObjectFactory<T> implements Factory<T> {
     /** Class default constructor. */
-    private final Constructor<T> cnstr;
+    private final MethodHandle constr;
 
     /**
      * Constructor.
@@ -34,11 +35,9 @@ public class ObjectFactory<T> implements Factory<T> {
      */
     public ObjectFactory(Class<T> tClass) {
         try {
-            cnstr = tClass.getDeclaredConstructor();
-
-            cnstr.setAccessible(true);
+            constr = MethodHandles.privateLookupIn(tClass, 
MethodHandles.lookup()).findConstructor(tClass, 
MethodType.methodType(void.class));
         }
-        catch (NoSuchMethodException e) {
+        catch (NoSuchMethodException | IllegalAccessException e) {
             throw new IllegalStateException("Class has no default constructor: 
class=" + tClass.getName(), e);
         }
     }
@@ -46,17 +45,10 @@ public class ObjectFactory<T> implements Factory<T> {
     /** {@inheritDoc} */
     @Override public T create() throws IllegalStateException {
         try {
-            return cnstr.newInstance();
+            return (T)constr.invoke();
         }
-        catch (IllegalAccessException | InvocationTargetException | 
InstantiationException e) {
-            throw new IllegalStateException("Failed to instantiate class: " + 
cnstr.getDeclaringClass().getName(), e);
+        catch (Throwable e) {
+            throw new IllegalStateException("Failed to instantiate class: " + 
constr.type().returnType(), e);
         }
     }
-
-    /**
-     * @return Class of object created by the factory.
-     */
-    public Class<T> getClazz() {
-        return cnstr.getDeclaringClass();
-    }
 }
diff --git a/pom.xml b/pom.xml
index 7d1a734..0ad6c7c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,7 @@
 
         <!-- Dependencies versions. -->
         <janino.version>3.0.11</janino.version>
+        <javapoet.version>1.13.0</javapoet.version>
         <javax.annotation.api.version>1.3.2</javax.annotation.api.version>
         <jetbrains.annotations.version>20.1.0</jetbrains.annotations.version>
         <jmh.framework.verion>1.9.3</jmh.framework.verion>

Reply via email to