src/share/vm/opto/stringopts.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot-comp Sdiff src/share/vm/opto

src/share/vm/opto/stringopts.cpp

Print this page


   1 /*
   2  * Copyright (c) 2009, 2012, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


  25 #include "precompiled.hpp"
  26 #include "compiler/compileLog.hpp"
  27 #include "opto/addnode.hpp"
  28 #include "opto/callGenerator.hpp"
  29 #include "opto/callnode.hpp"
  30 #include "opto/divnode.hpp"
  31 #include "opto/graphKit.hpp"
  32 #include "opto/idealKit.hpp"
  33 #include "opto/rootnode.hpp"
  34 #include "opto/runtime.hpp"
  35 #include "opto/stringopts.hpp"
  36 #include "opto/subnode.hpp"
  37 
  38 #define __ kit.
  39 
  40 class StringConcat : public ResourceObj {
  41  private:
  42   PhaseStringOpts*    _stringopts;
  43   Node*               _string_alloc;
  44   AllocateNode*       _begin;          // The allocation the begins the pattern

  45   CallStaticJavaNode* _end;            // The final call of the pattern.  Will either be
  46                                        // SB.toString or or String.<init>(SB.toString)
  47   bool                _multiple;       // indicates this is a fusion of two or more
  48                                        // separate StringBuilders
  49 
  50   Node*               _arguments;      // The list of arguments to be concatenated
  51   GrowableArray<int>  _mode;           // into a String along with a mode flag
  52                                        // indicating how to treat the value.
  53 
  54   Node_List           _control;        // List of control nodes that will be deleted
  55   Node_List           _uncommon_traps; // Uncommon traps that needs to be rewritten
  56                                        // to restart at the initial JVMState.

  57  public:
  58   // Mode for converting arguments to Strings
  59   enum {
  60     StringMode,
  61     IntMode,
  62     CharMode,
  63     StringNullCheckMode
  64   };
  65 
  66   StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end):
  67     _end(end),
  68     _begin(NULL),
  69     _multiple(false),
  70     _string_alloc(NULL),
  71     _stringopts(stringopts) {
  72     _arguments = new (_stringopts->C) Node(1);
  73     _arguments->del_req(0);
  74   }
  75 

  76   bool validate_control_flow();
  77 
  78   void merge_add() {
  79 #if 0
  80     // XXX This is place holder code for reusing an existing String
  81     // allocation but the logic for checking the state safety is
  82     // probably inadequate at the moment.
  83     CallProjections endprojs;
  84     sc->end()->extract_projections(&endprojs, false);
  85     if (endprojs.resproj != NULL) {
  86       for (SimpleDUIterator i(endprojs.resproj); i.has_next(); i.next()) {
  87         CallStaticJavaNode *use = i.get()->isa_CallStaticJava();
  88         if (use != NULL && use->method() != NULL &&
  89             use->method()->intrinsic_id() == vmIntrinsics::_String_String &&
  90             use->in(TypeFunc::Parms + 1) == endprojs.resproj) {
  91           // Found useless new String(sb.toString()) so reuse the newly allocated String
  92           // when creating the result instead of allocating a new one.
  93           sc->set_string_alloc(use->in(TypeFunc::Parms));
  94           sc->set_end(use);
  95         }
  96       }
  97     }
  98 #endif
  99   }
 100 
 101   StringConcat* merge(StringConcat* other, Node* arg);
 102 
 103   void set_allocation(AllocateNode* alloc) {
 104     _begin = alloc;
 105   }
 106 


 107   void append(Node* value, int mode) {
 108     _arguments->add_req(value);
 109     _mode.append(mode);
 110   }
 111   void push(Node* value, int mode) {
 112     _arguments->ins_req(0, value);
 113     _mode.insert_before(0, mode);
 114   }
 115 
 116   void push_string(Node* value) {
 117     push(value, StringMode);
 118   }
 119   void push_string_null_check(Node* value) {
 120     push(value, StringNullCheckMode);
 121   }
 122   void push_int(Node* value) {
 123     push(value, IntMode);
 124   }
 125   void push_char(Node* value) {
 126     push(value, CharMode);


 493           break;
 494         }
 495       }
 496       if (constructor == NULL) {
 497         // couldn't find constructor
 498 #ifndef PRODUCT
 499         if (PrintOptimizeStringConcat) {
 500           tty->print("giving up because couldn't find constructor ");
 501           alloc->jvms()->dump_spec(tty); tty->cr();
 502         }
 503 #endif
 504         break;
 505       }
 506 
 507       // Walked all the way back and found the constructor call so see
 508       // if this call converted into a direct string concatenation.
 509       sc->add_control(call);
 510       sc->add_control(constructor);
 511       sc->add_control(alloc);
 512       sc->set_allocation(alloc);
 513       if (sc->validate_control_flow()) {

 514         return sc;
 515       } else {
 516         return NULL;
 517       }
 518     } else if (cnode->method() == NULL) {
 519       break;
 520     } else if (!cnode->method()->is_static() &&
 521                cnode->method()->holder() == m->holder() &&
 522                cnode->method()->name() == ciSymbol::append_name() &&
 523                (cnode->method()->signature()->as_symbol() == string_sig ||
 524                 cnode->method()->signature()->as_symbol() == char_sig ||
 525                 cnode->method()->signature()->as_symbol() == int_sig)) {
 526       sc->add_control(cnode);
 527       Node* arg = cnode->in(TypeFunc::Parms + 1);
 528       if (cnode->method()->signature()->as_symbol() == int_sig) {
 529         sc->push_int(arg);
 530       } else if (cnode->method()->signature()->as_symbol() == char_sig) {
 531         sc->push_char(arg);
 532       } else {
 533         if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) {


 554       continue;
 555     } else {
 556       // some unhandled signature
 557 #ifndef PRODUCT
 558       if (PrintOptimizeStringConcat) {
 559         tty->print("giving up because encountered unexpected signature ");
 560         cnode->tf()->dump(); tty->cr();
 561         cnode->in(TypeFunc::Parms + 1)->dump();
 562       }
 563 #endif
 564       break;
 565     }
 566   }
 567   return NULL;
 568 }
 569 
 570 
 571 PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*):
 572   Phase(StringOpts),
 573   _gvn(gvn),
 574   _visited(Thread::current()->resource_area()) {

 575 
 576   assert(OptimizeStringConcat, "shouldn't be here");
 577 
 578   size_table_field = C->env()->Integer_klass()->get_field_by_name(ciSymbol::make("sizeTable"),
 579                                                                   ciSymbol::make("[I"), true);
 580   if (size_table_field == NULL) {
 581     // Something wrong so give up.
 582     assert(false, "why can't we find Integer.sizeTable?");
 583     return;
 584   }
 585 
 586   // Collect the types needed to talk about the various slices of memory
 587   char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
 588 
 589   // For each locally allocated StringBuffer see if the usages can be
 590   // collapsed into a single String construction.
 591 
 592   // Run through the list of allocation looking for SB.toString to see
 593   // if it's possible to fuse the usage of the SB into a single String
 594   // construction.


 603 
 604   // try to coalesce separate concats
 605  restart:
 606   for (int c = 0; c < concats.length(); c++) {
 607     StringConcat* sc = concats.at(c);
 608     for (int i = 0; i < sc->num_arguments(); i++) {
 609       Node* arg = sc->argument_uncast(i);
 610       if (arg->is_Proj() && StringConcat::is_SB_toString(arg->in(0))) {
 611         CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava();
 612         for (int o = 0; o < concats.length(); o++) {
 613           if (c == o) continue;
 614           StringConcat* other = concats.at(o);
 615           if (other->end() == csj) {
 616 #ifndef PRODUCT
 617             if (PrintOptimizeStringConcat) {
 618               tty->print_cr("considering stacked concats");
 619             }
 620 #endif
 621 
 622             StringConcat* merged = sc->merge(other, arg);
 623             if (merged->validate_control_flow()) {
 624 #ifndef PRODUCT
 625               if (PrintOptimizeStringConcat) {
 626                 tty->print_cr("stacking would succeed");
 627               }
 628 #endif
 629               if (c < o) {
 630                 concats.remove_at(o);
 631                 concats.at_put(c, merged);
 632               } else {
 633                 concats.remove_at(c);
 634                 concats.at_put(o, merged);
 635               }
 636               goto restart;
 637             } else {
 638 #ifndef PRODUCT
 639               if (PrintOptimizeStringConcat) {
 640                 tty->print_cr("stacking would fail");
 641               }
 642 #endif
 643             }


 690         // Recurisvely clean up references to CreateEx so EA doesn't
 691         // get unhappy about the partially collapsed graph.
 692         for (SimpleDUIterator i(use); i.has_next(); i.next()) {
 693           Node* m = i.get();
 694           if (m->is_AddP()) {
 695             dead_worklist.push(m);
 696           }
 697         }
 698         C->gvn_replace_by(use, C->top());
 699         break;
 700       }
 701       case Op_Phi:
 702         if (use->in(0) == C->top()) {
 703           C->gvn_replace_by(use, C->top());
 704         }
 705         break;
 706     }
 707   }
 708 }
 709 

































































































































 710 
 711 bool StringConcat::validate_control_flow() {
 712   // We found all the calls and arguments now lets see if it's
 713   // safe to transform the graph as we would expect.
 714 
 715   // Check to see if this resulted in too many uncommon traps previously
 716   if (Compile::current()->too_many_traps(_begin->jvms()->method(), _begin->jvms()->bci(),
 717                         Deoptimization::Reason_intrinsic)) {
 718     return false;
 719   }
 720 
 721   // Walk backwards over the control flow from toString to the
 722   // allocation and make sure all the control flow is ok.  This
 723   // means it's either going to be eliminated once the calls are
 724   // removed or it can safely be transformed into an uncommon
 725   // trap.
 726 
 727   int null_check_count = 0;
 728   Unique_Node_List ctrl_path;
 729 


 919       }
 920 #ifndef PRODUCT
 921       if (PrintOptimizeStringConcat) {
 922         if (result != last_result) {
 923           last_result = result;
 924           tty->print_cr("extra uses for result:");
 925           last_result->dump();
 926         }
 927         use->dump();
 928       }
 929 #endif
 930       fail = true;
 931       break;
 932     }
 933   }
 934 
 935 #ifndef PRODUCT
 936   if (PrintOptimizeStringConcat && !fail) {
 937     ttyLocker ttyl;
 938     tty->cr();
 939     tty->print("fusion would succeed (%d %d) for ", null_check_count, _uncommon_traps.size());
 940     _begin->jvms()->dump_spec(tty); tty->cr();
 941     for (int i = 0; i < num_arguments(); i++) {
 942       argument(i)->dump();
 943     }
 944     _control.dump();
 945     tty->cr();
 946   }
 947 #endif
 948 
 949   return !fail;
 950 }
 951 
 952 Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) {
 953   const TypeInstPtr* mirror_type = TypeInstPtr::make(field->holder()->java_mirror());
 954   Node* klass_node = __ makecon(mirror_type);
 955   BasicType bt = field->layout_type();
 956   ciType* field_klass = field->type();
 957 
 958   const Type *type;
 959   if( bt == T_OBJECT ) {


   1 /*
   2  * Copyright (c) 2009, 2013, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


  25 #include "precompiled.hpp"
  26 #include "compiler/compileLog.hpp"
  27 #include "opto/addnode.hpp"
  28 #include "opto/callGenerator.hpp"
  29 #include "opto/callnode.hpp"
  30 #include "opto/divnode.hpp"
  31 #include "opto/graphKit.hpp"
  32 #include "opto/idealKit.hpp"
  33 #include "opto/rootnode.hpp"
  34 #include "opto/runtime.hpp"
  35 #include "opto/stringopts.hpp"
  36 #include "opto/subnode.hpp"
  37 
  38 #define __ kit.
  39 
  40 class StringConcat : public ResourceObj {
  41  private:
  42   PhaseStringOpts*    _stringopts;
  43   Node*               _string_alloc;
  44   AllocateNode*       _begin;          // The allocation the begins the pattern
  45   Node*               _constructor;    // Constructor of StringBuffer
  46   CallStaticJavaNode* _end;            // The final call of the pattern.  Will either be
  47                                        // SB.toString or or String.<init>(SB.toString)
  48   bool                _multiple;       // indicates this is a fusion of two or more
  49                                        // separate StringBuilders
  50 
  51   Node*               _arguments;      // The list of arguments to be concatenated
  52   GrowableArray<int>  _mode;           // into a String along with a mode flag
  53                                        // indicating how to treat the value.
  54 
  55   Node_List           _control;        // List of control nodes that will be deleted
  56   Node_List           _uncommon_traps; // Uncommon traps that needs to be rewritten
  57                                        // to restart at the initial JVMState.
  58 
  59  public:
  60   // Mode for converting arguments to Strings
  61   enum {
  62     StringMode,
  63     IntMode,
  64     CharMode,
  65     StringNullCheckMode
  66   };
  67 
  68   StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end):
  69     _end(end),
  70     _begin(NULL),
  71     _multiple(false),
  72     _string_alloc(NULL),
  73     _stringopts(stringopts) {
  74     _arguments = new (_stringopts->C) Node(1);
  75     _arguments->del_req(0);
  76   }
  77 
  78   bool validate_mem_flow();
  79   bool validate_control_flow();
  80 
  81   void merge_add() {
  82 #if 0
  83     // XXX This is place holder code for reusing an existing String
  84     // allocation but the logic for checking the state safety is
  85     // probably inadequate at the moment.
  86     CallProjections endprojs;
  87     sc->end()->extract_projections(&endprojs, false);
  88     if (endprojs.resproj != NULL) {
  89       for (SimpleDUIterator i(endprojs.resproj); i.has_next(); i.next()) {
  90         CallStaticJavaNode *use = i.get()->isa_CallStaticJava();
  91         if (use != NULL && use->method() != NULL &&
  92             use->method()->intrinsic_id() == vmIntrinsics::_String_String &&
  93             use->in(TypeFunc::Parms + 1) == endprojs.resproj) {
  94           // Found useless new String(sb.toString()) so reuse the newly allocated String
  95           // when creating the result instead of allocating a new one.
  96           sc->set_string_alloc(use->in(TypeFunc::Parms));
  97           sc->set_end(use);
  98         }
  99       }
 100     }
 101 #endif
 102   }
 103 
 104   StringConcat* merge(StringConcat* other, Node* arg);
 105 
 106   void set_allocation(AllocateNode* alloc) {
 107     _begin = alloc;
 108   }
 109   void set_constructor(Node* init) {
 110     _constructor = init;
 111   }
 112   void append(Node* value, int mode) {
 113     _arguments->add_req(value);
 114     _mode.append(mode);
 115   }
 116   void push(Node* value, int mode) {
 117     _arguments->ins_req(0, value);
 118     _mode.insert_before(0, mode);
 119   }
 120 
 121   void push_string(Node* value) {
 122     push(value, StringMode);
 123   }
 124   void push_string_null_check(Node* value) {
 125     push(value, StringNullCheckMode);
 126   }
 127   void push_int(Node* value) {
 128     push(value, IntMode);
 129   }
 130   void push_char(Node* value) {
 131     push(value, CharMode);


 498           break;
 499         }
 500       }
 501       if (constructor == NULL) {
 502         // couldn't find constructor
 503 #ifndef PRODUCT
 504         if (PrintOptimizeStringConcat) {
 505           tty->print("giving up because couldn't find constructor ");
 506           alloc->jvms()->dump_spec(tty); tty->cr();
 507         }
 508 #endif
 509         break;
 510       }
 511 
 512       // Walked all the way back and found the constructor call so see
 513       // if this call converted into a direct string concatenation.
 514       sc->add_control(call);
 515       sc->add_control(constructor);
 516       sc->add_control(alloc);
 517       sc->set_allocation(alloc);
 518       sc->set_constructor(constructor);
 519       if (sc->validate_control_flow() && sc->validate_mem_flow()) {
 520         return sc;
 521       } else {
 522         return NULL;
 523       }
 524     } else if (cnode->method() == NULL) {
 525       break;
 526     } else if (!cnode->method()->is_static() &&
 527                cnode->method()->holder() == m->holder() &&
 528                cnode->method()->name() == ciSymbol::append_name() &&
 529                (cnode->method()->signature()->as_symbol() == string_sig ||
 530                 cnode->method()->signature()->as_symbol() == char_sig ||
 531                 cnode->method()->signature()->as_symbol() == int_sig)) {
 532       sc->add_control(cnode);
 533       Node* arg = cnode->in(TypeFunc::Parms + 1);
 534       if (cnode->method()->signature()->as_symbol() == int_sig) {
 535         sc->push_int(arg);
 536       } else if (cnode->method()->signature()->as_symbol() == char_sig) {
 537         sc->push_char(arg);
 538       } else {
 539         if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) {


 560       continue;
 561     } else {
 562       // some unhandled signature
 563 #ifndef PRODUCT
 564       if (PrintOptimizeStringConcat) {
 565         tty->print("giving up because encountered unexpected signature ");
 566         cnode->tf()->dump(); tty->cr();
 567         cnode->in(TypeFunc::Parms + 1)->dump();
 568       }
 569 #endif
 570       break;
 571     }
 572   }
 573   return NULL;
 574 }
 575 
 576 
 577 PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*):
 578   Phase(StringOpts),
 579   _gvn(gvn),
 580   _visited(Thread::current()->resource_area()),
 581   _path(memory_flow_iteration_limit) {
 582 
 583   assert(OptimizeStringConcat, "shouldn't be here");
 584 
 585   size_table_field = C->env()->Integer_klass()->get_field_by_name(ciSymbol::make("sizeTable"),
 586                                                                   ciSymbol::make("[I"), true);
 587   if (size_table_field == NULL) {
 588     // Something wrong so give up.
 589     assert(false, "why can't we find Integer.sizeTable?");
 590     return;
 591   }
 592 
 593   // Collect the types needed to talk about the various slices of memory
 594   char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
 595 
 596   // For each locally allocated StringBuffer see if the usages can be
 597   // collapsed into a single String construction.
 598 
 599   // Run through the list of allocation looking for SB.toString to see
 600   // if it's possible to fuse the usage of the SB into a single String
 601   // construction.


 610 
 611   // try to coalesce separate concats
 612  restart:
 613   for (int c = 0; c < concats.length(); c++) {
 614     StringConcat* sc = concats.at(c);
 615     for (int i = 0; i < sc->num_arguments(); i++) {
 616       Node* arg = sc->argument_uncast(i);
 617       if (arg->is_Proj() && StringConcat::is_SB_toString(arg->in(0))) {
 618         CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava();
 619         for (int o = 0; o < concats.length(); o++) {
 620           if (c == o) continue;
 621           StringConcat* other = concats.at(o);
 622           if (other->end() == csj) {
 623 #ifndef PRODUCT
 624             if (PrintOptimizeStringConcat) {
 625               tty->print_cr("considering stacked concats");
 626             }
 627 #endif
 628 
 629             StringConcat* merged = sc->merge(other, arg);
 630             if (merged->validate_control_flow() && merged->validate_mem_flow()) {
 631 #ifndef PRODUCT
 632               if (PrintOptimizeStringConcat) {
 633                 tty->print_cr("stacking would succeed");
 634               }
 635 #endif
 636               if (c < o) {
 637                 concats.remove_at(o);
 638                 concats.at_put(c, merged);
 639               } else {
 640                 concats.remove_at(c);
 641                 concats.at_put(o, merged);
 642               }
 643               goto restart;
 644             } else {
 645 #ifndef PRODUCT
 646               if (PrintOptimizeStringConcat) {
 647                 tty->print_cr("stacking would fail");
 648               }
 649 #endif
 650             }


 697         // Recurisvely clean up references to CreateEx so EA doesn't
 698         // get unhappy about the partially collapsed graph.
 699         for (SimpleDUIterator i(use); i.has_next(); i.next()) {
 700           Node* m = i.get();
 701           if (m->is_AddP()) {
 702             dead_worklist.push(m);
 703           }
 704         }
 705         C->gvn_replace_by(use, C->top());
 706         break;
 707       }
 708       case Op_Phi:
 709         if (use->in(0) == C->top()) {
 710           C->gvn_replace_by(use, C->top());
 711         }
 712         break;
 713     }
 714   }
 715 }
 716 
 717 // Find all simple paths from start_mem to any node in end_set, check if any of the paths
 718 // has side effects.
 719 bool StringConcat::validate_mem_flow() {
 720   Node* start_mem = _end;
 721   Node* end_mem = _constructor;
 722   assert(start_mem->is_Call() && end_mem->is_Call(), "precondition");
 723   assert(_control.contains(start_mem) && _control.contains(end_mem), "precondition");
 724 
 725   Node_Stack& path = _stringopts->_path;
 726   path.clear();
 727 
 728   // Interested in simple paths, so we'll track the nodes visited
 729   VectorSet& visited = _stringopts->_visited;
 730   visited.Clear();
 731 
 732   Compile* C = _stringopts->C;
 733   path.push(start_mem, 0);
 734   visited.set(start_mem->_idx);
 735   visited.set(C->top()->_idx);
 736 
 737   int nodes_processed = 0;
 738   // Do DFS up the memory graph, storing the result in path,
 739   // use next_edge to track the last edge taken for the node.
 740   while (path.is_nonempty()) {
 741     if (nodes_processed++ > PhaseStringOpts::memory_flow_iteration_limit) {
 742       // We're spending too much time here, going to be pessimistic
 743       // and say we have found a side effect
 744 #ifndef PRODUCT
 745       if (PrintOptimizeStringConcat) {
 746         tty->print_cr("Giving up on memory flow analysis due to iteration cutoff");
 747       }
 748 #endif
 749       return false;
 750     }
 751 
 752     Node* curr = path.node();
 753     uint edge_idx = path.index();
 754     bool is_not_visited = (edge_idx == 0);
 755     Node* next = NULL;
 756 
 757     if (curr->is_Proj()) {
 758       assert(curr->as_Proj()->_con == TypeFunc::Memory, "must be a memory projection");
 759       if (is_not_visited) {
 760         next = curr->in(0);
 761       }
 762     } else if (curr->is_Mem()) {
 763       if (curr->is_Store() || curr->is_LoadStore()) {
 764 #ifndef PRODUCT
 765         if (PrintOptimizeStringConcat) {
 766           ttyLocker ttyl;
 767           tty->print("fusion has incorrect memory flow (side effects) for ");
 768           _begin->jvms()->dump_spec(tty); tty->cr();
 769           for (uint i = 0; i < path.size(); i++) {
 770             path.node_at(i)->dump();
 771           }
 772           tty->cr();
 773         }
 774 #endif // !PRODUCT
 775         return false;
 776       }
 777       if (is_not_visited) {
 778         next = curr->in(MemNode::Memory);
 779         assert(next != NULL, "should have memory edge");
 780       }
 781     } else if (curr->is_Call()) {
 782       if (is_not_visited) {
 783         next = curr->in(TypeFunc::Memory);
 784         assert(next != NULL, "should have memory edge");
 785       }
 786       if (curr == end_mem) {
 787         // Terminate this search branch
 788         next = NULL;
 789       }
 790     } else if (curr->is_MergeMem()) {
 791       while (edge_idx + 1 < curr->req() && next == NULL) {
 792         next = curr->in(edge_idx + 1);
 793         bool dup = false;
 794         if (next != NULL) {
 795           // skip duplicate edges
 796           for (uint i = 1; i < edge_idx + 1; i++) {
 797             if (next == curr->in(i)) {
 798               edge_idx++;
 799               next = NULL;
 800               break;
 801             }
 802           }
 803         } else {
 804           edge_idx++;
 805         }
 806       }
 807     } else if (curr->is_MemBar()) {
 808       if (edge_idx < 1) {
 809         next = curr->in(TypeFunc::Memory);
 810         assert(next != NULL, "should have memory edge");
 811       } else if (curr->is_Initialize() && edge_idx < 2) {
 812         next = curr->as_Initialize()->allocation();
 813       }
 814     } else {
 815       assert(false, err_msg_res("Unexpected node type: %s", curr->Name()));
 816       return false;
 817     }
 818     edge_idx++;
 819 
 820     if (next == NULL) {
 821       // Can't go any further, need to pop off the node
 822       visited.remove(curr->_idx);
 823       path.pop();
 824     } else {
 825       // Update the last visited edge number
 826       path.set_index(edge_idx);
 827       // Check if the next node was already visited
 828       if (!visited.test_set(next->_idx)) {
 829         // If not add it to the path
 830         path.push(next, 0);
 831       }
 832     }
 833   }
 834 
 835 #ifndef PRODUCT
 836   if (PrintOptimizeStringConcat) {
 837     tty->print("fusion has correct memory flow for ");
 838     _begin->jvms()->dump_spec(tty); tty->cr();
 839     tty->cr();
 840   }
 841 #endif
 842 
 843   // No interesing paths
 844   return true;
 845 }
 846 
 847 bool StringConcat::validate_control_flow() {
 848   // We found all the calls and arguments now lets see if it's
 849   // safe to transform the graph as we would expect.
 850 
 851   // Check to see if this resulted in too many uncommon traps previously
 852   if (Compile::current()->too_many_traps(_begin->jvms()->method(), _begin->jvms()->bci(),
 853                         Deoptimization::Reason_intrinsic)) {
 854     return false;
 855   }
 856 
 857   // Walk backwards over the control flow from toString to the
 858   // allocation and make sure all the control flow is ok.  This
 859   // means it's either going to be eliminated once the calls are
 860   // removed or it can safely be transformed into an uncommon
 861   // trap.
 862 
 863   int null_check_count = 0;
 864   Unique_Node_List ctrl_path;
 865 


1055       }
1056 #ifndef PRODUCT
1057       if (PrintOptimizeStringConcat) {
1058         if (result != last_result) {
1059           last_result = result;
1060           tty->print_cr("extra uses for result:");
1061           last_result->dump();
1062         }
1063         use->dump();
1064       }
1065 #endif
1066       fail = true;
1067       break;
1068     }
1069   }
1070 
1071 #ifndef PRODUCT
1072   if (PrintOptimizeStringConcat && !fail) {
1073     ttyLocker ttyl;
1074     tty->cr();
1075     tty->print("fusion has correct control flow (%d %d) for ", null_check_count, _uncommon_traps.size());
1076     _begin->jvms()->dump_spec(tty); tty->cr();
1077     for (int i = 0; i < num_arguments(); i++) {
1078       argument(i)->dump();
1079     }
1080     _control.dump();
1081     tty->cr();
1082   }
1083 #endif
1084 
1085   return !fail;
1086 }
1087 
1088 Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) {
1089   const TypeInstPtr* mirror_type = TypeInstPtr::make(field->holder()->java_mirror());
1090   Node* klass_node = __ makecon(mirror_type);
1091   BasicType bt = field->layout_type();
1092   ciType* field_klass = field->type();
1093 
1094   const Type *type;
1095   if( bt == T_OBJECT ) {


src/share/vm/opto/stringopts.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File