Repository: asterixdb Updated Branches: refs/heads/master 5ae0c1ffd -> 274f29671
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/CodeGenUtil.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/CodeGenUtil.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/CodeGenUtil.java deleted file mode 100644 index 87a9a84..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/CodeGenUtil.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.lang3.tuple.Pair; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; - -/** - * A utility class that generates byte code for scalar function descriptors. - */ -public class CodeGenUtil { - - public final static String DEFAULT_SUFFIX_FOR_GENERATED_CLASS = "Gen"; - private final static String OBJECT_CLASS_NAME = "java/lang/Object"; - private final static String DESCRIPTOR_SUPER_CLASS_NAME = "org/apache/asterix/runtime/" - + "evaluators/base/AbstractScalarFunctionDynamicDescriptor"; - private final static String EVALUATOR_FACTORY = "EvaluatorFactory"; - private final static String EVALUATOR = "Evaluator"; - private final static String INNER = "Inner"; - private final static String DOLLAR = "$"; - private final static String NESTED_CLASSNAME_PREFIX = "_"; - - /** - * The callback interface for a caller to determine what it needs to do for - * the generated class bytes. - */ - public static interface ClassByteCodeAction { - - /** - * Run a user-defined action for the generated class definition bytes. - * - * @param targetClassName, - * the name for the generated class. - * @param classDefinitionBytes, - * the class definition bytes. - * @throws IOException - */ - public void runAction(String targetClassName, byte[] classDefinitionBytes) throws IOException; - }; - - /** - * Generates the byte code for a scalar function descriptor. - * - * @param packagePrefix, - * the prefix of evaluators for code generation. - * @param originalFuncDescriptorClassName, - * the original class name of the function descriptor. - * @param suffixForGeneratedClass, - * the suffix for the generated class. - * @param action, - * the customized action for the generated class definition bytes. - * @throws IOException - * @throws ClassNotFoundException - */ - public static List<Pair<String, String>> generateScalarFunctionDescriptorBinary(String packagePrefix, - String originalFuncDescriptorClassName, String suffixForGeneratedClass, ClassLoader classLoader, - ClassByteCodeAction action) throws IOException, ClassNotFoundException { - originalFuncDescriptorClassName = toInternalClassName(originalFuncDescriptorClassName); - if (originalFuncDescriptorClassName.equals(DESCRIPTOR_SUPER_CLASS_NAME)) { - return Collections.emptyList(); - } - - String targetFuncDescriptorClassName = getGeneratedFunctionDescriptorInternalClassName( - originalFuncDescriptorClassName, suffixForGeneratedClass); - - // Adds the mapping of the old/new names of the function descriptor. - List<Pair<String, String>> nameMappings = new ArrayList<>(); - - // Generates code for super classes except java.lang.Object. - Class<?> evaluatorClass = CodeGenUtil.class.getClassLoader() - .loadClass(toJdkStandardName(originalFuncDescriptorClassName)); - nameMappings.addAll(generateScalarFunctionDescriptorBinary(packagePrefix, - evaluatorClass.getSuperclass().getName(), suffixForGeneratedClass, classLoader, action)); - - nameMappings.add(Pair.of(originalFuncDescriptorClassName, targetFuncDescriptorClassName)); - nameMappings.add(Pair.of(toJdkStandardName(originalFuncDescriptorClassName), - toJdkStandardName(targetFuncDescriptorClassName))); - - // Gathers evaluator factory classes that are created in the function descriptor. - ClassReader reader = new ClassReader(getResourceStream(originalFuncDescriptorClassName, classLoader)); - GatherEvaluatorFactoryCreationVisitor evalFactoryCreationVisitor = new GatherEvaluatorFactoryCreationVisitor( - toInternalClassName(packagePrefix)); - reader.accept(evalFactoryCreationVisitor, 0); - Set<String> evaluatorFactoryClassNames = evalFactoryCreationVisitor.getCreatedEvaluatorFactoryClassNames(); - - // Generates inner classes other than evaluator factories. - generateNonEvalInnerClasses(reader, evaluatorFactoryClassNames, nameMappings, suffixForGeneratedClass, - classLoader, action); - - // Generates evaluator factories that are created in the function descriptor. - int evalFactoryCounter = 0; - for (String evaluateFactoryClassName : evaluatorFactoryClassNames) { - generateEvaluatorFactoryClassBinary(packagePrefix, evaluateFactoryClassName, suffixForGeneratedClass, - evalFactoryCounter++, nameMappings, classLoader, action); - } - - // Transforms the function descriptor class and outputs the generated class binary. - ClassWriter writer = new ClassWriter(reader, 0); - RenameClassVisitor renamingVisitor = new RenameClassVisitor(writer, nameMappings); - reader.accept(renamingVisitor, 0); - action.runAction(targetFuncDescriptorClassName, writer.toByteArray()); - return nameMappings; - } - - public static String getGeneratedFunctionDescriptorClassName(String originalFuncDescriptorClassName, - String suffixForGeneratedClass) { - return toJdkStandardName(getGeneratedFunctionDescriptorInternalClassName(originalFuncDescriptorClassName, - suffixForGeneratedClass)); - } - - private static String getGeneratedFunctionDescriptorInternalClassName(String originalFuncDescriptorClassName, - String suffixForGeneratedClass) { - String originalFuncDescriptorClassInternalName = toInternalClassName(originalFuncDescriptorClassName); - String targetFuncDescriptorClassName = getGeneratedClassName(originalFuncDescriptorClassInternalName, - suffixForGeneratedClass, 0); - return targetFuncDescriptorClassName; - } - - /** - * Apply mappings for a class name. - * - * @param nameMappings, - * the mappings from existing class names to that of their generated counterparts. - * @param inputStr, - * the name of a class. - * @return the name of the generated counterpart class. - */ - static String applyMapping(List<Pair<String, String>> nameMappings, String inputStr) { - if (inputStr == null) { - return null; - } - String result = inputStr; - - // Applies name mappings in the reverse order, i.e., - // mapping recent added old/new name pairs first. - int index = nameMappings.size() - 1; - for (; index >= 0; --index) { - Pair<String, String> entry = nameMappings.get(index); - if (result.contains(entry.getLeft())) { - return result.replace(entry.getLeft(), entry.getRight()); - } - } - return result; - } - - /** - * Generates the byte code for an evaluator factory class. - * - * @param packagePrefix, - * the prefix of evaluators for code generation. - * @param originalEvaluatorFactoryClassName, - * the original evaluator factory class name. - * @param suffixForGeneratedClass, - * the suffix for the generated class. - * @param factoryCounter, - * the counter for the generated class. - * @param nameMappings, - * class names that needs to be rewritten in the generated byte code. - * @param classLoader, - * a class loader that has the original evaluator factory class in its resource paths. - * @param action, - * a user definition action for the generated byte code. - * @throws IOException - * @throws ClassNotFoundException - */ - private static void generateEvaluatorFactoryClassBinary(String packagePrefix, - String originalEvaluatorFactoryClassName, String suffixForGeneratedClass, int factoryCounter, - List<Pair<String, String>> nameMappings, ClassLoader classLoader, ClassByteCodeAction action) - throws IOException, ClassNotFoundException { - originalEvaluatorFactoryClassName = toInternalClassName(originalEvaluatorFactoryClassName); - String targetEvaluatorFactoryClassName = getGeneratedClassName(originalEvaluatorFactoryClassName, - EVALUATOR_FACTORY + suffixForGeneratedClass, factoryCounter); - - // Adds the old/new names of the evaluator factory into the mapping. - nameMappings.add(Pair.of(originalEvaluatorFactoryClassName, targetEvaluatorFactoryClassName)); - nameMappings.add(Pair.of(toJdkStandardName(originalEvaluatorFactoryClassName), - toJdkStandardName(targetEvaluatorFactoryClassName))); - - // Gathers the class names of the evaluators that are created in the evaluator factory. - ClassReader reader = new ClassReader(getResourceStream(originalEvaluatorFactoryClassName, classLoader)); - GatherEvaluatorCreationVisitor evalCreationVisitor = new GatherEvaluatorCreationVisitor( - toInternalClassName(packagePrefix)); - reader.accept(evalCreationVisitor, 0); - Set<String> evaluatorClassNames = evalCreationVisitor.getCreatedEvaluatorClassNames(); - - // Generates inner classes other than evaluators. - generateNonEvalInnerClasses(reader, evaluatorClassNames, nameMappings, suffixForGeneratedClass, classLoader, - action); - - // Generates code for all evaluators. - int evalCounter = 0; - for (String evaluateClassName : evaluatorClassNames) { - generateEvaluatorClassBinary(evaluateClassName, suffixForGeneratedClass, evalCounter++, nameMappings, - classLoader, action); - } - - // Transforms the evaluator factory class and outputs the generated class binary. - ClassWriter writer = new ClassWriter(reader, 0); - RenameClassVisitor renamingVisitor = new RenameClassVisitor(writer, nameMappings); - reader.accept(renamingVisitor, 0); - action.runAction(targetEvaluatorFactoryClassName, writer.toByteArray()); - } - - /** - * Generates the byte code for an evaluator class. - * - * @param originalEvaluatorClassName, - * the name of the original evaluator class. - * @param suffixForGeneratedClass, - * the suffix for the generated class. - * @param evalCounter, - * the counter for the generated class. - * @param nameMappings, - * class names that needs to be rewritten in the generated byte code. - * @param classLoader, - * a class loader that has the original evaluator factory class in its resource paths. - * @param action, - * a user definition action for the generated byte code. - * @throws IOException - * @throws ClassNotFoundException - */ - private static void generateEvaluatorClassBinary(String originalEvaluatorClassName, String suffixForGeneratedClass, - int evalCounter, List<Pair<String, String>> nameMappings, ClassLoader classLoader, - ClassByteCodeAction action) throws IOException, ClassNotFoundException { - // Convert class names. - originalEvaluatorClassName = toInternalClassName(originalEvaluatorClassName); - if (originalEvaluatorClassName.equals(OBJECT_CLASS_NAME)) { - return; - } - String targetEvaluatorClassName = getGeneratedClassName(originalEvaluatorClassName, - EVALUATOR + suffixForGeneratedClass, evalCounter); - - // Generates code for super classes except java.lang.Object. - Class<?> evaluatorClass = CodeGenUtil.class.getClassLoader() - .loadClass(toJdkStandardName(originalEvaluatorClassName)); - generateEvaluatorClassBinary(evaluatorClass.getSuperclass().getName(), suffixForGeneratedClass, evalCounter, - nameMappings, classLoader, action); - - // Adds name mapping. - nameMappings.add(Pair.of(originalEvaluatorClassName, targetEvaluatorClassName)); - nameMappings.add( - Pair.of(toJdkStandardName(originalEvaluatorClassName), toJdkStandardName(targetEvaluatorClassName))); - - ClassReader firstPassReader = new ClassReader(getResourceStream(originalEvaluatorClassName, classLoader)); - // Generates inner classes other than the evaluator. - Set<String> excludedNames = new HashSet<>(); - for (Pair<String, String> entry : nameMappings) { - excludedNames.add(entry.getKey()); - } - generateNonEvalInnerClasses(firstPassReader, excludedNames, nameMappings, suffixForGeneratedClass, classLoader, - action); - - // Injects missing-handling byte code. - ClassWriter firstPassWriter = new ClassWriter(firstPassReader, 0); - EvaluatorMissingCheckVisitor missingHandlingVisitor = new EvaluatorMissingCheckVisitor(firstPassWriter); - firstPassReader.accept(missingHandlingVisitor, 0); - - ClassReader secondPassReader = new ClassReader(firstPassWriter.toByteArray()); - // Injects null-handling byte code and output the class binary. - // Since we're going to add jump instructions, we have to let the ClassWriter to - // automatically generate frames for JVM to verify the class. - ClassWriter secondPassWriter = new ClassWriter(secondPassReader, - ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - RenameClassVisitor renamingVisitor = new RenameClassVisitor(secondPassWriter, nameMappings); - EvaluatorNullCheckVisitor nullHandlingVisitor = new EvaluatorNullCheckVisitor(renamingVisitor, - missingHandlingVisitor.getLastAddedLabel()); - secondPassReader.accept(nullHandlingVisitor, 0); - action.runAction(targetEvaluatorClassName, secondPassWriter.toByteArray()); - } - - /** - * Generates non-evaluator(-factory) inner classes defined in either a function descriptor - * or an evaluator factory. - * - * @param reader, - * the reader of the outer class. - * @param evalClassNames, - * the names of evaluator/evaluator-factory classes that shouldn't be generated in this - * method. - * @param nameMappings, - * class names that needs to be rewritten in the generated byte code. - * @param classLoader, - * a class loader that has the original evaluator factory class in its resource paths. - * @param action, - * a user definition action for the generated byte code. - * @throws IOException - */ - private static void generateNonEvalInnerClasses(ClassReader reader, Set<String> evalClassNames, - List<Pair<String, String>> nameMappings, String suffixForGeneratedClass, ClassLoader classLoader, - ClassByteCodeAction action) throws IOException { - // Gathers inner classes of the function descriptor. - GatherInnerClassVisitor innerClassVisitor = new GatherInnerClassVisitor(); - reader.accept(innerClassVisitor, 0); - Set<String> innerClassNames = innerClassVisitor.getInnerClassNames(); - innerClassNames.removeAll(evalClassNames); - - // Rewrites inner classes. - int counter = 0; - String suffix = INNER + suffixForGeneratedClass; - for (String innerClassName : innerClassNames) { - // adds name mapping. - String targetInnerClassName = getGeneratedClassName(innerClassName, suffix, counter++); - nameMappings.add(Pair.of(innerClassName, targetInnerClassName)); - nameMappings.add(Pair.of(toJdkStandardName(innerClassName), toJdkStandardName(targetInnerClassName))); - - // Renaming appearances of original class names. - ClassReader innerClassReader = new ClassReader(getResourceStream(innerClassName, classLoader)); - ClassWriter writer = new ClassWriter(innerClassReader, 0); - RenameClassVisitor renamingVisitor = new RenameClassVisitor(writer, nameMappings); - innerClassReader.accept(renamingVisitor, 0); - action.runAction(targetInnerClassName, writer.toByteArray()); - } - } - - /** - * Converts a JDK class name to the class naming format of ASM. - * - * @param name, - * a class name following the JDK convention. - * @return a "/"-separated class name assumed by ASM. - */ - private static String toInternalClassName(String name) { - return name.replace(".", "/"); - } - - /** - * Converts an ASM class name to the JDK class naming format. - * - * @param name, - * a class name following the ASM convention. - * @return a "."-separated class name for JDK. - */ - private static String toJdkStandardName(String name) { - return name.replace("/", "."); - } - - /** - * Gets the name of a generated class. - * - * @param originalClassName, - * the original class, i.e., the source of the generated class. - * @param suffix, - * the suffix for the generated class. - * @param counter, - * a counter that appearing at the end of the name of the generated class. - * @return the name of the generated class. - */ - private static String getGeneratedClassName(String originalClassName, String suffix, int counter) { - StringBuilder sb = new StringBuilder(); - int end = originalClassName.indexOf(DOLLAR); - if (end < 0) { - end = originalClassName.length(); - } - - String name = originalClassName.substring(0, end); - sb.append(name); - sb.append(DOLLAR); - sb.append(NESTED_CLASSNAME_PREFIX); - sb.append(suffix); - - if (counter > 0) { - sb.append(counter); - } - return sb.toString(); - } - - /** - * Gets the input stream from a class file. - * - * @param className, - * the name of a class. - * @param classLoader, - * the corresponding class loader. - * @return the input stream. - */ - private static InputStream getResourceStream(String className, ClassLoader classLoader) { - return classLoader.getResourceAsStream(className.replace('.', '/') + ".class"); - } -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorMissingCheckVisitor.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorMissingCheckVisitor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorMissingCheckVisitor.java deleted file mode 100644 index adedee5..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorMissingCheckVisitor.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import java.util.ArrayList; -import java.util.List; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.IincInsnNode; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.IntInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - -/** - * This visitor adds missing-handling byte code into an evaluator class. - */ -public class EvaluatorMissingCheckVisitor extends ClassVisitor { - private static final String EVALUATE_DESC = "(Lorg/apache/hyracks/dataflow/common/data/" - + "accessors/IFrameTupleReference;Lorg/apache/hyracks/data/std/api/IPointable;)V"; - private static final String EVALUATE = "evaluate"; - private static final MethodIdentifier METHOD_IDENTIFIER = new MethodIdentifier(EVALUATE, EVALUATE_DESC, null); - private static final String TYPE_CHECKER_CLASS = "org/apache/asterix/runtime/evaluators/staticcodegen/TypeChecker"; - private static final String TYPE_CHECKER_DESC = "L" + TYPE_CHECKER_CLASS + ";"; - private static final String TYPE_CHECKER_NAME = "typeChecker"; - private static final String IS_MISSING = "isMissing"; - private static final String TYPECHECK_METHOD_DESC = "(Lorg/apache/hyracks/data/std/api/IPointable;" - + "Lorg/apache/hyracks/data/std/api/IPointable;)Z"; - private static final String CONSTRUCTOR = "<init>"; - private String className = null; - private Label lastAddedLabel = null; - - public EvaluatorMissingCheckVisitor(ClassVisitor downStreamVisitor) { - super(Opcodes.ASM5, downStreamVisitor); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - if (cv != null) { - cv.visit(version, access, name, signature, superName, interfaces); - } - this.className = name; - } - - @Override - public void visitEnd() { - if (cv != null) { - cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, TYPE_CHECKER_NAME, TYPE_CHECKER_DESC, null, null); - cv.visitEnd(); - } - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); - if (!METHOD_IDENTIFIER.equals(new MethodIdentifier(name, desc, signature)) && !name.equals(CONSTRUCTOR)) { - return mv; - } - if (name.equals(CONSTRUCTOR) && mv != null) { - return new ConstructorVisitor(Opcodes.ASM5, mv); - } - if (mv != null) { - return new InjectMissingCheckVisitor(Opcodes.ASM5, mv); - } - return null; - } - - // Obtains the last added label. - Label getLastAddedLabel() { - return lastAddedLabel; - } - - class ConstructorVisitor extends MethodVisitor { - - public ConstructorVisitor(int api, MethodVisitor mv) { - super(api, mv); - } - - @Override - public void visitInsn(int opcode) { - if (opcode != Opcodes.RETURN) { - mv.visitInsn(opcode); - return; - } - // Loads "this". - mv.visitVarInsn(Opcodes.ALOAD, 0); - // New TypeChecker. - mv.visitTypeInsn(Opcodes.NEW, TYPE_CHECKER_CLASS); - // Duplicate the top operand. - mv.visitInsn(Opcodes.DUP); - // Invoke the constructor of TypeChecker. - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, TYPE_CHECKER_CLASS, CONSTRUCTOR, "()V", true); - // Putfield for the field typeChecker. - mv.visitFieldInsn(Opcodes.PUTFIELD, className, TYPE_CHECKER_NAME, TYPE_CHECKER_DESC); - // RETURN. - mv.visitInsn(Opcodes.RETURN); - } - } - - class InjectMissingCheckVisitor extends MethodVisitor { - - private FieldInsnNode fieldAccessNode = null; - private List<AbstractInsnNode> instructionsAfterFieldAccess = new ArrayList<>(); - private boolean updateToNextLabel = false; - - public InjectMissingCheckVisitor(int opcode, MethodVisitor mv) { - super(opcode, mv); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - mv.visitFieldInsn(opcode, owner, name, desc); - fieldAccessNode = new FieldInsnNode(opcode, owner, name, desc); - instructionsAfterFieldAccess.clear(); - } - - @Override - public void visitIincInsn(int var, int increment) { - if (fieldAccessNode != null) { - instructionsAfterFieldAccess.add(new IincInsnNode(var, increment)); - } - super.visitIincInsn(var, increment); - } - - @Override - public void visitInsn(int opcode) { - if (fieldAccessNode != null) { - instructionsAfterFieldAccess.add(new InsnNode(opcode)); - } - super.visitInsn(opcode); - } - - @Override - public void visitIntInsn(int opcode, int operand) { - if (fieldAccessNode != null) { - instructionsAfterFieldAccess.add(new IntInsnNode(opcode, operand)); - } - super.visitIntInsn(opcode, operand); - } - - @Override - public void visitVarInsn(int opcode, int operand) { - if (fieldAccessNode != null) { - instructionsAfterFieldAccess.add(new VarInsnNode(opcode, operand)); - } - super.visitVarInsn(opcode, operand); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - mv.visitMethodInsn(opcode, owner, name, desc, itf); - if (fieldAccessNode == null || !METHOD_IDENTIFIER.equals(new MethodIdentifier(name, desc, null))) { - return; - } - - // Loads the callee. - mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitFieldInsn(Opcodes.GETFIELD, className, TYPE_CHECKER_NAME, TYPE_CHECKER_DESC); - - // Loads "this". - mv.visitVarInsn(Opcodes.ALOAD, 0); - // Replays the field access instruction. - fieldAccessNode.accept(mv); - - // Replays other instruction between the field access and the evaluator call. - for (AbstractInsnNode instruction : instructionsAfterFieldAccess) { - instruction.accept(mv); - } - - // Loads the result IPointable. - mv.visitVarInsn(Opcodes.ALOAD, 2); - - // Invokes the missing check method. - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_CHECKER_CLASS, IS_MISSING, TYPECHECK_METHOD_DESC, false); - lastAddedLabel = new Label(); - // Adds the if branch. - mv.visitJumpInsn(Opcodes.IFEQ, lastAddedLabel); - mv.visitInsn(Opcodes.RETURN); - mv.visitLabel(lastAddedLabel); - } - - @Override - public void visitLabel(Label label) { - if (updateToNextLabel) { - lastAddedLabel = label; - updateToNextLabel = false; - } - super.visitLabel(label); - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - super.visitJumpInsn(opcode, label); - if (lastAddedLabel == null) { - return; - } - try { - if (label.getOffset() < lastAddedLabel.getOffset()) { - // Backward jump, i.e., loop. - updateToNextLabel = true; - } - } catch (IllegalStateException e) { - // Forward jump, the offset is not available. - } - } - } - -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorNullCheckVisitor.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorNullCheckVisitor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorNullCheckVisitor.java deleted file mode 100644 index 30f810b..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/EvaluatorNullCheckVisitor.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -/** - * This visitor adds null-handling byte code into an evaluator class. - */ -public class EvaluatorNullCheckVisitor extends ClassVisitor { - private final static String EVALUATE_DESC = "(Lorg/apache/hyracks/dataflow/common/data/accessors/" - + "IFrameTupleReference;Lorg/apache/hyracks/data/std/api/IPointable;)V"; - private final static String EVALUATE = "evaluate"; - private final static MethodIdentifier METHOD_IDENTIFIER = new MethodIdentifier(EVALUATE, EVALUATE_DESC, null); - private final static String TYPE_CHECKER_CLASS = "org/apache/asterix/runtime/evaluators/staticcodegen/" - + "TypeChecker"; - private final static String TYPE_CHECKER_DESC = "L" + TYPE_CHECKER_CLASS + ";"; - private final static String TYPE_CHECKER_NAME = "typeChecker"; - private final static String IS_NULL = "isNull"; - private final static String TYPECHECK_METHOD_DESC = "(Lorg/apache/hyracks/data/std/api/IPointable;)Z"; - private String className = null; - private final Label lastAddedLabel; - - public EvaluatorNullCheckVisitor(ClassVisitor downStreamVisitor, Label lastAddedLabel) { - super(Opcodes.ASM5, downStreamVisitor); - this.lastAddedLabel = lastAddedLabel; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - if (cv != null) { - cv.visit(version, access, name, signature, superName, interfaces); - } - this.className = name; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); - if (!METHOD_IDENTIFIER.equals(new MethodIdentifier(name, desc, signature))) { - return mv; - } - if (mv != null) { - return new InjectNullCheckVisitor(Opcodes.ASM5, mv); - } - return null; - } - - // Obtains the last added label. - Label getLastAddedLabel() { - return lastAddedLabel; - } - - class InjectNullCheckVisitor extends MethodVisitor { - - public InjectNullCheckVisitor(int api, MethodVisitor mv) { - super(api, mv); - } - - @Override - public void visitLabel(Label label) { - // Emits the label. - mv.visitLabel(label); - - // Injects null-handling after the last missing-handling byte code. - if (lastAddedLabel == null || lastAddedLabel.getOffset() != label.getOffset()) { - return; - } - - // Loads the callee. - mv.visitVarInsn(Opcodes.ALOAD, 0); - mv.visitFieldInsn(Opcodes.GETFIELD, className, TYPE_CHECKER_NAME, TYPE_CHECKER_DESC); - - // Loads the result IPointable. - mv.visitVarInsn(Opcodes.ALOAD, 2); - - // Invokes the null check method. - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_CHECKER_CLASS, IS_NULL, TYPECHECK_METHOD_DESC, false); - Label notNull = new Label(); - // Adds the if branch. - mv.visitJumpInsn(Opcodes.IFEQ, notNull); - mv.visitInsn(Opcodes.RETURN); - mv.visitLabel(notNull); - } - } -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorCreationVisitor.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorCreationVisitor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorCreationVisitor.java deleted file mode 100644 index 416ce63..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorCreationVisitor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import java.util.HashSet; -import java.util.Set; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -/** - * This visitor gathers all created evaluators in an evaluator factory. - */ -public class GatherEvaluatorCreationVisitor extends ClassVisitor { - - private static String METHOD_NAME = "createScalarEvaluator"; - private Set<String> createdEvaluatorClassNames = new HashSet<>(); - private String ownerPrefix; - - public GatherEvaluatorCreationVisitor(String ownerPrefix) { - super(Opcodes.ASM5); - this.ownerPrefix = ownerPrefix; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - if (!name.equals(METHOD_NAME)) { - return null; - } - return new MethodVisitor(Opcodes.ASM5, null) { - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - if (opcode != Opcodes.INVOKESPECIAL) { - return; - } - if (owner.startsWith(ownerPrefix)) { - createdEvaluatorClassNames.add(owner); - } - } - }; - - } - - public Set<String> getCreatedEvaluatorClassNames() { - return createdEvaluatorClassNames; - } - -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorFactoryCreationVisitor.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorFactoryCreationVisitor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorFactoryCreationVisitor.java deleted file mode 100644 index 19234e2..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherEvaluatorFactoryCreationVisitor.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import java.util.HashSet; -import java.util.Set; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -/** - * This visitor gathers all created evaluator factories in a scalar function descriptor. - */ -public class GatherEvaluatorFactoryCreationVisitor extends ClassVisitor { - - private static String METHOD_NAME = "createEvaluatorFactory"; - private final Set<String> createdEvaluatorFactoryClassNames = new HashSet<>(); - private String ownerPrefix; - - public GatherEvaluatorFactoryCreationVisitor(String ownerPrefix) { - super(Opcodes.ASM5); - this.ownerPrefix = ownerPrefix; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - if (!name.equals(METHOD_NAME)) { - return null; - } - return new MethodVisitor(Opcodes.ASM5, null) { - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - if (opcode != Opcodes.INVOKESPECIAL) { - return; - } - if (owner.startsWith(ownerPrefix)) { - createdEvaluatorFactoryClassNames.add(owner); - } - } - }; - } - - public Set<String> getCreatedEvaluatorFactoryClassNames() { - return createdEvaluatorFactoryClassNames; - } - -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherInnerClassVisitor.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherInnerClassVisitor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherInnerClassVisitor.java deleted file mode 100644 index 031707b..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/GatherInnerClassVisitor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import java.util.HashSet; -import java.util.Set; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Opcodes; - -/** - * This class gathers all inner classes defined in a class. - */ -public class GatherInnerClassVisitor extends ClassVisitor { - - private final Set<String> innerClassNames = new HashSet<>(); - private String className = null; - - public GatherInnerClassVisitor() { - super(Opcodes.ASM5); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - className = name; - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - if ((className == null || !name.equals(className)) - && ((access & Opcodes.ACC_PUBLIC) == 0 || (access & Opcodes.ACC_STATIC) == 0)) { - innerClassNames.add(name); - } - } - - public Set<String> getInnerClassNames() { - return innerClassNames; - } -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/MethodIdentifier.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/MethodIdentifier.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/MethodIdentifier.java deleted file mode 100644 index c37b93e..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/MethodIdentifier.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -/** - * The data structure that can uniquely identify a method. - */ -public class MethodIdentifier { - - private final String name; - private final String desc; - private final String signature; - - public MethodIdentifier(String name, String desc, String signature) { - this.name = name == null ? "" : name; - this.desc = desc == null ? "" : desc; - this.signature = signature == null ? "" : signature; - } - - @Override - public int hashCode() { - return name.hashCode() * desc.hashCode() * signature.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof MethodIdentifier)) { - return false; - } - MethodIdentifier methodIdentifier = (MethodIdentifier) o; - return name.equals(methodIdentifier.name) && desc.equals(methodIdentifier.desc) - && signature.equals(methodIdentifier.signature); - } - - @Override - public String toString() { - return name + ":" + desc + ":" + signature; - } - -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/274f2967/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/RenameClassVisitor.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/RenameClassVisitor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/RenameClassVisitor.java deleted file mode 100644 index 4396fd6..0000000 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/staticcodegen/RenameClassVisitor.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.asterix.runtime.evaluators.staticcodegen; - -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -/** - * This visitor replaces all the appearances of original class names with - * new (generated) class names, according to an input name mapping. - */ -public class RenameClassVisitor extends ClassVisitor { - - private final List<Pair<String, String>> nameMapping; - - public RenameClassVisitor(ClassVisitor downStreamVisitor, List<Pair<String, String>> nameMapping) { - super(Opcodes.ASM5, downStreamVisitor); - this.nameMapping = nameMapping; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, applyMapping(name), signature, applyMapping(superName), interfaces); - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - // Skips outer class descriptions. - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - if ((access & Opcodes.ACC_PUBLIC) != 0 && (access & Opcodes.ACC_STATIC) != 0) { - super.visitInnerClass(name, outerName, innerName, access); - } - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - return cv.visitField(access, name, applyMapping(desc), applyMapping(signature), value); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, applyMapping(desc), applyMapping(signature), exceptions); - if (mv != null) { - return new MethodVisitor(Opcodes.ASM5, mv) { - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - mv.visitFieldInsn(opcode, applyMapping(owner), applyMapping(name), applyMapping(desc)); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - mv.visitMethodInsn(opcode, applyMapping(owner), name, applyMapping(desc), itf); - } - - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, - int index) { - mv.visitLocalVariable(name, applyMapping(desc), applyMapping(signature), start, end, index); - } - - @Override - public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { - if (local != null) { - for (int index = 0; index < local.length; ++index) { - if (local[index] instanceof String) { - local[index] = applyMapping((String) local[index]); - } - } - } - mv.visitFrame(type, nLocal, local, nStack, stack); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - mv.visitTypeInsn(opcode, applyMapping(type)); - } - - }; - } - return null; - } - - private String applyMapping(String inputStr) { - return CodeGenUtil.applyMapping(nameMapping, inputStr); - } - -}
