8076758: new StringBuilder().append(String).toString() should be recognized by OptimizeStringConcat
authorshade
Tue, 01 Sep 2015 12:57:41 +0300
changeset 32467 23b29549f8d1
parent 32466 915d0c3d25aa
child 32468 54fbe836fcf0
child 32572 53295136b7bc
child 32734 7029a3eb3008
8076758: new StringBuilder().append(String).toString() should be recognized by OptimizeStringConcat Reviewed-by: kvn, thartmann
hotspot/src/share/vm/opto/stringopts.cpp
--- a/hotspot/src/share/vm/opto/stringopts.cpp	Mon Aug 31 13:49:18 2015 +0200
+++ b/hotspot/src/share/vm/opto/stringopts.cpp	Tue Sep 01 12:57:41 2015 +0300
@@ -1576,51 +1576,58 @@
 
   Node* result;
   if (!kit.stopped()) {
+    Node* char_array = NULL;
+    if (sc->num_arguments() == 1 &&
+          (sc->mode(0) == StringConcat::StringMode ||
+           sc->mode(0) == StringConcat::StringNullCheckMode)) {
+      // Handle the case when there is only a single String argument.
+      // In this case, we can just pull the value from the String itself.
+      char_array = kit.load_String_value(kit.control(), sc->argument(0));
+    } else {
+      // length now contains the number of characters needed for the
+      // char[] so create a new AllocateArray for the char[]
+      {
+        PreserveReexecuteState preexecs(&kit);
+        // The original jvms is for an allocation of either a String or
+        // StringBuffer so no stack adjustment is necessary for proper
+        // reexecution.  If we deoptimize in the slow path the bytecode
+        // will be reexecuted and the char[] allocation will be thrown away.
+        kit.jvms()->set_should_reexecute(true);
+        char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
+                                   length, 1);
+      }
 
-    // length now contains the number of characters needed for the
-    // char[] so create a new AllocateArray for the char[]
-    Node* char_array = NULL;
-    {
-      PreserveReexecuteState preexecs(&kit);
-      // The original jvms is for an allocation of either a String or
-      // StringBuffer so no stack adjustment is necessary for proper
-      // reexecution.  If we deoptimize in the slow path the bytecode
-      // will be reexecuted and the char[] allocation will be thrown away.
-      kit.jvms()->set_should_reexecute(true);
-      char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
-                                 length, 1);
-    }
-
-    // Mark the allocation so that zeroing is skipped since the code
-    // below will overwrite the entire array
-    AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
-    char_alloc->maybe_set_complete(_gvn);
+      // Mark the allocation so that zeroing is skipped since the code
+      // below will overwrite the entire array
+      AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
+      char_alloc->maybe_set_complete(_gvn);
 
-    // Now copy the string representations into the final char[]
-    Node* start = __ intcon(0);
-    for (int argi = 0; argi < sc->num_arguments(); argi++) {
-      Node* arg = sc->argument(argi);
-      switch (sc->mode(argi)) {
-        case StringConcat::IntMode: {
-          Node* end = __ AddI(start, string_sizes->in(argi));
-          // getChars words backwards so pass the ending point as well as the start
-          int_getChars(kit, arg, char_array, start, end);
-          start = end;
-          break;
+      // Now copy the string representations into the final char[]
+      Node* start = __ intcon(0);
+      for (int argi = 0; argi < sc->num_arguments(); argi++) {
+        Node* arg = sc->argument(argi);
+        switch (sc->mode(argi)) {
+          case StringConcat::IntMode: {
+            Node* end = __ AddI(start, string_sizes->in(argi));
+            // getChars words backwards so pass the ending point as well as the start
+            int_getChars(kit, arg, char_array, start, end);
+            start = end;
+            break;
+          }
+          case StringConcat::StringNullCheckMode:
+          case StringConcat::StringMode: {
+            start = copy_string(kit, arg, char_array, start);
+            break;
+          }
+          case StringConcat::CharMode: {
+            __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
+                               arg, T_CHAR, char_adr_idx, MemNode::unordered);
+            start = __ AddI(start, __ intcon(1));
+            break;
+          }
+          default:
+            ShouldNotReachHere();
         }
-        case StringConcat::StringNullCheckMode:
-        case StringConcat::StringMode: {
-          start = copy_string(kit, arg, char_array, start);
-          break;
-        }
-        case StringConcat::CharMode: {
-          __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
-                             arg, T_CHAR, char_adr_idx, MemNode::unordered);
-          start = __ AddI(start, __ intcon(1));
-          break;
-        }
-        default:
-          ShouldNotReachHere();
       }
     }