1.1 --- a/src/share/vm/opto/stringopts.cpp Mon Dec 27 21:51:31 2010 -0800 1.2 +++ b/src/share/vm/opto/stringopts.cpp Tue Dec 28 17:34:02 2010 -0800 1.3 @@ -59,7 +59,8 @@ 1.4 enum { 1.5 StringMode, 1.6 IntMode, 1.7 - CharMode 1.8 + CharMode, 1.9 + StringNullCheckMode 1.10 }; 1.11 1.12 StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): 1.13 @@ -114,6 +115,9 @@ 1.14 void push_string(Node* value) { 1.15 push(value, StringMode); 1.16 } 1.17 + void push_string_null_check(Node* value) { 1.18 + push(value, StringNullCheckMode); 1.19 + } 1.20 void push_int(Node* value) { 1.21 push(value, IntMode); 1.22 } 1.23 @@ -416,7 +420,19 @@ 1.24 if (sig == ciSymbol::string_void_signature()) { 1.25 // StringBuilder(String) so pick this up as the first argument 1.26 assert(use->in(TypeFunc::Parms + 1) != NULL, "what?"); 1.27 - sc->push_string(use->in(TypeFunc::Parms + 1)); 1.28 + const Type* type = _gvn->type(use->in(TypeFunc::Parms + 1)); 1.29 + if (type == TypePtr::NULL_PTR) { 1.30 + // StringBuilder(null) throws exception. 1.31 +#ifndef PRODUCT 1.32 + if (PrintOptimizeStringConcat) { 1.33 + tty->print("giving up because StringBuilder(null) throws exception"); 1.34 + alloc->jvms()->dump_spec(tty); tty->cr(); 1.35 + } 1.36 +#endif 1.37 + return NULL; 1.38 + } 1.39 + // StringBuilder(str) argument needs null check. 1.40 + sc->push_string_null_check(use->in(TypeFunc::Parms + 1)); 1.41 } 1.42 // The int variant takes an initial size for the backing 1.43 // array so just treat it like the void version. 1.44 @@ -436,7 +452,7 @@ 1.45 #ifndef PRODUCT 1.46 if (PrintOptimizeStringConcat) { 1.47 tty->print("giving up because couldn't find constructor "); 1.48 - alloc->jvms()->dump_spec(tty); 1.49 + alloc->jvms()->dump_spec(tty); tty->cr(); 1.50 } 1.51 #endif 1.52 break; 1.53 @@ -1269,6 +1285,25 @@ 1.54 string_sizes->init_req(argi, string_size); 1.55 break; 1.56 } 1.57 + case StringConcat::StringNullCheckMode: { 1.58 + const Type* type = kit.gvn().type(arg); 1.59 + assert(type != TypePtr::NULL_PTR, "missing check"); 1.60 + if (!type->higher_equal(TypeInstPtr::NOTNULL)) { 1.61 + // Null check with uncommont trap since 1.62 + // StringBuilder(null) throws exception. 1.63 + // Use special uncommon trap instead of 1.64 + // calling normal do_null_check(). 1.65 + Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); 1.66 + IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); 1.67 + overflow->add_req(__ IfFalse(iff)); 1.68 + Node* notnull = __ IfTrue(iff); 1.69 + kit.set_control(notnull); // set control for the cast_not_null 1.70 + arg = kit.cast_not_null(arg, false); 1.71 + sc->set_argument(argi, arg); 1.72 + } 1.73 + assert(kit.gvn().type(arg)->higher_equal(TypeInstPtr::NOTNULL), "sanity"); 1.74 + // Fallthrough to add string length. 1.75 + } 1.76 case StringConcat::StringMode: { 1.77 const Type* type = kit.gvn().type(arg); 1.78 if (type == TypePtr::NULL_PTR) { 1.79 @@ -1328,6 +1363,7 @@ 1.80 // Hook 1.81 PreserveJVMState pjvms(&kit); 1.82 kit.set_control(overflow); 1.83 + C->record_for_igvn(overflow); 1.84 kit.uncommon_trap(Deoptimization::Reason_intrinsic, 1.85 Deoptimization::Action_make_not_entrant); 1.86 } 1.87 @@ -1363,6 +1399,7 @@ 1.88 start = end; 1.89 break; 1.90 } 1.91 + case StringConcat::StringNullCheckMode: 1.92 case StringConcat::StringMode: { 1.93 start = copy_string(kit, arg, char_array, start); 1.94 break;