hotspot/src/share/vm/opto/stringopts.cpp
changeset 20716 5093ad743df4
parent 15113 823590505eb4
child 22845 d8812d0ff387
equal deleted inserted replaced
20715:be1135dc1406 20716:5093ad743df4
     1 /*
     1 /*
     2  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    48                                        // separate StringBuilders
    48                                        // separate StringBuilders
    49 
    49 
    50   Node*               _arguments;      // The list of arguments to be concatenated
    50   Node*               _arguments;      // The list of arguments to be concatenated
    51   GrowableArray<int>  _mode;           // into a String along with a mode flag
    51   GrowableArray<int>  _mode;           // into a String along with a mode flag
    52                                        // indicating how to treat the value.
    52                                        // indicating how to treat the value.
    53 
    53   Node_List           _constructors;   // List of constructors (many in case of stacked concat)
    54   Node_List           _control;        // List of control nodes that will be deleted
    54   Node_List           _control;        // List of control nodes that will be deleted
    55   Node_List           _uncommon_traps; // Uncommon traps that needs to be rewritten
    55   Node_List           _uncommon_traps; // Uncommon traps that needs to be rewritten
    56                                        // to restart at the initial JVMState.
    56                                        // to restart at the initial JVMState.
       
    57 
    57  public:
    58  public:
    58   // Mode for converting arguments to Strings
    59   // Mode for converting arguments to Strings
    59   enum {
    60   enum {
    60     StringMode,
    61     StringMode,
    61     IntMode,
    62     IntMode,
    71     _stringopts(stringopts) {
    72     _stringopts(stringopts) {
    72     _arguments = new (_stringopts->C) Node(1);
    73     _arguments = new (_stringopts->C) Node(1);
    73     _arguments->del_req(0);
    74     _arguments->del_req(0);
    74   }
    75   }
    75 
    76 
       
    77   bool validate_mem_flow();
    76   bool validate_control_flow();
    78   bool validate_control_flow();
    77 
    79 
    78   void merge_add() {
    80   void merge_add() {
    79 #if 0
    81 #if 0
    80     // XXX This is place holder code for reusing an existing String
    82     // XXX This is place holder code for reusing an existing String
   187   }
   189   }
   188   void add_control(Node* ctrl) {
   190   void add_control(Node* ctrl) {
   189     assert(!_control.contains(ctrl), "only push once");
   191     assert(!_control.contains(ctrl), "only push once");
   190     _control.push(ctrl);
   192     _control.push(ctrl);
   191   }
   193   }
       
   194   void add_constructor(Node* init) {
       
   195     assert(!_constructors.contains(init), "only push once");
       
   196     _constructors.push(init);
       
   197   }
   192   CallStaticJavaNode* end() { return _end; }
   198   CallStaticJavaNode* end() { return _end; }
   193   AllocateNode* begin() { return _begin; }
   199   AllocateNode* begin() { return _begin; }
   194   Node* string_alloc() { return _string_alloc; }
   200   Node* string_alloc() { return _string_alloc; }
   195 
   201 
   196   void eliminate_unneeded_control();
   202   void eliminate_unneeded_control();
   299     } else {
   305     } else {
   300       result->append(argx, mode(x));
   306       result->append(argx, mode(x));
   301     }
   307     }
   302   }
   308   }
   303   result->set_allocation(other->_begin);
   309   result->set_allocation(other->_begin);
       
   310   for (uint i = 0; i < _constructors.size(); i++) {
       
   311     result->add_constructor(_constructors.at(i));
       
   312   }
       
   313   for (uint i = 0; i < other->_constructors.size(); i++) {
       
   314     result->add_constructor(other->_constructors.at(i));
       
   315   }
   304   result->_multiple = true;
   316   result->_multiple = true;
   305   return result;
   317   return result;
   306 }
   318 }
   307 
   319 
   308 
   320 
   508       // if this call converted into a direct string concatenation.
   520       // if this call converted into a direct string concatenation.
   509       sc->add_control(call);
   521       sc->add_control(call);
   510       sc->add_control(constructor);
   522       sc->add_control(constructor);
   511       sc->add_control(alloc);
   523       sc->add_control(alloc);
   512       sc->set_allocation(alloc);
   524       sc->set_allocation(alloc);
   513       if (sc->validate_control_flow()) {
   525       sc->add_constructor(constructor);
       
   526       if (sc->validate_control_flow() && sc->validate_mem_flow()) {
   514         return sc;
   527         return sc;
   515       } else {
   528       } else {
   516         return NULL;
   529         return NULL;
   517       }
   530       }
   518     } else if (cnode->method() == NULL) {
   531     } else if (cnode->method() == NULL) {
   618               tty->print_cr("considering stacked concats");
   631               tty->print_cr("considering stacked concats");
   619             }
   632             }
   620 #endif
   633 #endif
   621 
   634 
   622             StringConcat* merged = sc->merge(other, arg);
   635             StringConcat* merged = sc->merge(other, arg);
   623             if (merged->validate_control_flow()) {
   636             if (merged->validate_control_flow() && merged->validate_mem_flow()) {
   624 #ifndef PRODUCT
   637 #ifndef PRODUCT
   625               if (PrintOptimizeStringConcat) {
   638               if (PrintOptimizeStringConcat) {
   626                 tty->print_cr("stacking would succeed");
   639                 tty->print_cr("stacking would succeed");
   627               }
   640               }
   628 #endif
   641 #endif
   706     }
   719     }
   707   }
   720   }
   708 }
   721 }
   709 
   722 
   710 
   723 
       
   724 bool StringConcat::validate_mem_flow() {
       
   725   Compile* C = _stringopts->C;
       
   726 
       
   727   for (uint i = 0; i < _control.size(); i++) {
       
   728 #ifndef PRODUCT
       
   729     Node_List path;
       
   730 #endif
       
   731     Node* curr = _control.at(i);
       
   732     if (curr->is_Call() && curr != _begin) { // For all calls except the first allocation
       
   733       // Now here's the main invariant in our case:
       
   734       // For memory between the constructor, and appends, and toString we should only see bottom memory,
       
   735       // produced by the previous call we know about.
       
   736       if (!_constructors.contains(curr)) {
       
   737         NOT_PRODUCT(path.push(curr);)
       
   738         Node* mem = curr->in(TypeFunc::Memory);
       
   739         assert(mem != NULL, "calls should have memory edge");
       
   740         assert(!mem->is_Phi(), "should be handled by control flow validation");
       
   741         NOT_PRODUCT(path.push(mem);)
       
   742         while (mem->is_MergeMem()) {
       
   743           for (uint i = 1; i < mem->req(); i++) {
       
   744             if (i != Compile::AliasIdxBot && mem->in(i) != C->top()) {
       
   745 #ifndef PRODUCT
       
   746               if (PrintOptimizeStringConcat) {
       
   747                 tty->print("fusion has incorrect memory flow (side effects) for ");
       
   748                 _begin->jvms()->dump_spec(tty); tty->cr();
       
   749                 path.dump();
       
   750               }
       
   751 #endif
       
   752               return false;
       
   753             }
       
   754           }
       
   755           // skip through a potential MergeMem chain, linked through Bot
       
   756           mem = mem->in(Compile::AliasIdxBot);
       
   757           NOT_PRODUCT(path.push(mem);)
       
   758         }
       
   759         // now let it fall through, and see if we have a projection
       
   760         if (mem->is_Proj()) {
       
   761           // Should point to a previous known call
       
   762           Node *prev = mem->in(0);
       
   763           NOT_PRODUCT(path.push(prev);)
       
   764           if (!prev->is_Call() || !_control.contains(prev)) {
       
   765 #ifndef PRODUCT
       
   766             if (PrintOptimizeStringConcat) {
       
   767               tty->print("fusion has incorrect memory flow (unknown call) for ");
       
   768               _begin->jvms()->dump_spec(tty); tty->cr();
       
   769               path.dump();
       
   770             }
       
   771 #endif
       
   772             return false;
       
   773           }
       
   774         } else {
       
   775           assert(mem->is_Store() || mem->is_LoadStore(), err_msg_res("unexpected node type: %s", mem->Name()));
       
   776 #ifndef PRODUCT
       
   777           if (PrintOptimizeStringConcat) {
       
   778             tty->print("fusion has incorrect memory flow (unexpected source) for ");
       
   779             _begin->jvms()->dump_spec(tty); tty->cr();
       
   780             path.dump();
       
   781           }
       
   782 #endif
       
   783           return false;
       
   784         }
       
   785       } else {
       
   786         // For memory that feeds into constructors it's more complicated.
       
   787         // However the advantage is that any side effect that happens between the Allocate/Initialize and
       
   788         // the constructor will have to be control-dependent on Initialize.
       
   789         // So we actually don't have to do anything, since it's going to be caught by the control flow
       
   790         // analysis.
       
   791 #ifdef ASSERT
       
   792         // Do a quick verification of the control pattern between the constructor and the initialize node
       
   793         assert(curr->is_Call(), "constructor should be a call");
       
   794         // Go up the control starting from the constructor call
       
   795         Node* ctrl = curr->in(0);
       
   796         IfNode* iff = NULL;
       
   797         RegionNode* copy = NULL;
       
   798 
       
   799         while (true) {
       
   800           // skip known check patterns
       
   801           if (ctrl->is_Region()) {
       
   802             if (ctrl->as_Region()->is_copy()) {
       
   803               copy = ctrl->as_Region();
       
   804               ctrl = copy->is_copy();
       
   805             } else { // a cast
       
   806               assert(ctrl->req() == 3 &&
       
   807                      ctrl->in(1) != NULL && ctrl->in(1)->is_Proj() &&
       
   808                      ctrl->in(2) != NULL && ctrl->in(2)->is_Proj() &&
       
   809                      ctrl->in(1)->in(0) == ctrl->in(2)->in(0) &&
       
   810                      ctrl->in(1)->in(0) != NULL && ctrl->in(1)->in(0)->is_If(),
       
   811                      "must be a simple diamond");
       
   812               Node* true_proj = ctrl->in(1)->is_IfTrue() ? ctrl->in(1) : ctrl->in(2);
       
   813               for (SimpleDUIterator i(true_proj); i.has_next(); i.next()) {
       
   814                 Node* use = i.get();
       
   815                 assert(use == ctrl || use->is_ConstraintCast(),
       
   816                        err_msg_res("unexpected user: %s", use->Name()));
       
   817               }
       
   818 
       
   819               iff = ctrl->in(1)->in(0)->as_If();
       
   820               ctrl = iff->in(0);
       
   821             }
       
   822           } else if (ctrl->is_IfTrue()) { // null checks, class checks
       
   823             iff = ctrl->in(0)->as_If();
       
   824             assert(iff->is_If(), "must be if");
       
   825             // Verify that the other arm is an uncommon trap
       
   826             Node* otherproj = iff->proj_out(1 - ctrl->as_Proj()->_con);
       
   827             CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava();
       
   828             assert(strcmp(call->_name, "uncommon_trap") == 0, "must be uncommond trap");
       
   829             ctrl = iff->in(0);
       
   830           } else {
       
   831             break;
       
   832           }
       
   833         }
       
   834 
       
   835         assert(ctrl->is_Proj(), "must be a projection");
       
   836         assert(ctrl->in(0)->is_Initialize(), "should be initialize");
       
   837         for (SimpleDUIterator i(ctrl); i.has_next(); i.next()) {
       
   838           Node* use = i.get();
       
   839           assert(use == copy || use == iff || use == curr || use->is_CheckCastPP() || use->is_Load(),
       
   840                  err_msg_res("unexpected user: %s", use->Name()));
       
   841         }
       
   842 #endif // ASSERT
       
   843       }
       
   844     }
       
   845   }
       
   846 
       
   847 #ifndef PRODUCT
       
   848   if (PrintOptimizeStringConcat) {
       
   849     tty->print("fusion has correct memory flow for ");
       
   850     _begin->jvms()->dump_spec(tty); tty->cr();
       
   851     tty->cr();
       
   852   }
       
   853 #endif
       
   854   return true;
       
   855 }
       
   856 
   711 bool StringConcat::validate_control_flow() {
   857 bool StringConcat::validate_control_flow() {
   712   // We found all the calls and arguments now lets see if it's
   858   // We found all the calls and arguments now lets see if it's
   713   // safe to transform the graph as we would expect.
   859   // safe to transform the graph as we would expect.
   714 
   860 
   715   // Check to see if this resulted in too many uncommon traps previously
   861   // Check to see if this resulted in too many uncommon traps previously
   751     } else {
   897     } else {
   752       ShouldNotReachHere();
   898       ShouldNotReachHere();
   753     }
   899     }
   754   }
   900   }
   755 
   901 
   756   // Skip backwards through the control checking for unexpected contro flow
   902   // Skip backwards through the control checking for unexpected control flow
   757   Node* ptr = _end;
   903   Node* ptr = _end;
   758   bool fail = false;
   904   bool fail = false;
   759   while (ptr != _begin) {
   905   while (ptr != _begin) {
   760     if (ptr->is_Call() && ctrl_path.member(ptr)) {
   906     if (ptr->is_Call() && ctrl_path.member(ptr)) {
   761       ptr = ptr->in(0);
   907       ptr = ptr->in(0);
   934 
  1080 
   935 #ifndef PRODUCT
  1081 #ifndef PRODUCT
   936   if (PrintOptimizeStringConcat && !fail) {
  1082   if (PrintOptimizeStringConcat && !fail) {
   937     ttyLocker ttyl;
  1083     ttyLocker ttyl;
   938     tty->cr();
  1084     tty->cr();
   939     tty->print("fusion would succeed (%d %d) for ", null_check_count, _uncommon_traps.size());
  1085     tty->print("fusion has correct control flow (%d %d) for ", null_check_count, _uncommon_traps.size());
   940     _begin->jvms()->dump_spec(tty); tty->cr();
  1086     _begin->jvms()->dump_spec(tty); tty->cr();
   941     for (int i = 0; i < num_arguments(); i++) {
  1087     for (int i = 0; i < num_arguments(); i++) {
   942       argument(i)->dump();
  1088       argument(i)->dump();
   943     }
  1089     }
   944     _control.dump();
  1090     _control.dump();