621 return true;
622 }
623 return false;
624 }
625
626 /**
627 * Emit an invoke for the given name, using the MemberName directly.
628 */
629 void emitStaticInvoke(MemberName member, Name name) {
630 assert(member.equals(name.function.member()));
631 String cname = getInternalName(member.getDeclaringClass());
632 String mname = member.getName();
633 String mtype;
634 byte refKind = member.getReferenceKind();
635 if (refKind == REF_invokeSpecial) {
636 // in order to pass the verifier, we need to convert this to invokevirtual in all cases
637 assert(member.canBeStaticallyBound()) : member;
638 refKind = REF_invokeVirtual;
639 }
640
641 // push arguments
642 for (int i = 0; i < name.arguments.length; i++) {
643 emitPushArgument(name, i);
644 }
645
646 // invocation
647 if (member.isMethod()) {
648 mtype = member.getMethodType().toMethodDescriptorString();
649 mv.visitMethodInsn(refKindOpcode(refKind), cname, mname, mtype,
650 member.getDeclaringClass().isInterface());
651 } else {
652 mtype = MethodType.toFieldDescriptorString(member.getFieldType());
653 mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype);
654 }
655 }
656 int refKindOpcode(byte refKind) {
657 switch (refKind) {
658 case REF_invokeVirtual: return Opcodes.INVOKEVIRTUAL;
659 case REF_invokeStatic: return Opcodes.INVOKESTATIC;
660 case REF_invokeSpecial: return Opcodes.INVOKESPECIAL;
|
621 return true;
622 }
623 return false;
624 }
625
626 /**
627 * Emit an invoke for the given name, using the MemberName directly.
628 */
629 void emitStaticInvoke(MemberName member, Name name) {
630 assert(member.equals(name.function.member()));
631 String cname = getInternalName(member.getDeclaringClass());
632 String mname = member.getName();
633 String mtype;
634 byte refKind = member.getReferenceKind();
635 if (refKind == REF_invokeSpecial) {
636 // in order to pass the verifier, we need to convert this to invokevirtual in all cases
637 assert(member.canBeStaticallyBound()) : member;
638 refKind = REF_invokeVirtual;
639 }
640
641 if (member.getDeclaringClass().isInterface() && refKind == REF_invokeVirtual) {
642 // Methods from Object declared in an interface can be resolved by JVM to invokevirtual kind.
643 // Need to convert it back to invokeinterface to pass verification and make the invocation works as expected.
644 refKind = REF_invokeInterface;
645 }
646
647 // push arguments
648 for (int i = 0; i < name.arguments.length; i++) {
649 emitPushArgument(name, i);
650 }
651
652 // invocation
653 if (member.isMethod()) {
654 mtype = member.getMethodType().toMethodDescriptorString();
655 mv.visitMethodInsn(refKindOpcode(refKind), cname, mname, mtype,
656 member.getDeclaringClass().isInterface());
657 } else {
658 mtype = MethodType.toFieldDescriptorString(member.getFieldType());
659 mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype);
660 }
661 }
662 int refKindOpcode(byte refKind) {
663 switch (refKind) {
664 case REF_invokeVirtual: return Opcodes.INVOKEVIRTUAL;
665 case REF_invokeStatic: return Opcodes.INVOKESTATIC;
666 case REF_invokeSpecial: return Opcodes.INVOKESPECIAL;
|