Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/library_call.cpp @ 2320:41d4973cf100
6942326: x86 code in string_indexof() could read beyond reserved heap space
Summary: copy small (<8) strings on stack if str+16 crosses a page boundary and load from stack into XMM. Back up pointer when loading string's tail.
Reviewed-by: never
author | kvn |
---|---|
date | Sat, 26 Feb 2011 12:10:54 -0800 |
parents | f95d63e2154a |
children | 0ac769a57c64 |
comparison
equal
deleted
inserted
replaced
2319:8190d4b75e09 | 2320:41d4973cf100 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1999, 2011, 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. |
1191 Node *receiver = pop(); | 1191 Node *receiver = pop(); |
1192 | 1192 |
1193 Node* result; | 1193 Node* result; |
1194 // Disable the use of pcmpestri until it can be guaranteed that | 1194 // Disable the use of pcmpestri until it can be guaranteed that |
1195 // the load doesn't cross into the uncommited space. | 1195 // the load doesn't cross into the uncommited space. |
1196 if (false && Matcher::has_match_rule(Op_StrIndexOf) && | 1196 if (Matcher::has_match_rule(Op_StrIndexOf) && |
1197 UseSSE42Intrinsics) { | 1197 UseSSE42Intrinsics) { |
1198 // Generate SSE4.2 version of indexOf | 1198 // Generate SSE4.2 version of indexOf |
1199 // We currently only have match rules that use SSE4.2 | 1199 // We currently only have match rules that use SSE4.2 |
1200 | 1200 |
1201 // Null check on self without removing any arguments. The argument | 1201 // Null check on self without removing any arguments. The argument |
1209 | 1209 |
1210 if (stopped()) { | 1210 if (stopped()) { |
1211 return true; | 1211 return true; |
1212 } | 1212 } |
1213 | 1213 |
1214 ciInstanceKlass* str_klass = env()->String_klass(); | |
1215 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(str_klass); | |
1216 | |
1214 // Make the merge point | 1217 // Make the merge point |
1215 RegionNode* result_rgn = new (C, 3) RegionNode(3); | 1218 RegionNode* result_rgn = new (C, 4) RegionNode(4); |
1216 Node* result_phi = new (C, 3) PhiNode(result_rgn, TypeInt::INT); | 1219 Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT); |
1217 Node* no_ctrl = NULL; | 1220 Node* no_ctrl = NULL; |
1218 | |
1219 ciInstanceKlass* klass = env()->String_klass(); | |
1220 const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); | |
1221 | 1221 |
1222 // Get counts for string and substr | 1222 // Get counts for string and substr |
1223 Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset); | 1223 Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset); |
1224 Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); | 1224 Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); |
1225 | 1225 |
1234 result_phi->init_req(2, intcon(-1)); | 1234 result_phi->init_req(2, intcon(-1)); |
1235 result_rgn->init_req(2, if_gt); | 1235 result_rgn->init_req(2, if_gt); |
1236 } | 1236 } |
1237 | 1237 |
1238 if (!stopped()) { | 1238 if (!stopped()) { |
1239 // Check for substr count == 0 | |
1240 cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, intcon(0)) ); | |
1241 bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::eq) ); | |
1242 Node* if_zero = generate_slow_guard(bol, NULL); | |
1243 if (if_zero != NULL) { | |
1244 result_phi->init_req(3, intcon(0)); | |
1245 result_rgn->init_req(3, if_zero); | |
1246 } | |
1247 } | |
1248 | |
1249 if (!stopped()) { | |
1239 result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt); | 1250 result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt); |
1240 result_phi->init_req(1, result); | 1251 result_phi->init_req(1, result); |
1241 result_rgn->init_req(1, control()); | 1252 result_rgn->init_req(1, control()); |
1242 } | 1253 } |
1243 set_control(_gvn.transform(result_rgn)); | 1254 set_control(_gvn.transform(result_rgn)); |
1244 record_for_igvn(result_rgn); | 1255 record_for_igvn(result_rgn); |
1245 result = _gvn.transform(result_phi); | 1256 result = _gvn.transform(result_phi); |
1246 | 1257 |
1247 } else { //Use LibraryCallKit::string_indexOf | 1258 } else { // Use LibraryCallKit::string_indexOf |
1248 // don't intrinsify is argument isn't a constant string. | 1259 // don't intrinsify if argument isn't a constant string. |
1249 if (!argument->is_Con()) { | 1260 if (!argument->is_Con()) { |
1250 return false; | 1261 return false; |
1251 } | 1262 } |
1252 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); | 1263 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); |
1253 if (str_type == NULL) { | 1264 if (str_type == NULL) { |
1279 _sp += 2; | 1290 _sp += 2; |
1280 receiver = do_null_check(receiver, T_OBJECT); | 1291 receiver = do_null_check(receiver, T_OBJECT); |
1281 // No null check on the argument is needed since it's a constant String oop. | 1292 // No null check on the argument is needed since it's a constant String oop. |
1282 _sp -= 2; | 1293 _sp -= 2; |
1283 if (stopped()) { | 1294 if (stopped()) { |
1284 return true; | 1295 return true; |
1285 } | 1296 } |
1286 | 1297 |
1287 // The null string as a pattern always returns 0 (match at beginning of string) | 1298 // The null string as a pattern always returns 0 (match at beginning of string) |
1288 if (c == 0) { | 1299 if (c == 0) { |
1289 push(intcon(0)); | 1300 push(intcon(0)); |