Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/stringopts.cpp @ 2090:2ddb2fab82cb
7009359: HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected
Summary: Bailout StringConcat optimization if null is passed to StringBuffer constructor.
Reviewed-by: iveresov
author | kvn |
---|---|
date | Tue, 28 Dec 2010 17:34:02 -0800 |
parents | f95d63e2154a |
children | b099aaf51bf8 9dc311b8473e |
comparison
equal
deleted
inserted
replaced
2089:037c727f35fb | 2090:2ddb2fab82cb |
---|---|
57 public: | 57 public: |
58 // Mode for converting arguments to Strings | 58 // Mode for converting arguments to Strings |
59 enum { | 59 enum { |
60 StringMode, | 60 StringMode, |
61 IntMode, | 61 IntMode, |
62 CharMode | 62 CharMode, |
63 StringNullCheckMode | |
63 }; | 64 }; |
64 | 65 |
65 StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): | 66 StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): |
66 _end(end), | 67 _end(end), |
67 _begin(NULL), | 68 _begin(NULL), |
112 _mode.insert_before(0, mode); | 113 _mode.insert_before(0, mode); |
113 } | 114 } |
114 void push_string(Node* value) { | 115 void push_string(Node* value) { |
115 push(value, StringMode); | 116 push(value, StringMode); |
116 } | 117 } |
118 void push_string_null_check(Node* value) { | |
119 push(value, StringNullCheckMode); | |
120 } | |
117 void push_int(Node* value) { | 121 void push_int(Node* value) { |
118 push(value, IntMode); | 122 push(value, IntMode); |
119 } | 123 } |
120 void push_char(Node* value) { | 124 void push_char(Node* value) { |
121 push(value, CharMode); | 125 push(value, CharMode); |
414 sig == ciSymbol::int_void_signature() || | 418 sig == ciSymbol::int_void_signature() || |
415 sig == ciSymbol::string_void_signature()) { | 419 sig == ciSymbol::string_void_signature()) { |
416 if (sig == ciSymbol::string_void_signature()) { | 420 if (sig == ciSymbol::string_void_signature()) { |
417 // StringBuilder(String) so pick this up as the first argument | 421 // StringBuilder(String) so pick this up as the first argument |
418 assert(use->in(TypeFunc::Parms + 1) != NULL, "what?"); | 422 assert(use->in(TypeFunc::Parms + 1) != NULL, "what?"); |
419 sc->push_string(use->in(TypeFunc::Parms + 1)); | 423 const Type* type = _gvn->type(use->in(TypeFunc::Parms + 1)); |
424 if (type == TypePtr::NULL_PTR) { | |
425 // StringBuilder(null) throws exception. | |
426 #ifndef PRODUCT | |
427 if (PrintOptimizeStringConcat) { | |
428 tty->print("giving up because StringBuilder(null) throws exception"); | |
429 alloc->jvms()->dump_spec(tty); tty->cr(); | |
430 } | |
431 #endif | |
432 return NULL; | |
433 } | |
434 // StringBuilder(str) argument needs null check. | |
435 sc->push_string_null_check(use->in(TypeFunc::Parms + 1)); | |
420 } | 436 } |
421 // The int variant takes an initial size for the backing | 437 // The int variant takes an initial size for the backing |
422 // array so just treat it like the void version. | 438 // array so just treat it like the void version. |
423 constructor = use; | 439 constructor = use; |
424 } else { | 440 } else { |
434 if (constructor == NULL) { | 450 if (constructor == NULL) { |
435 // couldn't find constructor | 451 // couldn't find constructor |
436 #ifndef PRODUCT | 452 #ifndef PRODUCT |
437 if (PrintOptimizeStringConcat) { | 453 if (PrintOptimizeStringConcat) { |
438 tty->print("giving up because couldn't find constructor "); | 454 tty->print("giving up because couldn't find constructor "); |
439 alloc->jvms()->dump_spec(tty); | 455 alloc->jvms()->dump_spec(tty); tty->cr(); |
440 } | 456 } |
441 #endif | 457 #endif |
442 break; | 458 break; |
443 } | 459 } |
444 | 460 |
1266 length = __ AddI(length, string_size); | 1282 length = __ AddI(length, string_size); |
1267 | 1283 |
1268 // Cache this value for the use by int_toString | 1284 // Cache this value for the use by int_toString |
1269 string_sizes->init_req(argi, string_size); | 1285 string_sizes->init_req(argi, string_size); |
1270 break; | 1286 break; |
1287 } | |
1288 case StringConcat::StringNullCheckMode: { | |
1289 const Type* type = kit.gvn().type(arg); | |
1290 assert(type != TypePtr::NULL_PTR, "missing check"); | |
1291 if (!type->higher_equal(TypeInstPtr::NOTNULL)) { | |
1292 // Null check with uncommont trap since | |
1293 // StringBuilder(null) throws exception. | |
1294 // Use special uncommon trap instead of | |
1295 // calling normal do_null_check(). | |
1296 Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); | |
1297 IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); | |
1298 overflow->add_req(__ IfFalse(iff)); | |
1299 Node* notnull = __ IfTrue(iff); | |
1300 kit.set_control(notnull); // set control for the cast_not_null | |
1301 arg = kit.cast_not_null(arg, false); | |
1302 sc->set_argument(argi, arg); | |
1303 } | |
1304 assert(kit.gvn().type(arg)->higher_equal(TypeInstPtr::NOTNULL), "sanity"); | |
1305 // Fallthrough to add string length. | |
1271 } | 1306 } |
1272 case StringConcat::StringMode: { | 1307 case StringConcat::StringMode: { |
1273 const Type* type = kit.gvn().type(arg); | 1308 const Type* type = kit.gvn().type(arg); |
1274 if (type == TypePtr::NULL_PTR) { | 1309 if (type == TypePtr::NULL_PTR) { |
1275 // replace the argument with the null checked version | 1310 // replace the argument with the null checked version |
1326 | 1361 |
1327 { | 1362 { |
1328 // Hook | 1363 // Hook |
1329 PreserveJVMState pjvms(&kit); | 1364 PreserveJVMState pjvms(&kit); |
1330 kit.set_control(overflow); | 1365 kit.set_control(overflow); |
1366 C->record_for_igvn(overflow); | |
1331 kit.uncommon_trap(Deoptimization::Reason_intrinsic, | 1367 kit.uncommon_trap(Deoptimization::Reason_intrinsic, |
1332 Deoptimization::Action_make_not_entrant); | 1368 Deoptimization::Action_make_not_entrant); |
1333 } | 1369 } |
1334 | 1370 |
1335 // length now contains the number of characters needed for the | 1371 // length now contains the number of characters needed for the |
1361 // getChars words backwards so pass the ending point as well as the start | 1397 // getChars words backwards so pass the ending point as well as the start |
1362 int_getChars(kit, arg, char_array, start, end); | 1398 int_getChars(kit, arg, char_array, start, end); |
1363 start = end; | 1399 start = end; |
1364 break; | 1400 break; |
1365 } | 1401 } |
1402 case StringConcat::StringNullCheckMode: | |
1366 case StringConcat::StringMode: { | 1403 case StringConcat::StringMode: { |
1367 start = copy_string(kit, arg, char_array, start); | 1404 start = copy_string(kit, arg, char_array, start); |
1368 break; | 1405 break; |
1369 } | 1406 } |
1370 case StringConcat::CharMode: { | 1407 case StringConcat::CharMode: { |