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 import java.lang.invoke.MethodHandle; 32 import java.lang.invoke.MethodHandles; 33 import java.lang.invoke.MethodType; 34 35 /** 36 * Helper for string concatenation. These methods are mostly looked up with private lookups 37 * from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle} 38 * combinators there. 39 */ 40 final class StringConcatHelper { 41 42 private StringConcatHelper() { 43 // no instantiation 44 } 45 46 /** 47 * Check for overflow, throw exception on overflow. 48 * 49 * @param lengthCoder String length with coder packed into higher bits 50 * the upper word. 51 * @return the given parameter value, if valid 52 */ 53 private static long checkOverflow(long lengthCoder) { 54 if ((int)lengthCoder >= 0) { 55 return lengthCoder; 56 } 57 throw new OutOfMemoryError("Overflow: String length out of range"); 58 } 59 60 /** 61 * Mix value length and coder into current length and coder. 62 * @param lengthCoder String length with coder packed into higher bits 63 * the upper word. 64 * @param value value to mix in 65 * @return new length and coder 66 */ 67 static long mix(long lengthCoder, boolean value) { 68 return checkOverflow(lengthCoder + (value ? 4 : 5)); 69 } 70 71 /** 72 * Mix value length and coder into current length and coder. 73 * @param lengthCoder String length with coder packed into higher bits 74 * the upper word. 75 * @param value value to mix in 76 * @return new length and coder 77 */ 78 static long mix(long lengthCoder, byte value) { 79 return mix(lengthCoder, (int)value); 80 } 81 82 /** 83 * Mix value length and coder into current length and coder. 84 * @param lengthCoder String length with coder packed into higher bits 85 * the upper word. 86 * @param value value to mix in 87 * @return new length and coder 88 */ 89 static long mix(long lengthCoder, char value) { 90 return checkOverflow(lengthCoder + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16); 91 } 92 93 /** 94 * Mix value length and coder into current length and coder. 95 * @param lengthCoder String length with coder packed into higher bits 96 * the upper word. 97 * @param value value to mix in 98 * @return new length and coder 99 */ 100 static long mix(long lengthCoder, short value) { 101 return mix(lengthCoder, (int)value); 102 } 103 104 /** 105 * Mix value length and coder into current length and coder. 106 * @param lengthCoder String length with coder packed into higher bits 107 * the upper word. 108 * @param value value to mix in 109 * @return new length and coder 110 */ 111 static long mix(long lengthCoder, int value) { 112 return checkOverflow(lengthCoder + Integer.stringSize(value)); 113 } 114 115 /** 116 * Mix value length and coder into current length and coder. 117 * @param lengthCoder String length with coder packed into higher bits 118 * the upper word. 119 * @param value value to mix in 120 * @return new length and coder 121 */ 122 static long mix(long lengthCoder, long value) { 123 return checkOverflow(lengthCoder + Long.stringSize(value)); 124 } 125 126 /** 127 * Mix value length and coder into current length and coder. 128 * @param lengthCoder String length with coder packed into higher bits 129 * the upper word. 130 * @param value value to mix in 131 * @return new length and coder 132 */ 133 static long mix(long lengthCoder, String value) { 134 lengthCoder += value.length(); 135 if (value.coder() == String.UTF16) { 136 lengthCoder |= UTF16; 137 } 138 return checkOverflow(lengthCoder); 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 indexCoder final char index in the buffer, along with coder packed 146 * into higher bits. 147 * @param buf buffer to append to 148 * @param value boolean value to encode 149 * @return updated index (coder value retained) 150 */ 151 private static long prepend(long indexCoder, byte[] buf, boolean value) { 152 int index = (int)indexCoder; 153 if (indexCoder < UTF16) { 154 if (value) { 155 buf[--index] = 'e'; 156 buf[--index] = 'u'; 157 buf[--index] = 'r'; 158 buf[--index] = 't'; 159 } else { 160 buf[--index] = 'e'; 161 buf[--index] = 's'; 162 buf[--index] = 'l'; 163 buf[--index] = 'a'; 164 buf[--index] = 'f'; 165 } 166 return index; 167 } else { 168 if (value) { 169 StringUTF16.putChar(buf, --index, 'e'); 170 StringUTF16.putChar(buf, --index, 'u'); 171 StringUTF16.putChar(buf, --index, 'r'); 172 StringUTF16.putChar(buf, --index, 't'); 173 } else { 174 StringUTF16.putChar(buf, --index, 'e'); 175 StringUTF16.putChar(buf, --index, 's'); 176 StringUTF16.putChar(buf, --index, 'l'); 177 StringUTF16.putChar(buf, --index, 'a'); 178 StringUTF16.putChar(buf, --index, 'f'); 179 } 180 return index | UTF16; 181 } 182 } 183 184 /** 185 * Prepends constant and the stringly representation of value into buffer, 186 * given the coder and final index. Index is measured in chars, not in bytes! 187 * 188 * @param indexCoder final char index in the buffer, along with coder packed 189 * into higher bits. 190 * @param buf buffer to append to 191 * @param prefix a constant to prepend before value 192 * @param value boolean value to encode 193 * @param suffix a constant to prepend after value 194 * @return updated index (coder value retained) 195 */ 196 static long prepend(long indexCoder, byte[] buf, String prefix, boolean value, String suffix) { 197 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 198 indexCoder = prepend(indexCoder, buf, value); 199 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 200 return indexCoder; 201 } 202 203 /** 204 * Prepends constant and the stringly representation of value into buffer, 205 * given the coder and final index. Index is measured in chars, not in bytes! 206 * 207 * @param indexCoder final char index in the buffer, along with coder packed 208 * into higher bits. 209 * @param buf buffer to append to 210 * @param prefix a constant to prepend before value 211 * @param value boolean value to encode 212 * @param suffix a constant to prepend after value 213 * @return updated index (coder value retained) 214 */ 215 static long prepend(long indexCoder, byte[] buf, String prefix, byte value, String suffix) { 216 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 217 indexCoder = prepend(indexCoder, buf, (int)value); 218 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 219 return indexCoder; 220 } 221 222 /** 223 * Prepends the stringly representation of char value into buffer, 224 * given the coder and final index. Index is measured in chars, not in bytes! 225 * 226 * @param indexCoder final char index in the buffer, along with coder packed 227 * into higher bits. 228 * @param buf buffer to append to 229 * @param value char value to encode 230 * @return updated index (coder value retained) 231 */ 232 private static long prepend(long indexCoder, byte[] buf, char value) { 233 if (indexCoder < UTF16) { 234 buf[(int)(--indexCoder)] = (byte) (value & 0xFF); 235 } else { 236 StringUTF16.putChar(buf, (int)(--indexCoder), value); 237 } 238 return indexCoder; 239 } 240 241 /** 242 * Prepends constant and the stringly representation of value into buffer, 243 * given the coder and final index. Index is measured in chars, not in bytes! 244 * 245 * @param indexCoder final char index in the buffer, along with coder packed 246 * into higher bits. 247 * @param buf buffer to append to 248 * @param prefix a constant to prepend before value 249 * @param value boolean value to encode 250 * @param suffix a constant to prepend after value 251 * @return updated index (coder value retained) 252 */ 253 static long prepend(long indexCoder, byte[] buf, String prefix, char value, String suffix) { 254 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 255 indexCoder = prepend(indexCoder, buf, value); 256 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 257 return indexCoder; 258 } 259 260 /** 261 * Prepends constant and the stringly representation of value into buffer, 262 * given the coder and final index. Index is measured in chars, not in bytes! 263 * 264 * @param indexCoder final char index in the buffer, along with coder packed 265 * into higher bits. 266 * @param buf buffer to append to 267 * @param prefix a constant to prepend before value 268 * @param value boolean value to encode 269 * @param suffix a constant to prepend after value 270 * @return updated index (coder value retained) 271 */ 272 static long prepend(long indexCoder, byte[] buf, String prefix, short value, String suffix) { 273 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 274 indexCoder = prepend(indexCoder, buf, (int)value); 275 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 276 return indexCoder; 277 } 278 279 /** 280 * Prepends the stringly representation of integer value into buffer, 281 * given the coder and final index. Index is measured in chars, not in bytes! 282 * 283 * @param indexCoder final char index in the buffer, along with coder packed 284 * into higher bits. 285 * @param buf buffer to append to 286 * @param value integer value to encode 287 * @return updated index (coder value retained) 288 */ 289 private static long prepend(long indexCoder, byte[] buf, int value) { 290 if (indexCoder < UTF16) { 291 return Integer.getChars(value, (int)indexCoder, buf); 292 } else { 293 return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16; 294 } 295 } 296 297 /** 298 * Prepends constant and the stringly representation of value into buffer, 299 * given the coder and final index. Index is measured in chars, not in bytes! 300 * 301 * @param indexCoder final char index in the buffer, along with coder packed 302 * into higher bits. 303 * @param buf buffer to append to 304 * @param prefix a constant to prepend before value 305 * @param value boolean value to encode 306 * @param suffix a constant to prepend after value 307 * @return updated index (coder value retained) 308 */ 309 static long prepend(long indexCoder, byte[] buf, String prefix, int value, String suffix) { 310 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 311 indexCoder = prepend(indexCoder, buf, value); 312 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 313 return indexCoder; 314 } 315 316 /** 317 * Prepends the stringly representation of long value into buffer, 318 * given the coder and final index. Index is measured in chars, not in bytes! 319 * 320 * @param indexCoder final char index in the buffer, along with coder packed 321 * into higher bits. 322 * @param buf buffer to append to 323 * @param value long value to encode 324 * @return updated index (coder value retained) 325 */ 326 private static long prepend(long indexCoder, byte[] buf, long value) { 327 if (indexCoder < UTF16) { 328 return Long.getChars(value, (int)indexCoder, buf); 329 } else { 330 return StringUTF16.getChars(value, (int)indexCoder, buf) | UTF16; 331 } 332 } 333 334 /** 335 * Prepends constant and the stringly representation of value into buffer, 336 * given the coder and final index. Index is measured in chars, not in bytes! 337 * 338 * @param indexCoder final char index in the buffer, along with coder packed 339 * into higher bits. 340 * @param buf buffer to append to 341 * @param prefix a constant to prepend before value 342 * @param value boolean value to encode 343 * @param suffix a constant to prepend after value 344 * @return updated index (coder value retained) 345 */ 346 static long prepend(long indexCoder, byte[] buf, String prefix, long value, String suffix) { 347 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 348 indexCoder = prepend(indexCoder, buf, value); 349 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 350 return indexCoder; 351 } 352 353 /** 354 * Prepends the stringly representation of String value into buffer, 355 * given the coder and final index. Index is measured in chars, not in bytes! 356 * 357 * @param indexCoder final char index in the buffer, along with coder packed 358 * into higher bits. 359 * @param buf buffer to append to 360 * @param value String value to encode 361 * @return updated index (coder value retained) 362 */ 363 private static long prepend(long indexCoder, byte[] buf, String value) { 364 indexCoder -= value.length(); 365 if (indexCoder < UTF16) { 366 value.getBytes(buf, (int)indexCoder, String.LATIN1); 367 } else { 368 value.getBytes(buf, (int)indexCoder, String.UTF16); 369 } 370 return indexCoder; 371 } 372 373 /** 374 * Prepends constant and the stringly representation of value into buffer, 375 * given the coder and final index. Index is measured in chars, not in bytes! 376 * 377 * @param indexCoder final char index in the buffer, along with coder packed 378 * into higher bits. 379 * @param buf buffer to append to 380 * @param prefix a constant to prepend before value 381 * @param value boolean value to encode 382 * @param suffix a constant to prepend after value 383 * @return updated index (coder value retained) 384 */ 385 static long prepend(long indexCoder, byte[] buf, String prefix, String value, String suffix) { 386 if (suffix != null) indexCoder = prepend(indexCoder, buf, suffix); 387 indexCoder = prepend(indexCoder, buf, value); 388 if (prefix != null) indexCoder = prepend(indexCoder, buf, prefix); 389 return indexCoder; 390 } 391 392 /** 393 * Instantiates the String with given buffer and coder 394 * @param buf buffer to use 395 * @param indexCoder remaining index (should be zero) and coder 396 * @return String resulting string 397 */ 398 static String newString(byte[] buf, long indexCoder) { 399 // Use the private, non-copying constructor (unsafe!) 400 if (indexCoder == LATIN1) { 401 return new String(buf, String.LATIN1); 402 } else if (indexCoder == UTF16) { 403 return new String(buf, String.UTF16); 404 } else { 405 throw new InternalError("Storage is not completely initialized, " + (int)indexCoder + " bytes left"); 406 } 407 } 408 409 /** 410 * Perform a simple concatenation between two objects. Added for startup 411 * performance, but also demonstrates the code that would be emitted by 412 * {@code java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy} 413 * for two Object arguments. 414 * 415 * @param first first argument 416 * @param second second argument 417 * @return String resulting string 418 */ 419 @ForceInline 420 static String simpleConcat(Object first, Object second) { 421 String s1 = stringOf(first); 422 String s2 = stringOf(second); 423 // start "mixing" in length and coder or arguments, order is not 424 // important 425 long indexCoder = mix(initialCoder(), s2); 426 indexCoder = mix(indexCoder, s1); 427 byte[] buf = newArray(indexCoder); 428 // prepend each argument in reverse order, since we prepending 429 // from the end of the byte array 430 indexCoder = prepend(indexCoder, buf, s2); 431 indexCoder = prepend(indexCoder, buf, s1); 432 return newString(buf, indexCoder); 433 } 434 435 /** 436 * We need some additional conversion for Objects in general, because 437 * {@code String.valueOf(Object)} may return null. String conversion rules 438 * in Java state we need to produce "null" String in this case, so we 439 * provide a customized version that deals with this problematic corner case. 440 */ 441 static String stringOf(Object value) { 442 String s; 443 return (value == null || (s = value.toString()) == null) ? "null" : s; 444 } 445 446 private static final long LATIN1 = (long)String.LATIN1 << 32; 447 448 private static final long UTF16 = (long)String.UTF16 << 32; 449 450 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 451 452 /** 453 * Allocates an uninitialized byte array based on the length and coder information 454 * in indexCoder 455 * @param indexCoder 456 * @return the newly allocated byte array 457 */ 458 @ForceInline 459 static byte[] newArray(long indexCoder) { 460 byte coder = (byte)(indexCoder >> 32); 461 int index = (int)indexCoder; 462 return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder); 463 } 464 465 /** 466 * Provides the initial coder for the String. 467 * @return initial coder, adjusted into the upper half 468 */ 469 static long initialCoder() { 470 return String.COMPACT_STRINGS ? LATIN1 : UTF16; 471 } 472 473 static MethodHandle lookupStatic(String name, MethodType methodType) { 474 try { 475 return MethodHandles.lookup().findStatic(StringConcatHelper.class, name, methodType); 476 } catch (NoSuchMethodException|IllegalAccessException e) { 477 throw new AssertionError(e); 478 } 479 } 480 481 482 }