Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed 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 com.facebook.presto.sql.gen;
 
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import static com.facebook.presto.byteCode.control.LookupSwitch.lookupSwitchBuilder;
 import static com.facebook.presto.byteCode.expression.ByteCodeExpressions.constantFalse;
 import static com.facebook.presto.byteCode.instruction.JumpInstruction.jump;
 import static com.facebook.presto.sql.gen.ByteCodeUtils.ifWasNullPopAndGoto;
 import static com.facebook.presto.sql.gen.ByteCodeUtils.invoke;
 import static com.facebook.presto.sql.gen.ByteCodeUtils.loadConstant;
 
 public class InCodeGenerator
         implements ByteCodeGenerator
 {
     @Override
     public ByteCodeNode generateExpression(Signature signatureByteCodeGeneratorContext generatorContextType returnTypeList<RowExpressionarguments)
     {
         ByteCodeNode value = generatorContext.generate(arguments.get(0));
 
         List<RowExpressionvalues = arguments.subList(1, arguments.size());
 
         ImmutableList.Builder<ByteCodeNodevaluesByteCode = ImmutableList.builder();
         for (int i = 1; i < arguments.size(); i++) {
             ByteCodeNode testNode = generatorContext.generate(arguments.get(i));
             valuesByteCode.add(testNode);
         }
 
         Type type = arguments.get(0).getType();
         Class<?> javaType = type.getJavaType();
 
         FunctionInfo hashCodeFunction = generatorContext.getRegistry().resolveOperator(., ImmutableList.of(type));
 
         ImmutableListMultimap.Builder<IntegerByteCodeNodehashBucketsBuilder = ImmutableListMultimap.builder();
         ImmutableList.Builder<ByteCodeNodedefaultBucket = ImmutableList.builder();
         ImmutableSet.Builder<ObjectconstantValuesBuilder = ImmutableSet.builder();
 
         for (RowExpression testValue : values) {
             ByteCodeNode testByteCode = generatorContext.generate(testValue);
 
             if (testValue instanceof ConstantExpression && ((ConstantExpressiontestValue).getValue() != null) {
                 ConstantExpression constant = (ConstantExpressiontestValue;
                 Object object = constant.getValue();
                 constantValuesBuilder.add(object);
 
                 try {
                     int hashCode = ((LonghashCodeFunction.getMethodHandle().invoke(object)).intValue();
                     hashBucketsBuilder.put(hashCodetestByteCode);
                 }
                 catch (Throwable throwable) {
                     throw new IllegalArgumentException("Error processing IN statement: error calculating hash code for " + objectthrowable);
                 }
             }
             else {
                 defaultBucket.add(testByteCode);
             }
         }
         ImmutableListMultimap<IntegerByteCodeNodehashBuckets = hashBucketsBuilder.build();
         ImmutableSet<ObjectconstantValues = constantValuesBuilder.build();
 
         LabelNode end = new LabelNode("end");
         LabelNode match = new LabelNode("match");
         LabelNode noMatch = new LabelNode("noMatch");
 
         LabelNode defaultLabel = new LabelNode("default");
 
         Scope scope = generatorContext.getScope();
        ByteCodeNode switchBlock;
        if (constantValues.size() < 1000) {
            Block switchCaseBlocks = new Block();
            LookupSwitch.LookupSwitchBuilder switchBuilder = lookupSwitchBuilder();
            for (Map.Entry<IntegerCollection<ByteCodeNode>> bucket : hashBuckets.asMap().entrySet()) {
                LabelNode label = new LabelNode("inHash" + bucket.getKey());
                switchBuilder.addCase(bucket.getKey(), label);
                Collection<ByteCodeNodetestValues = bucket.getValue();
                Block caseBlock = buildInCase(generatorContextscopetypelabelmatchdefaultLabeltestValuesfalse);
                switchCaseBlocks
                        .append(caseBlock.setDescription("case " + bucket.getKey()));
            }
            switchBuilder.defaultCase(defaultLabel);
            Binding hashCodeBinding = generatorContext
                    .getCallSiteBinder()
                    .bind(hashCodeFunction.getMethodHandle());
            switchBlock = new Block()
                    .comment("lookupSwitch(hashCode(<stackValue>))")
                    .dup(javaType)
                    .append(invoke(hashCodeBindinghashCodeFunction.getSignature()))
                    .longToInt()
                    .append(switchBuilder.build())
                    .append(switchCaseBlocks);
        }
        else {
            // TODO: replace Set with fastutils (or similar) primitive sets if types are primitive
            // for huge IN lists, use a Set
            Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet.class);
            switchBlock = new Block()
                    .comment("inListSet.contains(<stackValue>)")
                    .append(new IfStatement()
                            .condition(new Block()
                                    .comment("value (+boxing if necessary)")
                                    .dup(javaType)
                                    .append(ByteCodeUtils.boxPrimitive(javaType))
                                    .comment("set")
                                    .append(loadConstant(constant))
                                    // TODO: use invokeVirtual on the set instead. This requires swapping the two elements in the stack
                                    .invokeStatic(CompilerOperations.class"in"boolean.classObject.classSet.class))
                            .ifTrue(jump(match)));
        }
        Block defaultCaseBlock = buildInCase(generatorContextscopetypedefaultLabelmatchnoMatchdefaultBucket.build(), true).setDescription("default");
        Block block = new Block()
                .comment("IN")
                .append(value)
                .append(ifWasNullPopAndGoto(scopeendboolean.classjavaType))
                .append(switchBlock)
                .append(defaultCaseBlock);
        Block matchBlock = new Block()
                .setDescription("match")
                .visitLabel(match)
                .pop(javaType)
                .append(generatorContext.wasNull().set(constantFalse()))
                .push(true)
                .gotoLabel(end);
        block.append(matchBlock);
        Block noMatchBlock = new Block()
                .setDescription("noMatch")
                .visitLabel(noMatch)
                .pop(javaType)
                .push(false)
                .gotoLabel(end);
        block.append(noMatchBlock);
        block.visitLabel(end);
        return block;
    }
    private Block buildInCase(ByteCodeGeneratorContext generatorContext,
            Scope scope,
            Type type,
            LabelNode caseLabel,
            LabelNode matchLabel,
            LabelNode noMatchLabel,
            Collection<ByteCodeNodetestValues,
            boolean checkForNulls)
    {
        Variable caseWasNull = null;
        if (checkForNulls) {
            caseWasNull = scope.createTempVariable(boolean.class);
        }
        Block caseBlock = new Block()
                .visitLabel(caseLabel);
        if (checkForNulls) {
            caseBlock.putVariable(caseWasNullfalse);
        }
        LabelNode elseLabel = new LabelNode("else");
        Block elseBlock = new Block()
                .visitLabel(elseLabel);
        Variable wasNull = generatorContext.wasNull();
        if (checkForNulls) {
            elseBlock.append(wasNull.set(caseWasNull));
        }
        elseBlock.gotoLabel(noMatchLabel);
        FunctionInfo operator = generatorContext.getRegistry().resolveOperator(., ImmutableList.of(typetype));
        Binding equalsFunction = generatorContext
                .getCallSiteBinder()
                .bind(operator.getMethodHandle());
        ByteCodeNode elseNode = elseBlock;
        for (ByteCodeNode testNode : testValues) {
            LabelNode testLabel = new LabelNode("test");
            IfStatement test = new IfStatement();
            test.condition()
                    .visitLabel(testLabel)
                    .dup(type.getJavaType())
                    .append(testNode);
            if (checkForNulls) {
                test.condition()
                        .append(wasNull)
                        .putVariable(caseWasNull)
                        .append(ifWasNullPopAndGoto(scopeelseLabelvoid.classtype.getJavaType(), type.getJavaType()));
            }
            test.condition()
                    .append(invoke(equalsFunctionoperator.getSignature()));
            test.ifTrue().gotoLabel(matchLabel);
            test.ifFalse(elseNode);
            elseNode = test;
            elseLabel = testLabel;
        }
        caseBlock.append(elseNode);
        return caseBlock;
    }
New to GrepCode? Check out our FAQ X