/** * Emit bytecode for the selectAlternative idiom. * * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest): * <blockquote><pre>{@code * Lambda(a0:L,a1:I)=>{ * t2:I=foo.test(a1:I); * t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int)); * t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I} * }</pre></blockquote> */ private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { //assert isStaticallyInvocable(invokeBasicName); Name receiver = (Name)invokeBasicName.arguments[0]; CodeEmitterLabel L_fallback = ilgen.DefineLabel(); CodeEmitterLabel L_done = ilgen.DefineLabel(); // load test result emitPushArgument(selectAlternativeName, 0); // if_icmpne L_fallback ilgen.EmitBrfalse(L_fallback); // invoke selectAlternativeName.arguments[1] //Class<?>[] preForkClasses = localClasses.clone(); emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot emitStaticInvoke(invokeBasicName); // goto L_done ilgen.EmitBr(L_done); // L_fallback: ilgen.MarkLabel(L_fallback); // invoke selectAlternativeName.arguments[2] //System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot emitStaticInvoke(invokeBasicName); // L_done: ilgen.MarkLabel(L_done); // for now do not bother to merge typestate; just reset to the dominator state //System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); return(invokeBasicName); // return what's on stack }
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) { ilgen.EmitBrfalse(label); }