ibessonov commented on code in PR #6316:
URL: https://github.com/apache/ignite-3/pull/6316#discussion_r2239440196


##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/sorted/comparator/JitComparatorGenerator.java:
##########
@@ -0,0 +1,661 @@
+/*
+ * 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.storage.pagememory.index.sorted.comparator;
+
+import static 
com.facebook.presto.bytecode.control.SwitchStatement.switchBuilder;
+import static com.facebook.presto.bytecode.expression.BytecodeExpressions.add;
+import static 
com.facebook.presto.bytecode.expression.BytecodeExpressions.bitwiseAnd;
+import static 
com.facebook.presto.bytecode.expression.BytecodeExpressions.bitwiseOr;
+import static 
com.facebook.presto.bytecode.expression.BytecodeExpressions.constantInt;
+import static 
com.facebook.presto.bytecode.expression.BytecodeExpressions.equal;
+import static 
com.facebook.presto.bytecode.expression.BytecodeExpressions.invokeStatic;
+import static 
com.facebook.presto.bytecode.expression.BytecodeExpressions.notEqual;
+import static com.facebook.presto.bytecode.instruction.JumpInstruction.jump;
+import static 
org.apache.ignite.internal.binarytuple.BinaryTupleParser.shortValue;
+import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+
+import com.facebook.presto.bytecode.Access;
+import com.facebook.presto.bytecode.BytecodeBlock;
+import com.facebook.presto.bytecode.ClassDefinition;
+import com.facebook.presto.bytecode.ClassGenerator;
+import com.facebook.presto.bytecode.MethodDefinition;
+import com.facebook.presto.bytecode.Parameter;
+import com.facebook.presto.bytecode.ParameterizedType;
+import com.facebook.presto.bytecode.Scope;
+import com.facebook.presto.bytecode.Variable;
+import com.facebook.presto.bytecode.control.IfStatement;
+import com.facebook.presto.bytecode.control.SwitchStatement.SwitchBuilder;
+import com.facebook.presto.bytecode.expression.BytecodeExpression;
+import com.facebook.presto.bytecode.instruction.LabelNode;
+import 
com.facebook.presto.bytecode.instruction.VariableInstruction.LoadVariableInstruction;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.file.Path;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoLocalDateTime;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.internal.binarytuple.BinaryTupleCommon;
+import org.apache.ignite.internal.binarytuple.BinaryTupleFormatException;
+import org.apache.ignite.internal.binarytuple.BinaryTupleParser;
+import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
+import org.apache.ignite.internal.binarytuple.ByteBufferAccessor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogColumnCollation;
+import org.apache.ignite.internal.lang.IgniteInternalException;
+import org.apache.ignite.internal.schema.BinaryTupleComparatorUtils;
+import org.apache.ignite.internal.schema.UnsafeByteBufferAccessor;
+import org.apache.ignite.internal.type.NativeType;
+import org.apache.ignite.internal.util.GridUnsafe;
+import org.apache.ignite.lang.ErrorGroups.Common;
+
+/**
+ * Generator for implementation of {@link JitComparator} using bytecode 
generation.
+ */
+public class JitComparatorGenerator {
+    /**
+     * Class generator. Please use {@link 
ClassGenerator#dumpClassFilesTo(Path)} for debugging or investigations.
+     */
+    private static final ClassGenerator CLASS_GENERATOR = 
ClassGenerator.classGenerator(JitComparatorGenerator.class.getClassLoader());
+
+    // Methods of BinaryTupleParser.
+    private static final Method PARSER_BYTE_VALUE;
+    private static final Method PARSER_SHORT_VALUE;
+    private static final Method PARSER_INT_VALUE;
+    private static final Method PARSER_LONG_VALUE;
+    private static final Method PARSER_FLOAT_VALUE;
+    private static final Method PARSER_DOUBLE_VALUE;
+    private static final Method PARSER_DATE_VALUE;
+    private static final Method PARSER_TIME_VALUE;
+    private static final Method PARSER_DATETIME_VALUE;
+
+    // "compare" methods of primitive types.
+    private static final Method BYTE_COMPARE;
+    private static final Method SHORT_COMPARE;
+    private static final Method INT_COMPARE;
+    private static final Method LONG_COMPARE;
+    private static final Method FLOAT_COMPARE;
+    private static final Method DOUBLE_COMPARE;
+
+    // Methods of BinaryTupleComparatorUtils.
+    private static final Method UTILS_TIMESTAMP_COMPARE;
+    private static final Method UTILS_UUID_COMPARE;
+    private static final Method UTILS_STRING_COMPARE;
+    private static final Method UTILS_BYTES_COMPARE;
+
+    // "compareBigDecimal" from this class.
+    private static final Method DECIMAL_COMPARE;
+
+    // "compareTo" methods of LocalDate, LocalTime, and LocalDateTime.
+    private static final Method DATE_COMPARE_TO;
+    private static final Method TIME_COMPARE_TO;
+    private static final Method DATETIME_COMPARE_TO;
+
+    static {
+        try {
+            PARSER_BYTE_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("byteValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_SHORT_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("shortValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_INT_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("intValue", ByteBufferAccessor.class, 
int.class, int.class);
+            PARSER_LONG_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("longValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_FLOAT_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("floatValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_DOUBLE_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("doubleValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_DATE_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("dateValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_TIME_VALUE = 
BinaryTupleParser.class.getDeclaredMethod("timeValue", 
ByteBufferAccessor.class, int.class, int.class);
+            PARSER_DATETIME_VALUE = BinaryTupleParser.class.getDeclaredMethod(
+                    "dateTimeValue", ByteBufferAccessor.class, int.class, 
int.class
+            );
+
+            BYTE_COMPARE = Byte.class.getDeclaredMethod("compare", byte.class, 
byte.class);
+            SHORT_COMPARE = Short.class.getDeclaredMethod("compare", 
short.class, short.class);
+            INT_COMPARE = Integer.class.getDeclaredMethod("compare", 
int.class, int.class);
+            LONG_COMPARE = Long.class.getDeclaredMethod("compare", long.class, 
long.class);
+            FLOAT_COMPARE = Float.class.getDeclaredMethod("compare", 
float.class, float.class);
+            DOUBLE_COMPARE = Double.class.getDeclaredMethod("compare", 
double.class, double.class);
+
+            UTILS_TIMESTAMP_COMPARE = 
BinaryTupleComparatorUtils.class.getDeclaredMethod(
+                    "compareAsTimestamp", ByteBufferAccessor.class, int.class, 
int.class, ByteBufferAccessor.class, int.class, int.class
+            );
+            UTILS_UUID_COMPARE = 
BinaryTupleComparatorUtils.class.getDeclaredMethod(
+                    "compareAsUuid", ByteBufferAccessor.class, int.class, 
ByteBufferAccessor.class, int.class
+            );
+            UTILS_STRING_COMPARE = 
BinaryTupleComparatorUtils.class.getDeclaredMethod(
+                    "compareAsString", ByteBufferAccessor.class, int.class, 
int.class, ByteBufferAccessor.class, int.class, int.class
+            );
+            UTILS_BYTES_COMPARE = 
BinaryTupleComparatorUtils.class.getDeclaredMethod(
+                    "compareAsBytes", ByteBufferAccessor.class, int.class, 
int.class, ByteBufferAccessor.class, int.class, int.class
+            );
+
+            DECIMAL_COMPARE = JitComparatorGenerator.class.getDeclaredMethod(
+                    "compareBigDecimal",
+                    UnsafeByteBufferAccessor.class, int.class, int.class, 
UnsafeByteBufferAccessor.class, int.class, int.class
+            );
+
+            DATE_COMPARE_TO = LocalDate.class.getDeclaredMethod("compareTo", 
ChronoLocalDate.class);
+            TIME_COMPARE_TO = LocalTime.class.getDeclaredMethod("compareTo", 
LocalTime.class);
+            DATETIME_COMPARE_TO = 
LocalDateTime.class.getDeclaredMethod("compareTo", ChronoLocalDateTime.class);
+        } catch (NoSuchMethodException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    /** Counter for generating class names. */
+    private static final AtomicInteger CLASS_NAME_COUNTER = new 
AtomicInteger();
+
+    /**
+     * Creates an instance of {@link JitComparator} using bytecode generation.
+     *
+     * @param columnCollations List of column collations.
+     * @param columnTypes List of column types.
+     * @param nullableFlags List of nullability flags for each column.
+     */
+    public static JitComparator createComparator(
+            List<CatalogColumnCollation> columnCollations,
+            List<NativeType> columnTypes,
+            List<Boolean> nullableFlags
+    ) {
+        int maxEntrySizeLog = maxEntrySizeLog(columnTypes);
+
+        // Name 
"org/apache/ignite/internal/storage/pagememory/index/sorted/comparator/JitComparatorGenerator&&<idx>"
 is used for generated
+        // classes.
+        ClassDefinition classDefinition = new ClassDefinition(
+                EnumSet.of(Access.PUBLIC, Access.FINAL),
+                JitComparator.class.getName().replace('.', '/') + "$$" + 
CLASS_NAME_COUNTER.getAndIncrement(),
+                ParameterizedType.type(Object.class),
+                ParameterizedType.type(JitComparator.class)
+        );
+
+        // The implementation of the "JitComparator#compare" method.
+        MethodDefinition compare = classDefinition.declareMethod(
+                EnumSet.of(Access.PUBLIC, Access.FINAL),
+                "compare",
+                ParameterizedType.type(int.class),
+                Parameter.arg("outerAccessor", UnsafeByteBufferAccessor.class),
+                Parameter.arg("outerSize", int.class),
+                Parameter.arg("innerAccessor", UnsafeByteBufferAccessor.class),
+                Parameter.arg("innerSize", int.class)
+        );
+        compare.declareAnnotation(Override.class);
+
+        Scope scope = compare.getScope();
+        BytecodeBlock body = compare.getBody();
+
+        // Method parameters.
+        Variable outerAccessor = scope.getVariable("outerAccessor");
+        Variable innerAccessor = scope.getVariable("innerAccessor");
+        Variable outerSize = scope.getVariable("outerSize");
+        Variable innerSize = scope.getVariable("innerSize");
+
+        // Variables for entry sizes. If the "maxEntrySizeLog" is "0", then 
these variables will left unused, because we know their value at
+        // compile time (it's always zero).
+        Variable outerEntrySize = scope.declareVariable(int.class, 
"outerEntrySize");
+        Variable innerEntrySize = scope.declareVariable(int.class, 
"innerEntrySize");
+
+        if (maxEntrySizeLog != 0) {
+            // If entry size can be more than 1, then we read it from headers 
of tuples like this:

Review Comment:
   I guess I meant `larger`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@ignite.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to