LabelNode defaultLabel = new LabelNode("default");
ByteCodeNode switchBlock;
if (constantValues.size() < 1000) {
Block switchCaseBlocks = new Block(context);
LookupSwitchBuilder switchBuilder = lookupSwitchBuilder();
for (Entry<Integer, Collection<ByteCodeNode>> bucket : hashBuckets.asMap().entrySet()) {
LabelNode label = new LabelNode("inHash" + bucket.getKey());
switchBuilder.addCase(bucket.getKey(), label);
Collection<ByteCodeNode> testValues = bucket.getValue();
Block caseBlock = buildInCase(context, type, label, match, defaultLabel, testValues, false);
switchCaseBlocks
.append(caseBlock.setDescription("case " + bucket.getKey()));
}
switchBuilder.defaultCase(defaultLabel);
switchBlock = new Block(context)
.comment("lookupSwitch(hashCode(<stackValue>))")
.dup(javaType)
.invokeDynamic(hashCodeFunction.getName(), hashCodeFunction.getCallSite().type(), hashCodeFunction.getBindingId())
.append(switchBuilder.build())
.append(switchCaseBlocks);
}
else {
// for huge IN lists, use a Set
FunctionBinding functionBinding = bootstrapFunctionBinder.bindFunction(
"in",
getSessionByteCode,
ImmutableList.<ByteCodeNode>of(),
new InFunctionBinder(javaType, constantValues));
switchBlock = new Block(context)
.comment("inListSet.contains(<stackValue>)")
.append(new IfStatement(context,
new Block(context).dup(javaType).invokeDynamic(functionBinding.getName(), functionBinding.getCallSite().type(), functionBinding.getBindingId()),
jump(match),
NOP));
}
Block defaultCaseBlock = buildInCase(context, type, defaultLabel, match, noMatch, defaultBucket.build(), true).setDescription("default");
Block block = new Block(context)
.comment(node.toString())
.append(value)
.append(ifWasNullPopAndGoto(context, end, boolean.class, javaType))
.append(switchBlock)
.append(defaultCaseBlock);
Block matchBlock = new Block(context)
.setDescription("match")
.visitLabel(match)
.pop(javaType)
.putVariable("wasNull", false)
.push(true)
.gotoLabel(end);
block.append(matchBlock);
Block noMatchBlock = new Block(context)
.setDescription("noMatch")
.visitLabel(noMatch)
.pop(javaType)
.push(false)
.gotoLabel(end);