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));