955 Exactness checks compare the final StringBuilder.capacity() with a resulting |
955 Exactness checks compare the final StringBuilder.capacity() with a resulting |
956 String.length(). If these values disagree, that means StringBuilder had to perform |
956 String.length(). If these values disagree, that means StringBuilder had to perform |
957 storage trimming, which defeats the purpose of exact strategies. |
957 storage trimming, which defeats the purpose of exact strategies. |
958 */ |
958 */ |
959 |
959 |
|
960 /* |
|
961 The logic for this check is as follows: |
|
962 |
|
963 Stack before: Op: |
|
964 (SB) dup, dup |
|
965 (SB, SB, SB) capacity() |
|
966 (int, SB, SB) swap |
|
967 (SB, int, SB) toString() |
|
968 (S, int, SB) length() |
|
969 (int, int, SB) if_icmpeq |
|
970 (SB) <end> |
|
971 |
|
972 Note that it leaves the same StringBuilder on exit, like the one on enter. |
|
973 */ |
|
974 |
|
975 mv.visitInsn(DUP); |
960 mv.visitInsn(DUP); |
976 mv.visitInsn(DUP); |
961 |
977 |
962 mv.visitMethodInsn( |
978 mv.visitMethodInsn( |
963 INVOKEVIRTUAL, |
979 INVOKEVIRTUAL, |
964 "java/lang/StringBuilder", |
980 "java/lang/StringBuilder", |
965 "capacity", |
981 "capacity", |
966 "()I", |
982 "()I", |
967 false |
983 false |
968 ); |
984 ); |
969 |
985 |
970 mv.visitIntInsn(ISTORE, 0); |
986 mv.visitInsn(SWAP); |
971 |
987 |
972 mv.visitMethodInsn( |
988 mv.visitMethodInsn( |
973 INVOKEVIRTUAL, |
989 INVOKEVIRTUAL, |
974 "java/lang/StringBuilder", |
990 "java/lang/StringBuilder", |
975 "toString", |
991 "toString", |
976 "()Ljava/lang/String;", |
992 "()Ljava/lang/String;", |
977 false |
993 false |
978 ); |
994 ); |
979 |
995 |
980 mv.visitInsn(DUP); |
|
981 |
|
982 mv.visitMethodInsn( |
996 mv.visitMethodInsn( |
983 INVOKEVIRTUAL, |
997 INVOKEVIRTUAL, |
984 "java/lang/String", |
998 "java/lang/String", |
985 "length", |
999 "length", |
986 "()I", |
1000 "()I", |
987 false |
1001 false |
988 ); |
1002 ); |
989 |
|
990 mv.visitIntInsn(ILOAD, 0); |
|
991 |
1003 |
992 Label l0 = new Label(); |
1004 Label l0 = new Label(); |
993 mv.visitJumpInsn(IF_ICMPEQ, l0); |
1005 mv.visitJumpInsn(IF_ICMPEQ, l0); |
994 |
1006 |
995 mv.visitTypeInsn(NEW, "java/lang/AssertionError"); |
1007 mv.visitTypeInsn(NEW, "java/lang/AssertionError"); |
1001 "(Ljava/lang/Object;)V", |
1013 "(Ljava/lang/Object;)V", |
1002 false); |
1014 false); |
1003 mv.visitInsn(ATHROW); |
1015 mv.visitInsn(ATHROW); |
1004 |
1016 |
1005 mv.visitLabel(l0); |
1017 mv.visitLabel(l0); |
1006 } else { |
1018 } |
1007 mv.visitMethodInsn( |
1019 |
1008 INVOKEVIRTUAL, |
1020 mv.visitMethodInsn( |
1009 "java/lang/StringBuilder", |
1021 INVOKEVIRTUAL, |
1010 "toString", |
1022 "java/lang/StringBuilder", |
1011 "()Ljava/lang/String;", |
1023 "toString", |
1012 false |
1024 "()Ljava/lang/String;", |
1013 ); |
1025 false |
1014 } |
1026 ); |
1015 |
1027 |
1016 mv.visitInsn(ARETURN); |
1028 mv.visitInsn(ARETURN); |
1017 |
1029 |
1018 mv.visitMaxs(-1, -1); |
1030 mv.visitMaxs(-1, -1); |
1019 mv.visitEnd(); |
1031 mv.visitEnd(); |