< prev index next >

src/java.base/share/classes/java/lang/StringConcatHelper.java

Print this page
rev 52310 : 8213035: Pack MethodHandleInlineStrategy coder and length into a long
Reviewed-by: TBD


  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 /**
  29  * Helper for string concatenation. These methods are mostly looked up with private lookups
  30  * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
  31  * combinators there.
  32  */
  33 final class StringConcatHelper {
  34 
  35     private StringConcatHelper() {
  36         // no instantiation
  37     }
  38 
  39     /**
  40      * Check for overflow, throw the exception on overflow.
  41      * @param len String length
  42      * @return length
  43      */
  44     private static int checkOverflow(int len) {
  45         if (len < 0) {
  46             throw new OutOfMemoryError("Overflow: String length out of range");
  47         }
  48         return len;
  49     }
  50 
  51     /**
  52      * Mix value length into current length
  53      * @param current current length
  54      * @param value   value to mix in
  55      * @return new length
  56      */
  57     static int mixLen(int current, boolean value) {
  58         return checkOverflow(current + (value ? 4 : 5));
  59     }
  60 
  61     /**
  62      * Mix value length into current length
  63      * @param current current length
  64      * @param value   value to mix in
  65      * @return new length
  66      */
  67     static int mixLen(int current, byte value) {
  68         return mixLen(current, (int)value);
  69     }
  70 
  71     /**
  72      * Mix value length into current length
  73      * @param current current length
  74      * @param value   value to mix in
  75      * @return new length
  76      */
  77     static int mixLen(int current, char value) {
  78         return checkOverflow(current + 1);
  79     }
  80 
  81     /**
  82      * Mix value length into current length
  83      * @param current current length
  84      * @param value   value to mix in
  85      * @return new length
  86      */
  87     static int mixLen(int current, short value) {
  88         return mixLen(current, (int)value);
  89     }
  90 
  91     /**
  92      * Mix value length into current length
  93      * @param current current length
  94      * @param value   value to mix in
  95      * @return new length
  96      */
  97     static int mixLen(int current, int value) {
  98         return checkOverflow(current + Integer.stringSize(value));
  99     }
 100 
 101     /**
 102      * Mix value length into current length
 103      * @param current current length
 104      * @param value   value to mix in
 105      * @return new length
 106      */
 107     static int mixLen(int current, long value) {
 108         return checkOverflow(current + Long.stringSize(value));
 109     }
 110 
 111     /**
 112      * Mix value length into current length
 113      * @param current current length
 114      * @param value   value to mix in
 115      * @return new length
 116      */
 117     static int mixLen(int current, String value) {
 118         return checkOverflow(current + value.length());


 119     }
 120 
 121     /**
 122      * Mix coder into current coder
 123      * @param current current coder
 124      * @param value   value to mix in
 125      * @return new coder
 126      */
 127     static byte mixCoder(byte current, char value) {
 128         return (byte)(current | (StringLatin1.canEncode(value) ? 0 : 1));
 129     }
 130 
 131     /**
 132      * Mix coder into current coder
 133      * @param current current coder
 134      * @param value   value to mix in
 135      * @return new coder
 136      */
 137     static byte mixCoder(byte current, String value) {
 138         return (byte)(current | value.coder());
 139     }
 140 
 141     /**
 142      * Prepends the stringly representation of boolean value into buffer,
 143      * given the coder and final index. Index is measured in chars, not in bytes!
 144      *
 145      * @param index final char index in the buffer

 146      * @param buf   buffer to append to
 147      * @param coder coder to add with
 148      * @param value boolean value to encode
 149      * @return new index
 150      */
 151     static int prepend(int index, byte[] buf, byte coder, boolean value) {
 152         if (coder == String.LATIN1) {

 153             if (value) {
 154                 buf[--index] = 'e';
 155                 buf[--index] = 'u';
 156                 buf[--index] = 'r';
 157                 buf[--index] = 't';
 158             } else {
 159                 buf[--index] = 'e';
 160                 buf[--index] = 's';
 161                 buf[--index] = 'l';
 162                 buf[--index] = 'a';
 163                 buf[--index] = 'f';
 164             }

 165         } else {
 166             if (value) {
 167                 StringUTF16.putChar(buf, --index, 'e');
 168                 StringUTF16.putChar(buf, --index, 'u');
 169                 StringUTF16.putChar(buf, --index, 'r');
 170                 StringUTF16.putChar(buf, --index, 't');
 171             } else {
 172                 StringUTF16.putChar(buf, --index, 'e');
 173                 StringUTF16.putChar(buf, --index, 's');
 174                 StringUTF16.putChar(buf, --index, 'l');
 175                 StringUTF16.putChar(buf, --index, 'a');
 176                 StringUTF16.putChar(buf, --index, 'f');
 177             }

 178         }
 179         return index;
 180     }
 181 
 182     /**
 183      * Prepends the stringly representation of byte value into buffer,
 184      * given the coder and final index. Index is measured in chars, not in bytes!
 185      *
 186      * @param index final char index in the buffer

 187      * @param buf   buffer to append to
 188      * @param coder coder to add with
 189      * @param value byte value to encode
 190      * @return new index
 191      */
 192     static int prepend(int index, byte[] buf, byte coder, byte value) {
 193         return prepend(index, buf, coder, (int)value);
 194     }
 195 
 196     /**
 197      * Prepends the stringly representation of char value into buffer,
 198      * given the coder and final index. Index is measured in chars, not in bytes!
 199      *
 200      * @param index final char index in the buffer

 201      * @param buf   buffer to append to
 202      * @param coder coder to add with
 203      * @param value char value to encode
 204      * @return new index
 205      */
 206     static int prepend(int index, byte[] buf, byte coder, char value) {
 207         if (coder == String.LATIN1) {
 208             buf[--index] = (byte) (value & 0xFF);
 209         } else {
 210             StringUTF16.putChar(buf, --index, value);
 211         }
 212         return index;
 213     }
 214 
 215     /**
 216      * Prepends the stringly representation of short value into buffer,
 217      * given the coder and final index. Index is measured in chars, not in bytes!
 218      *
 219      * @param index final char index in the buffer

 220      * @param buf   buffer to append to
 221      * @param coder coder to add with
 222      * @param value short value to encode
 223      * @return new index
 224      */
 225     static int prepend(int index, byte[] buf, byte coder, short value) {
 226         return prepend(index, buf, coder, (int)value);
 227     }
 228 
 229     /**
 230      * Prepends the stringly representation of integer value into buffer,
 231      * given the coder and final index. Index is measured in chars, not in bytes!
 232      *
 233      * @param index final char index in the buffer

 234      * @param buf   buffer to append to
 235      * @param coder coder to add with
 236      * @param value integer value to encode
 237      * @return new index
 238      */
 239     static int prepend(int index, byte[] buf, byte coder, int value) {
 240         if (coder == String.LATIN1) {
 241             return Integer.getChars(value, index, buf);
 242         } else {
 243             return StringUTF16.getChars(value, index, buf);
 244         }
 245     }
 246 
 247     /**
 248      * Prepends the stringly representation of long value into buffer,
 249      * given the coder and final index. Index is measured in chars, not in bytes!
 250      *
 251      * @param index final char index in the buffer

 252      * @param buf   buffer to append to
 253      * @param coder coder to add with
 254      * @param value long value to encode
 255      * @return new index
 256      */
 257     static int prepend(int index, byte[] buf, byte coder, long value) {
 258         if (coder == String.LATIN1) {
 259             return Long.getChars(value, index, buf);
 260         } else {
 261             return StringUTF16.getChars(value, index, buf);
 262         }
 263     }
 264 
 265     /**
 266      * Prepends the stringly representation of String value into buffer,
 267      * given the coder and final index. Index is measured in chars, not in bytes!
 268      *
 269      * @param index final char index in the buffer

 270      * @param buf   buffer to append to
 271      * @param coder coder to add with
 272      * @param value String value to encode
 273      * @return new index
 274      */
 275     static int prepend(int index, byte[] buf, byte coder, String value) {
 276         index -= value.length();
 277         value.getBytes(buf, index, coder);
 278         return index;




 279     }
 280 
 281     /**
 282      * Instantiates the String with given buffer and coder
 283      * @param buf     buffer to use
 284      * @param index   remaining index
 285      * @param coder   coder to use
 286      * @return String resulting string
 287      */
 288     static String newString(byte[] buf, int index, byte coder) {
 289         // Use the private, non-copying constructor (unsafe!)
 290         if (index != 0) {
 291             throw new InternalError("Storage is not completely initialized, " + index + " bytes left");




 292         }
 293         return new String(buf, coder);
 294     }
 295 




 296     /**
 297      * Provides the initial coder for the String.
 298      * @return initial coder
 299      */
 300     static byte initialCoder() {
 301         return String.COMPACT_STRINGS ? String.LATIN1 : String.UTF16;
 302     }
 303 
 304 }


  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 /**
  29  * Helper for string concatenation. These methods are mostly looked up with private lookups
  30  * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
  31  * combinators there.
  32  */
  33 final class StringConcatHelper {
  34 
  35     private StringConcatHelper() {
  36         // no instantiation
  37     }
  38 
  39     /**
  40      * Check for overflow, throw exception on overflow.
  41      * @param lengthCoder String length and coder
  42      * @return lengthCoder
  43      */
  44     private static long checkOverflow(long lengthCoder) {
  45         if ((int)lengthCoder >= 0) {
  46             return lengthCoder;
  47         }
  48         throw new OutOfMemoryError("Overflow: String length out of range");
  49     }
  50 
  51     /**
  52      * Mix value length and coder into current length and coder.
  53      * @param current current length
  54      * @param value   value to mix in
  55      * @return new length and coder
  56      */
  57     static long mix(long current, boolean value) {
  58         return checkOverflow(current + (value ? 4 : 5));
  59     }
  60 
  61     /**
  62      * Mix value length and coder into current length and coder.
  63      * @param current current length
  64      * @param value   value to mix in
  65      * @return new length and coder
  66      */
  67     static long mix(long current, byte value) {
  68         return mix(current, (int)value);
  69     }
  70 
  71     /**
  72      * Mix value length and coder into current length and coder.
  73      * @param current current length
  74      * @param value   value to mix in
  75      * @return new length and coder
  76      */
  77     static long mix(long current, char value) {
  78         return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
  79     }
  80 
  81     /**
  82      * Mix value length and coder into current length and coder.
  83      * @param current current length
  84      * @param value   value to mix in
  85      * @return new length and coder
  86      */
  87     static long mix(long current, short value) {
  88         return mix(current, (int)value);
  89     }
  90 
  91     /**
  92      * Mix value length and coder into current length and coder.
  93      * @param current current length
  94      * @param value   value to mix in
  95      * @return new length and coder
  96      */
  97     static long mix(long current, int value) {
  98         return checkOverflow(current + Integer.stringSize(value));
  99     }
 100 
 101     /**
 102      * Mix value length and coder into current length and coder.
 103      * @param current current length
 104      * @param value   value to mix in
 105      * @return new length and coder
 106      */
 107     static long mix(long current, long value) {
 108         return checkOverflow(current + Long.stringSize(value));
 109     }
 110 
 111     /**
 112      * Mix value length and coder into current length and coder.
 113      * @param current current length
 114      * @param value   value to mix in
 115      * @return new length and coder
 116      */
 117     static long mix(long current, String value) {
 118         current += value.length();
 119         if (value.coder() == String.UTF16) {
 120             current |= UTF16;
 121         }
 122         return checkOverflow(current);


















 123     }
 124 
 125     /**
 126      * Prepends the stringly representation of boolean value into buffer,
 127      * given the coder and final index. Index is measured in chars, not in bytes!
 128      *
 129      * @param indexCoder final char index in the buffer, along with coder packed
 130      *                   into higher bits.
 131      * @param buf        buffer to append to

 132      * @param value      boolean value to encode
 133      * @return           updated index (coder value retained)
 134      */
 135     static long prepend(long indexCoder, byte[] buf, boolean value) {
 136         int index = (int)indexCoder;
 137         if (indexCoder < UTF16) {
 138             if (value) {
 139                 buf[--index] = 'e';
 140                 buf[--index] = 'u';
 141                 buf[--index] = 'r';
 142                 buf[--index] = 't';
 143             } else {
 144                 buf[--index] = 'e';
 145                 buf[--index] = 's';
 146                 buf[--index] = 'l';
 147                 buf[--index] = 'a';
 148                 buf[--index] = 'f';
 149             }
 150             return index;
 151         } else {
 152             if (value) {
 153                 StringUTF16.putChar(buf, --index, 'e');
 154                 StringUTF16.putChar(buf, --index, 'u');
 155                 StringUTF16.putChar(buf, --index, 'r');
 156                 StringUTF16.putChar(buf, --index, 't');
 157             } else {
 158                 StringUTF16.putChar(buf, --index, 'e');
 159                 StringUTF16.putChar(buf, --index, 's');
 160                 StringUTF16.putChar(buf, --index, 'l');
 161                 StringUTF16.putChar(buf, --index, 'a');
 162                 StringUTF16.putChar(buf, --index, 'f');
 163             }
 164             return index | UTF16;
 165         }

 166     }
 167 
 168     /**
 169      * Prepends the stringly representation of byte value into buffer,
 170      * given the coder and final index. Index is measured in chars, not in bytes!
 171      *
 172      * @param indexCoder final char index in the buffer, along with coder packed
 173      *                   into higher bits.
 174      * @param buf        buffer to append to

 175      * @param value      byte value to encode
 176      * @return           updated index (coder value retained)
 177      */
 178     static long prepend(long indexCoder, byte[] buf, byte value) {
 179         return prepend(indexCoder, buf, (int)value);
 180     }
 181 
 182     /**
 183      * Prepends the stringly representation of char value into buffer,
 184      * given the coder and final index. Index is measured in chars, not in bytes!
 185      *
 186      * @param indexCoder final char index in the buffer, along with coder packed
 187      *                   into higher bits.
 188      * @param buf        buffer to append to

 189      * @param value      char value to encode
 190      * @return           updated index (coder value retained)
 191      */
 192     static long prepend(long indexCoder, byte[] buf, char value) {
 193         if (indexCoder < UTF16) {
 194             buf[(int)(--indexCoder)] = (byte) (value & 0xFF);
 195         } else {
 196             StringUTF16.putChar(buf, (int)(--indexCoder), value);
 197         }
 198         return indexCoder;
 199     }
 200 
 201     /**
 202      * Prepends the stringly representation of short value into buffer,
 203      * given the coder and final index. Index is measured in chars, not in bytes!
 204      *
 205      * @param indexCoder final char index in the buffer, along with coder packed
 206      *                   into higher bits.
 207      * @param buf        buffer to append to

 208      * @param value      short value to encode
 209      * @return           updated index (coder value retained)
 210      */
 211     static long prepend(long indexCoder, byte[] buf, short value) {
 212         return prepend(indexCoder, buf, (int)value);
 213     }
 214 
 215     /**
 216      * Prepends the stringly representation of integer value into buffer,
 217      * given the coder and final index. Index is measured in chars, not in bytes!
 218      *
 219      * @param indexCoder final char index in the buffer, along with coder packed
 220      *                   into higher bits.
 221      * @param buf        buffer to append to

 222      * @param value      integer value to encode
 223      * @return           updated index (coder value retained)
 224      */
 225     static long prepend(long indexCoder, byte[] buf, int value) {
 226         if (indexCoder < UTF16) {
 227             return Integer.getChars(value, (int)indexCoder, buf);
 228         } else {
 229             return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16;
 230         }
 231     }
 232 
 233     /**
 234      * Prepends the stringly representation of long value into buffer,
 235      * given the coder and final index. Index is measured in chars, not in bytes!
 236      *
 237      * @param indexCoder final char index in the buffer, along with coder packed
 238      *                   into higher bits.
 239      * @param buf        buffer to append to

 240      * @param value      long value to encode
 241      * @return           updated index (coder value retained)
 242      */
 243     static long prepend(long indexCoder, byte[] buf, long value) {
 244         if (indexCoder < UTF16) {
 245             return Long.getChars(value, (int)indexCoder, buf);
 246         } else {
 247             return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16;
 248         }
 249     }
 250 
 251     /**
 252      * Prepends the stringly representation of String value into buffer,
 253      * given the coder and final index. Index is measured in chars, not in bytes!
 254      *
 255      * @param indexCoder final char index in the buffer, along with coder packed
 256      *                   into higher bits.
 257      * @param buf        buffer to append to

 258      * @param value      String value to encode
 259      * @return           updated index (coder value retained)
 260      */
 261     static long prepend(long indexCoder, byte[] buf, String value) {
 262         indexCoder -= value.length();
 263         if (indexCoder < UTF16) {
 264             value.getBytes(buf, (int)indexCoder, String.LATIN1);
 265         } else {
 266             value.getBytes(buf, (int)indexCoder, String.UTF16);
 267         }
 268         return indexCoder;
 269     }
 270 
 271     /**
 272      * Instantiates the String with given buffer and coder
 273      * @param buf           buffer to use
 274      * @param indexCoder    remaining index (should be zero) and coder

 275      * @return String       resulting string
 276      */
 277     static String newString(byte[] buf, long indexCoder) {
 278         // Use the private, non-copying constructor (unsafe!)
 279         if (indexCoder == LATIN1) {
 280             return new String(buf, String.LATIN1);
 281         } else if (indexCoder == UTF16) {
 282             return new String(buf, String.UTF16);
 283         } else {
 284             throw new InternalError("Storage is not completely initialized, " + (int)indexCoder + " bytes left");
 285         }

 286     }
 287 
 288     private static final long LATIN1 = (long)String.LATIN1 << 32;
 289 
 290     private static final long UTF16 = (long)String.UTF16 << 32;
 291 
 292     /**
 293      * Provides the initial coder for the String.
 294      * @return initial coder, adjusted into the upper half
 295      */
 296     static long initialCoder() {
 297         return String.COMPACT_STRINGS ? LATIN1 : UTF16;
 298     }
 299 
 300 }
< prev index next >