1 21 package proguard.classfile.instruction; 22 23 import proguard.classfile.*; 24 import proguard.classfile.instruction.visitor.InstructionVisitor; 25 import proguard.classfile.attribute.*; 26 27 32 public abstract class Instruction 33 { 34 private static final boolean[] IS_CATEGORY2 = new boolean[] 36 { 37 false, false, false, false, false, false, false, false, false, true, true, false, false, false, true, true, false, false, false, false, true, false, true, false, true, false, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, false, false, true, true, true, false, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, false, false, false, true, true, true, false, false, false, true, true, true, false, false, false, true, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, }; 240 241 242 private static final int[] STACK_POP_COUNTS = new int[] 245 { 246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 3, 4, 3, 4, 3, 3, 3, 3, 1, 2, 1, 2, 3, 2, 3, 4, 2, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 1, 2, 1, 2, 2, 3, 2, 3, 2, 3, 2, 4, 2, 4, 2, 4, 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 4, 2, 2, 4, 4, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1, 1, 2, 1, 2, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, }; 449 450 451 private static final int[] STACK_PUSH_COUNTS = new int[] 454 { 455 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 4, 5, 6, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, }; 658 659 660 public byte opcode; 661 662 663 667 public byte canonicalOpcode() 668 { 669 return opcode; 670 } 671 672 673 677 public abstract Instruction shrink(); 678 679 680 681 684 public final void write(CodeAttribute codeAttribute, int offset) 685 { 686 write(codeAttribute.code, offset); 687 } 688 689 690 693 public final void write(byte[] code, int offset) 694 { 695 if (isWide()) 697 { 698 code[offset++] = InstructionConstants.OP_WIDE; 699 } 700 701 code[offset++] = opcode; 703 704 writeInfo(code, offset); 706 } 707 708 709 713 protected boolean isWide() 714 { 715 return false; 716 } 717 718 719 722 protected abstract void readInfo(byte[] code, int offset); 723 724 725 728 protected abstract void writeInfo(byte[] code, int offset); 729 730 731 734 public abstract int length(int offset); 735 736 737 740 public abstract void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor); 741 742 743 746 public String toString(int offset) 747 { 748 return "["+offset+"] "+ this.toString(); 749 } 750 751 752 755 public String getName() 756 { 757 return InstructionConstants.NAMES[opcode & 0xff]; 758 } 759 760 761 765 public boolean isCategory2() 766 { 767 return IS_CATEGORY2[opcode & 0xff]; 768 } 769 770 771 775 public int stackPopCount(Clazz clazz) 776 { 777 return STACK_POP_COUNTS[opcode & 0xff]; 778 } 779 780 781 785 public int stackPushCount(Clazz clazz) 786 { 787 return STACK_PUSH_COUNTS[opcode & 0xff]; 788 } 789 790 791 793 protected static int readByte(byte[] code, int offset) 794 { 795 return code[offset] & 0xff; 796 } 797 798 protected static int readShort(byte[] code, int offset) 799 { 800 return ((code[offset++] & 0xff) << 8) | 801 ( code[offset ] & 0xff ); 802 } 803 804 protected static int readInt(byte[] code, int offset) 805 { 806 return ( code[offset++] << 24) | 807 ((code[offset++] & 0xff) << 16) | 808 ((code[offset++] & 0xff) << 8) | 809 ( code[offset ] & 0xff ); 810 } 811 812 protected static int readValue(byte[] code, int offset, int valueSize) 813 { 814 switch (valueSize) 815 { 816 case 0: return 0; 817 case 1: return readByte( code, offset); 818 case 2: return readShort(code, offset); 819 case 4: return readInt( code, offset); 820 default: throw new IllegalArgumentException ("Unsupported value size ["+valueSize+"]"); 821 } 822 } 823 824 protected static int readSignedByte(byte[] code, int offset) 825 { 826 return code[offset]; 827 } 828 829 protected static int readSignedShort(byte[] code, int offset) 830 { 831 return (code[offset++] << 8) | 832 (code[offset ] & 0xff); 833 } 834 835 protected static int readSignedValue(byte[] code, int offset, int valueSize) 836 { 837 switch (valueSize) 838 { 839 case 0: return 0; 840 case 1: return readSignedByte( code, offset); 841 case 2: return readSignedShort(code, offset); 842 case 4: return readInt( code, offset); 843 default: throw new IllegalArgumentException ("Unsupported value size ["+valueSize+"]"); 844 } 845 } 846 847 protected static void writeByte(byte[] code, int offset, int value) 848 { 849 if (value > 0xff) 850 { 851 throw new IllegalArgumentException ("Unsigned byte value larger than 0xff ["+value+"]"); 852 } 853 854 code[offset] = (byte)value; 855 } 856 857 protected static void writeShort(byte[] code, int offset, int value) 858 { 859 if (value > 0xffff) 860 { 861 throw new IllegalArgumentException ("Unsigned short value larger than 0xffff ["+value+"]"); 862 } 863 864 code[offset++] = (byte)(value >> 8); 865 code[offset ] = (byte)(value ); 866 } 867 868 protected static void writeInt(byte[] code, int offset, int value) 869 { 870 code[offset++] = (byte)(value >> 24); 871 code[offset++] = (byte)(value >> 16); 872 code[offset++] = (byte)(value >> 8); 873 code[offset ] = (byte)(value ); 874 } 875 876 protected static void writeValue(byte[] code, int offset, int value, int valueSize) 877 { 878 switch (valueSize) 879 { 880 case 0: break; 881 case 1: writeByte( code, offset, value); break; 882 case 2: writeShort(code, offset, value); break; 883 case 4: writeInt( code, offset, value); break; 884 default: throw new IllegalArgumentException ("Unsupported value size ["+valueSize+"]"); 885 } 886 } 887 888 protected static void writeSignedByte(byte[] code, int offset, int value) 889 { 890 if (value << 24 >> 24 != value) 891 { 892 throw new IllegalArgumentException ("Signed byte value out of range ["+value+"]"); 893 } 894 895 code[offset] = (byte)value; 896 } 897 898 protected static void writeSignedShort(byte[] code, int offset, int value) 899 { 900 if (value << 16 >> 16 != value) 901 { 902 throw new IllegalArgumentException ("Signed short value out of range ["+value+"]"); 903 } 904 905 code[offset++] = (byte)(value >> 8); 906 code[offset ] = (byte)(value ); 907 } 908 909 protected static void writeSignedValue(byte[] code, int offset, int value, int valueSize) 910 { 911 switch (valueSize) 912 { 913 case 0: break; 914 case 1: writeSignedByte( code, offset, value); break; 915 case 2: writeSignedShort(code, offset, value); break; 916 case 4: writeInt( code, offset, value); break; 917 default: throw new IllegalArgumentException ("Unsupported value size ["+valueSize+"]"); 918 } 919 } 920 } 921 | Popular Tags |