From 9ad008dd309534b48cc2254eeb81f9974fbaa7ab Mon Sep 17 00:00:00 2001 From: "igor%mir2.org" Date: Fri, 8 Aug 2003 09:30:57 +0000 Subject: [PATCH] Added addPush(String) to generate code to push the given String into stack even if String does not fit the class file format restriction that JVM utf-8 encoding of strings in constant pool can not exceed 64K - 1. Also added addPush(int/double) for symmetry, they are copied here from omj/optimizer/Codegen.java. --- .../mozilla/classfile/ClassFileWriter.java | 122 +++++++++++++++--- 1 file changed, 106 insertions(+), 16 deletions(-) diff --git a/js/rhino/src/org/mozilla/classfile/ClassFileWriter.java b/js/rhino/src/org/mozilla/classfile/ClassFileWriter.java index 1a85a7e4e648..5534fe14d103 100644 --- a/js/rhino/src/org/mozilla/classfile/ClassFileWriter.java +++ b/js/rhino/src/org/mozilla/classfile/ClassFileWriter.java @@ -583,6 +583,86 @@ public class ClassFileWriter { add(ByteCode.LDC, itsConstantPool.addConstant(k)); } + /** + * Generate code to load the given integer on stack. + * + * @param k the constant + */ + public void addPush(int k) + { + if ((byte)k == k) { + if (k == -1) { + add(ByteCode.ICONST_M1); + } else if (0 <= k && k <= 5) { + add((byte)(ByteCode.ICONST_0 + k)); + } else { + add(ByteCode.BIPUSH, (byte)k); + } + } else if ((short)k == k) { + add(ByteCode.SIPUSH, (short)k); + } else { + addLoadConstant(k); + } + } + + /** + * Generate code to load the given double on stack. + * + * @param k the constant + */ + public void addPush(double k) + { + if (k == 0.0 && 1.0 / k >= 0.0) { + // Positive zero + add(ByteCode.DCONST_0); + } else if (k == 1.0) { + add(ByteCode.DCONST_1); + } else { + addLoadConstant(k); + } + } + + /** + * Generate the code to leave on stack the given string even if the + * string encoding exeeds the class file limit for single string constant + * + * @param k the constant + */ + public void addPush(String k) { + int length = k.length(); + int limit = itsConstantPool.getUtfEncodingLimit(k, 0, length); + if (limit == length) { + addLoadConstant(k); + return; + } + // Split string into picies fitting the UTF limit and generate code for + // StringBuffer sb = new StringBuffer(length); + // sb.append(loadConstant(piece_1)); + // ... + // sb.append(loadConstant(piece_N)); + // sb.toString(); + final String SB = "java/lang/StringBuffer"; + add(ByteCode.NEW, SB); + add(ByteCode.DUP); + addPush(length); + addInvoke(ByteCode.INVOKESTATIC, SB, "", "(I)V"); + int cursor = 0; + for (;;) { + add(ByteCode.DUP); + String s = k.substring(cursor, limit); + addLoadConstant(k); + addInvoke(ByteCode.INVOKEVIRTUAL, SB, "append", + "(Ljava/lang/String;)V"); + if (limit == length) { + break; + } + cursor = limit; + limit = itsConstantPool.getUtfEncodingLimit(k, limit, length); + } + addInvoke(ByteCode.INVOKEVIRTUAL, SB, "toString", + "()Ljava/lang/String;"); + } + /** * Check if k fits limit on string constant size imposed by class file * format. @@ -1641,31 +1721,41 @@ final class ConstantPool return (short)theIndex; } - boolean isUnderUtfEncodingLimit(String k) + boolean isUnderUtfEncodingLimit(String s) { - int strLen = k.length(); + int strLen = s.length(); if (strLen * 3 <= MAX_UTF_ENCODING_SIZE) { return true; } else if (strLen > MAX_UTF_ENCODING_SIZE) { return false; } + return strLen == getUtfEncodingLimit(s, 0, strLen); + } - char[] chars = getCharBuffer(strLen); - k.getChars(0, strLen, chars, 0); - - int utfLen = strLen; - for (int i = 0; i != strLen; i++) { - int c = chars[i]; - if (c == 0 || c > 0x7F) { - if (c < 0x7FF) { - ++utfLen; - } else { - utfLen += 2; - } + /** + * Get maximum i such that start <= i <= end and + * s.substring(start, i) fits JVM UTF string encoding limit. + */ + int getUtfEncodingLimit(String s, int start, int end) + { + if ((end - start) * 3 <= MAX_UTF_ENCODING_SIZE) { + return end; + } + int limit = MAX_UTF_ENCODING_SIZE; + for (int i = start; i != end; i++) { + int c = s.charAt(i); + if (0 != c && c <= 0x7F) { + --limit; + } else if (c < 0x7FF) { + limit -= 2; + } else { + limit -= 3; + } + if (limit < 0) { + return i; } } - - return utfLen <= 65535; + return end; } short addUtf8(String k)