1 /* 2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 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 import jdk.internal.misc.Unsafe; 29 import jdk.internal.vm.annotation.ForceInline; 30 31 /** 32 * Helper for string concatenation. These methods are mostly looked up with private lookups 33 * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle} 34 * combinators there. 35 */ 36 final class StringConcatHelper { 37 38 private StringConcatHelper() { 39 // no instantiation 40 } 41 42 /** 43 * Check for overflow, throw exception on overflow. 44 * 45 * @param lengthCoder String length with coder packed into higher bits 46 * the upper word. 47 * @return the given parameter value, if valid 48 */ 49 private static long checkOverflow(long lengthCoder) { 50 if ((int)lengthCoder >= 0) { 51 return lengthCoder; 52 } 53 throw new OutOfMemoryError("Overflow: String length out of range"); 54 } 55 56 /** 57 * Mix value length and coder into current length and coder. 58 * @param lengthCoder String length with coder packed into higher bits 59 * the upper word. 60 * @param value value to mix in 61 * @return new length and coder 62 */ 63 static long mix(long lengthCoder, boolean value) { 64 return checkOverflow(lengthCoder + (value ? 4 : 5)); 65 } 66 67 /** 68 * Mix value length and coder into current length and coder. 69 * @param lengthCoder String length with coder packed into higher bits 70 * the upper word. 71 * @param value value to mix in 72 * @return new length and coder 73 */ 74 static long mix(long lengthCoder, byte value) { 75 return mix(lengthCoder, (int)value); 76 } 77 78 /** 79 * Mix value length and coder into current length and coder. 80 * @param lengthCoder String length with coder packed into higher bits 81 * the upper word. 82 * @param value value to mix in 83 * @return new length and coder 84 */ 85 static long mix(long lengthCoder, char value) { 86 return checkOverflow(lengthCoder + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16); 87 } 88 89 /** 90 * Mix value length and coder into current length and coder. 91 * @param lengthCoder String length with coder packed into higher bits 92 * the upper word. 93 * @param value value to mix in 94 * @return new length and coder 95 */ 96 static long mix(long lengthCoder, short value) { 97 return mix(lengthCoder, (int)value); 98 } 99 100 /** 101 * Mix value length and coder into current length and coder. 102 * @param lengthCoder String length with coder packed into higher bits 103 * the upper word. 104 * @param value value to mix in 105 * @return new length and coder 106 */ 107 static long mix(long lengthCoder, int value) { 108 return checkOverflow(lengthCoder + Integer.stringSize(value)); 109 } 110 111 /** 112 * Mix value length and coder into current length and coder. 113 * @param lengthCoder String length with coder packed into higher bits 114 * the upper word. 115 * @param value value to mix in 116 * @return new length and coder 117 */ 118 static long mix(long lengthCoder, long value) { 119 return checkOverflow(lengthCoder + Long.stringSize(value)); 120 } 121 122 /** 123 * Mix value length and coder into current length and coder. 124 * @param lengthCoder String length with coder packed into higher bits 125 * the upper word. 126 * @param value value to mix in 127 * @return new length and coder 128 */ 129 static long mix(long lengthCoder, String value) { 130 lengthCoder += value.length(); 131 if (value.coder() == String.UTF16) { 132 lengthCoder |= UTF16; 133 } 134 return checkOverflow(lengthCoder); 135 } 136 137 /** 138 * Prepends the stringly representation of boolean value into buffer, 139 * given the coder and final index. Index is measured in chars, not in bytes! 140 * 141 * @param indexCoder final char index in the buffer, along with coder packed 142 * into higher bits. 143 * @param buf buffer to append to 144 * @param value boolean value to encode 145 * @return updated index (coder value retained) 146 */ 147 static long prepend(long indexCoder, byte[] buf, boolean value) { 148 int index = (int)indexCoder; 149 if (indexCoder < UTF16) { 150 if (value) { 151 buf[--index] = 'e'; 152 buf[--index] = 'u'; 153 buf[--index] = 'r'; 154 buf[--index] = 't'; 155 } else { 156 buf[--index] = 'e'; 157 buf[--index] = 's'; 158 buf[--index] = 'l'; 159 buf[--index] = 'a'; 160 buf[--index] = 'f'; 161 } 162 return index; 163 } else { 164 if (value) { 165 StringUTF16.putChar(buf, --index, 'e'); 166 StringUTF16.putChar(buf, --index, 'u'); 167 StringUTF16.putChar(buf, --index, 'r'); 168 StringUTF16.putChar(buf, --index, 't'); 169 } else { 170 StringUTF16.putChar(buf, --index, 'e'); 171 StringUTF16.putChar(buf, --index, 's'); 172 StringUTF16.putChar(buf, --index, 'l'); 173 StringUTF16.putChar(buf, --index, 'a'); 174 StringUTF16.putChar(buf, --index, 'f'); 175 } 176 return index | UTF16; 177 } 178 } 179 180 /** 181 * Prepends the stringly representation of byte value into buffer, 182 * given the coder and final index. Index is measured in chars, not in bytes! 183 * 184 * @param indexCoder final char index in the buffer, along with coder packed 185 * into higher bits. 186 * @param buf buffer to append to 187 * @param value byte value to encode 188 * @return updated index (coder value retained) 189 */ 190 static long prepend(long indexCoder, byte[] buf, byte value) { 191 return prepend(indexCoder, buf, (int)value); 192 } 193 194 /** 195 * Prepends the stringly representation of char value into buffer, 196 * given the coder and final index. Index is measured in chars, not in bytes! 197 * 198 * @param indexCoder final char index in the buffer, along with coder packed 199 * into higher bits. 200 * @param buf buffer to append to 201 * @param value char value to encode 202 * @return updated index (coder value retained) 203 */ 204 static long prepend(long indexCoder, byte[] buf, char value) { 205 if (indexCoder < UTF16) { 206 buf[(int)(--indexCoder)] = (byte) (value & 0xFF); 207 } else { 208 StringUTF16.putChar(buf, (int)(--indexCoder), value); 209 } 210 return indexCoder; 211 } 212 213 /** 214 * Prepends the stringly representation of short value into buffer, 215 * given the coder and final index. Index is measured in chars, not in bytes! 216 * 217 * @param indexCoder final char index in the buffer, along with coder packed 218 * into higher bits. 219 * @param buf buffer to append to 220 * @param value short value to encode 221 * @return updated index (coder value retained) 222 */ 223 static long prepend(long indexCoder, byte[] buf, short value) { 224 return prepend(indexCoder, buf, (int)value); 225 } 226 227 /** 228 * Prepends the stringly representation of integer value into buffer, 229 * given the coder and final index. Index is measured in chars, not in bytes! 230 * 231 * @param indexCoder final char index in the buffer, along with coder packed 232 * into higher bits. 233 * @param buf buffer to append to 234 * @param value integer value to encode 235 * @return updated index (coder value retained) 236 */ 237 static long prepend(long indexCoder, byte[] buf, int value) { 238 if (indexCoder < UTF16) { 239 return Integer.getChars(value, (int)indexCoder, buf); 240 } else { 241 return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16; 242 } 243 } 244 245 /** 246 * Prepends the stringly representation of long value into buffer, 247 * given the coder and final index. Index is measured in chars, not in bytes! 248 * 249 * @param indexCoder final char index in the buffer, along with coder packed 250 * into higher bits. 251 * @param buf buffer to append to 252 * @param value long value to encode 253 * @return updated index (coder value retained) 254 */ 255 static long prepend(long indexCoder, byte[] buf, long value) { 256 if (indexCoder < UTF16) { 257 return Long.getChars(value, (int)indexCoder, buf); 258 } else { 259 return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16; 260 } 261 } 262 263 /** 264 * Prepends the stringly representation of String value into buffer, 265 * given the coder and final index. Index is measured in chars, not in bytes! 266 * 267 * @param indexCoder final char index in the buffer, along with coder packed 268 * into higher bits. 269 * @param buf buffer to append to 270 * @param value String value to encode 271 * @return updated index (coder value retained) 272 */ 273 static long prepend(long indexCoder, byte[] buf, String value) { 274 indexCoder -= value.length(); 275 if (indexCoder < UTF16) { 276 value.getBytes(buf, (int)indexCoder, String.LATIN1); 277 } else { 278 value.getBytes(buf, (int)indexCoder, String.UTF16); 279 } 280 return indexCoder; 281 } 282 283 /** 284 * Instantiates the String with given buffer and coder 285 * @param buf buffer to use 286 * @param indexCoder remaining index (should be zero) and coder 287 * @return String resulting string 288 */ 289 static String newString(byte[] buf, long indexCoder) { 290 // Use the private, non-copying constructor (unsafe!) 291 if (indexCoder == LATIN1) { 292 return new String(buf, String.LATIN1); 293 } else if (indexCoder == UTF16) { 294 return new String(buf, String.UTF16); 295 } else { 296 throw new InternalError("Storage is not completely initialized, " + (int)indexCoder + " bytes left"); 297 } 298 } 299 300 /** 301 * Perform a simple concatenation between two objects. Added for startup 302 * performance, but also demonstrates the code that would be emitted by 303 * {@code java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy} 304 * for two Object arguments. 305 * 306 * @param first first argument 307 * @param second second argument 308 * @return String resulting string 309 */ 310 @ForceInline 311 static String simpleConcat(Object first, Object second) { 312 String s1 = stringOf(first); 313 String s2 = stringOf(second); 314 // start "mixing" in length and coder or arguments, order is not 315 // important 316 long indexCoder = mix(initialCoder(), s2); 317 indexCoder = mix(indexCoder, s1); 318 byte[] buf = newArray(indexCoder); 319 // prepend each argument in reverse order, since we prepending 320 // from the end of the byte array 321 indexCoder = prepend(indexCoder, buf, s2); 322 indexCoder = prepend(indexCoder, buf, s1); 323 return newString(buf, indexCoder); 324 } 325 326 /** 327 * We need some additional conversion for Objects in general, because 328 * {@code String.valueOf(Object)} may return null. String conversion rules 329 * in Java state we need to produce "null" String in this case, so we 330 * provide a customized version that deals with this problematic corner case. 331 */ 332 static String stringOf(Object value) { 333 String s; 334 return (value == null || (s = value.toString()) == null) ? "null" : s; 335 } 336 337 private static final long LATIN1 = (long)String.LATIN1 << 32; 338 339 private static final long UTF16 = (long)String.UTF16 << 32; 340 341 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 342 343 /** 344 * Allocates an uninitialized byte array based on the length and coder information 345 * in indexCoder 346 * @param indexCoder 347 * @return the newly allocated byte array 348 */ 349 @ForceInline 350 static byte[] newArray(long indexCoder) { 351 byte coder = (byte)(indexCoder >> 32); 352 int index = (int)indexCoder; 353 return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder); 354 } 355 356 /** 357 * Provides the initial coder for the String. 358 * @return initial coder, adjusted into the upper half 359 */ 360 static long initialCoder() { 361 return String.COMPACT_STRINGS ? LATIN1 : UTF16; 362 } 363 364 }